encommon 0.4.1__py3-none-any.whl → 0.6.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.
encommon/config/config.py CHANGED
@@ -155,9 +155,9 @@ class Config:
155
155
  self,
156
156
  ) -> Params:
157
157
  """
158
- Return the configuration in the object format for files.
158
+ Return the Pydantic model containing the configuration.
159
159
 
160
- :returns: Configuration in the object format for files.
160
+ :returns: Pydantic model containing the configuration.
161
161
  """
162
162
 
163
163
  if self.__params is not None:
encommon/config/params.py CHANGED
@@ -20,7 +20,9 @@ class ConfigParams(BaseModel, extra='forbid'):
20
20
  """
21
21
  Process and validate the common configuration parameters.
22
22
 
23
+ :param paths: Complete or relative path to config paths.
23
24
  :param data: Keyword arguments passed to Pydantic model.
25
+ This parameter is picked up by autodoc, please ignore.
24
26
  """
25
27
 
26
28
  paths: Optional[list[str]] = None
@@ -31,7 +33,11 @@ class LoggerParams(BaseModel, extra='forbid'):
31
33
  """
32
34
  Process and validate the common configuration parameters.
33
35
 
36
+ :param stdo_level: Minimum log message severity level.
37
+ :param file_level: Minimum log message severity level.
38
+ :param file_path: Enables writing to the filesystem path.
34
39
  :param data: Keyword arguments passed to Pydantic model.
40
+ This parameter is picked up by autodoc, please ignore.
35
41
  """
36
42
 
37
43
  stdo_level: Optional[LOGLEVELS] = None
@@ -44,7 +50,11 @@ class Params(BaseModel, extra='forbid'):
44
50
  """
45
51
  Process and validate the common configuration parameters.
46
52
 
53
+ :param enconfig: Configuration for the `.Config` object.
54
+ :param enlogger: Configuration for the `.Logger` object.
55
+ :param encrypts: Configuration for the `.Crypts` object.
47
56
  :param data: Keyword arguments passed to Pydantic model.
57
+ This parameter is picked up by autodoc, please ignore.
48
58
  """
49
59
 
50
60
  enconfig: Optional[ConfigParams] = None
@@ -25,7 +25,7 @@ SAMPLES = (
25
25
 
26
26
 
27
27
 
28
- def test_Config(
28
+ def test_Config( # noqa: CFQ001
29
29
  config_path: Path,
30
30
  ) -> None:
31
31
  """
@@ -108,6 +108,26 @@ def test_Config(
108
108
  assert sample == expect
109
109
 
110
110
 
111
+ _params1 = config.params
112
+ _params2 = config.params
113
+
114
+ assert _params1 is _params2
115
+
116
+ sample = load_sample(
117
+ path=SAMPLES.joinpath('params.json'),
118
+ update=ENPYRWS,
119
+ content=_params1.model_dump(),
120
+ replace={
121
+ 'config_path': str(config_path)})
122
+
123
+ expect = prep_sample(
124
+ content=_params2.model_dump(),
125
+ replace={
126
+ 'config_path': str(config_path)})
127
+
128
+ assert sample == expect
129
+
130
+
111
131
  logger = config.logger
112
132
 
113
133
  assert isinstance(logger, Logger)
@@ -21,6 +21,7 @@ def config_path(
21
21
  Construct the directory and files needed for the tests.
22
22
 
23
23
  :param tmp_path: pytest object for temporal filesystem.
24
+ :returns: New resolved filesystem path object instance.
24
25
  """
25
26
 
26
27
 
@@ -40,4 +41,4 @@ def config_path(
40
41
  .write_text('name: Tony Stark'))
41
42
 
42
43
 
43
- return tmp_path
44
+ return tmp_path.resolve()
encommon/times/common.py CHANGED
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
20
20
 
21
21
 
22
22
  NUMERISH = compile(r'^\-?\d+(\.\d+)?$')
23
- SNAPABLE = compile(r'^\-|\+[\d\@a-z]+$')
23
+ SNAPABLE = compile(r'^(\-|\+)[\d\@a-z\-\+]+$')
24
24
  STRINGNOW = {'None', 'null', 'now'}
25
25
 
26
26
  NUMERIC = Union[int, float]
@@ -7,6 +7,7 @@ is permitted, for more information consult the project license file.
7
7
 
8
8
 
9
9
 
10
+ from pathlib import Path
10
11
  from time import sleep
11
12
 
12
13
  from pytest import raises
@@ -25,8 +26,10 @@ def test_Timers() -> None:
25
26
  attrs = list(timers.__dict__)
26
27
 
27
28
  assert attrs == [
28
- '_Timers__timing',
29
- '_Timers__caches']
29
+ '_Timers__timers',
30
+ '_Timers__cache_file',
31
+ '_Timers__cache_name',
32
+ '_Timers__cache_dict']
30
33
 
31
34
 
32
35
  assert repr(timers).startswith(
@@ -36,7 +39,11 @@ def test_Timers() -> None:
36
39
  '<encommon.times.timers.Timers')
37
40
 
38
41
 
39
- assert timers.timing == {'one': 1}
42
+ assert timers.timers == {'one': 1}
43
+ assert timers.cache_file is not None
44
+ assert len(timers.cache_dict) == 1
45
+ assert timers.cache_name is not None
46
+
40
47
 
41
48
  assert not timers.ready('one')
42
49
  sleep(1.1)
@@ -50,6 +57,42 @@ def test_Timers() -> None:
50
57
 
51
58
 
52
59
 
60
+ def test_Timers_cache(
61
+ tmp_path: Path,
62
+ ) -> None:
63
+ """
64
+ Perform various tests associated with relevant routines.
65
+
66
+ :param tmp_path: pytest object for temporal filesystem.
67
+ """
68
+
69
+ cache_file = (
70
+ f'{tmp_path}/timers.db')
71
+
72
+ timers1 = Timers(
73
+ timers={'one': 1},
74
+ cache_file=cache_file)
75
+
76
+ assert not timers1.ready('one')
77
+
78
+ sleep(0.75)
79
+
80
+ timers2 = Timers(
81
+ timers={'one': 1},
82
+ cache_file=cache_file)
83
+
84
+ assert not timers1.ready('one')
85
+ assert not timers2.ready('one')
86
+
87
+ sleep(0.25)
88
+
89
+ timers2.load_cache()
90
+
91
+ assert timers1.ready('one')
92
+ assert timers2.ready('one')
93
+
94
+
95
+
53
96
  def test_Timers_raises() -> None:
54
97
  """
55
98
  Perform various tests associated with relevant routines.
encommon/times/timers.py CHANGED
@@ -7,59 +7,155 @@ is permitted, for more information consult the project license file.
7
7
 
8
8
 
9
9
 
10
+ from sqlite3 import connect as SQLite
10
11
  from typing import Optional
12
+ from typing import TYPE_CHECKING
11
13
 
12
14
  from .common import NUMERIC
13
15
  from .common import PARSABLE
14
16
  from .times import Times
15
17
 
18
+ if TYPE_CHECKING:
19
+ from sqlite3 import Connection
20
+
21
+
22
+ TABLE = (
23
+ """
24
+ create table
25
+ if not exists
26
+ {0} (
27
+ "unique" text not null,
28
+ "update" text not null,
29
+ primary key ("unique"));
30
+ """) # noqa: LIT003
31
+
16
32
 
17
33
 
18
34
  class Timers:
19
35
  """
20
36
  Track timers on unique key and determine when to proceed.
21
37
 
38
+ .. warning::
39
+ This class will use an in-memory database for cache,
40
+ unless a cache file is explicity defined.
41
+
22
42
  .. testsetup::
23
43
  >>> from time import sleep
24
44
 
25
45
  Example
26
46
  -------
27
- >>> timing = {'test': 1}
28
- >>> timers = Timers(timing)
29
- >>> timers.ready('test')
47
+ >>> timers = Timers({'one': 1})
48
+ >>> timers.ready('one')
30
49
  False
31
50
  >>> sleep(1)
32
- >>> timers.ready('test')
51
+ >>> timers.ready('one')
33
52
  True
34
53
 
35
- :param timing: Seconds that are used for each of timers.
54
+ :param timers: Seconds that are used for each of timers.
55
+ :param cache_file: Optional path to SQLite database for
56
+ cache. This will allow for use between executions.
57
+ :param cache_name: Optional override default table name.
36
58
  """
37
59
 
38
- __timing: dict[str, float]
39
- __caches: dict[str, Times]
60
+ __timers: dict[str, float]
61
+ __cache_file: 'Connection'
62
+ __cache_name: str
63
+ __cache_dict: dict[str, Times]
40
64
 
41
65
 
42
66
  def __init__(
43
67
  self,
44
- timing: Optional[dict[str, NUMERIC]] = None,
68
+ timers: Optional[dict[str, NUMERIC]] = None,
69
+ cache_file: str = ':memory:',
70
+ cache_name: str = 'encommon_timers',
45
71
  ) -> None:
46
72
  """
47
73
  Initialize instance for class using provided parameters.
48
74
  """
49
75
 
50
- timing = timing or {}
76
+ timers = timers or {}
51
77
 
52
- self.__timing = {
78
+
79
+ self.__timers = {
53
80
  k: float(v)
54
- for k, v in timing.items()}
81
+ for k, v in
82
+ timers.items()}
83
+
84
+
85
+ cached = SQLite(cache_file)
86
+
87
+ cached.execute(
88
+ TABLE.format(cache_name))
55
89
 
56
- self.__caches = {
90
+ cached.commit()
91
+
92
+ self.__cache_file = cached
93
+ self.__cache_name = cache_name
94
+
95
+
96
+ self.__cache_dict = {
57
97
  x: Times()
58
- for x in self.__timing}
98
+ for x in
99
+ self.__timers}
100
+
101
+
102
+ self.load_cache()
103
+ self.save_cache()
104
+
105
+
106
+ def load_cache(
107
+ self,
108
+ ) -> None:
109
+ """
110
+ Load the timers cache from the database into attribute.
111
+ """
112
+
113
+ cached = self.__cache_file
114
+ table = self.__cache_name
115
+ cachem = self.__cache_dict
116
+
117
+ cursor = cached.execute(
118
+ f'select * from {table}'
119
+ ' order by "unique" asc')
120
+
121
+ records = cursor.fetchall()
122
+
123
+ for record in records:
124
+
125
+ unique = record[0]
126
+ update = record[1]
127
+
128
+ times = Times(update)
129
+
130
+ cachem[unique] = times
131
+
132
+
133
+ def save_cache(
134
+ self,
135
+ ) -> None:
136
+ """
137
+ Save the timers cache from the attribute into database.
138
+ """
139
+
140
+ cached = self.__cache_file
141
+ table = self.__cache_name
142
+ cachem = self.__cache_dict
143
+
144
+ insert = [
145
+ (k, str(v)) for k, v
146
+ in cachem.items()]
147
+
148
+ cached.executemany(
149
+ (f'replace into {table}'
150
+ ' ("unique", "update")'
151
+ ' values (?, ?)'),
152
+ tuple(insert))
153
+
154
+ cached.commit()
59
155
 
60
156
 
61
157
  @property
62
- def timing(
158
+ def timers(
63
159
  self,
64
160
  ) -> dict[str, float]:
65
161
  """
@@ -68,7 +164,46 @@ class Timers:
68
164
  :returns: Property for attribute from the class instance.
69
165
  """
70
166
 
71
- return dict(self.__timing)
167
+ return dict(self.__timers)
168
+
169
+
170
+ @property
171
+ def cache_file(
172
+ self,
173
+ ) -> 'Connection':
174
+ """
175
+ Return the property for attribute from the class instance.
176
+
177
+ :returns: Property for attribute from the class instance.
178
+ """
179
+
180
+ return self.__cache_file
181
+
182
+
183
+ @property
184
+ def cache_dict(
185
+ self,
186
+ ) -> dict[str, Times]:
187
+ """
188
+ Return the property for attribute from the class instance.
189
+
190
+ :returns: Property for attribute from the class instance.
191
+ """
192
+
193
+ return dict(self.__cache_dict)
194
+
195
+
196
+ @property
197
+ def cache_name(
198
+ self,
199
+ ) -> str:
200
+ """
201
+ Return the property for attribute from the class instance.
202
+
203
+ :returns: Property for attribute from the class instance.
204
+ """
205
+
206
+ return self.__cache_name
72
207
 
73
208
 
74
209
  def ready(
@@ -79,20 +214,24 @@ class Timers:
79
214
  """
80
215
  Determine whether or not the appropriate time has passed.
81
216
 
217
+ .. note::
218
+ For performance reasons, this method will not notice
219
+ changes within the database unless refreshed first.
220
+
82
221
  :param unique: Unique identifier for the timer in mapping.
83
222
  :param update: Determines whether or not time is updated.
84
223
  """
85
224
 
86
- timer = self.__timing
87
- cache = self.__caches
225
+ timers = self.__timers
226
+ caches = self.__cache_dict
88
227
 
89
- if unique not in cache:
228
+ if unique not in caches:
90
229
  raise ValueError('unique')
91
230
 
92
- _cache = cache[unique]
93
- _timer = timer[unique]
231
+ cache = caches[unique]
232
+ timer = timers[unique]
94
233
 
95
- ready = _cache.elapsed >= _timer
234
+ ready = cache.elapsed >= timer
96
235
 
97
236
  if ready and update:
98
237
  self.update(unique)
@@ -112,12 +251,14 @@ class Timers:
112
251
  :param started: Override the start time for timer value.
113
252
  """
114
253
 
115
- cache = self.__caches
254
+ caches = self.__cache_dict
116
255
 
117
- if unique not in cache:
256
+ if unique not in caches:
118
257
  raise ValueError('unique')
119
258
 
120
- cache[unique] = Times(started)
259
+ caches[unique] = Times(started)
260
+
261
+ self.save_cache()
121
262
 
122
263
 
123
264
  def create(
@@ -130,15 +271,17 @@ class Timers:
130
271
  Update the existing timer from mapping within the cache.
131
272
 
132
273
  :param unique: Unique identifier for the timer in mapping.
133
- :param started: Determines when the time starts for timer.
134
274
  :param minimum: Determines minimum seconds that must pass.
275
+ :param started: Determines when the time starts for timer.
135
276
  """
136
277
 
137
- timer = self.__timing
138
- cache = self.__caches
278
+ timers = self.__timers
279
+ caches = self.__cache_dict
139
280
 
140
- if unique in cache:
281
+ if unique in caches:
141
282
  raise ValueError('unique')
142
283
 
143
- timer[unique] = float(minimum)
144
- cache[unique] = Times(started)
284
+ timers[unique] = float(minimum)
285
+ caches[unique] = Times(started)
286
+
287
+ self.save_cache()
@@ -8,10 +8,14 @@ is permitted, for more information consult the project license file.
8
8
 
9
9
 
10
10
  from .dicts import merge_dicts
11
+ from .dicts import sort_dict
11
12
  from .empty import Empty
13
+ from .strings import striplower
12
14
 
13
15
 
14
16
 
15
17
  __all__ = [
16
18
  'Empty',
17
- 'merge_dicts']
19
+ 'merge_dicts',
20
+ 'sort_dict',
21
+ 'striplower']
encommon/types/dicts.py CHANGED
@@ -58,3 +58,29 @@ def merge_dicts(
58
58
 
59
59
  elif force is True:
60
60
  dict1[key] = value
61
+
62
+
63
+
64
+ def sort_dict(
65
+ value: dict[Any, Any],
66
+ reverse: bool = False,
67
+ ) -> dict[Any, Any]:
68
+ """
69
+ Sort the keys within the dictionary and return new one.
70
+
71
+ Example
72
+ -------
73
+ >>> foo = {'b': 'be', 'a': 'ey'}
74
+ >>> sort_dict(foo)
75
+ {'a': 'ey', 'b': 'be'}
76
+ >>> sort_dict(foo, True)
77
+ {'b': 'be', 'a': 'ey'}
78
+
79
+ :param value: Dictionary whose keys are sorted into new.
80
+ :param reverse: Optionally reverse the sort direction.
81
+ :returns: New dictionary with keys sorted alphabetical.
82
+ """
83
+
84
+ return dict(sorted(
85
+ value.items(),
86
+ reverse=reverse))
@@ -0,0 +1,25 @@
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
+ def striplower(
11
+ value: str,
12
+ ) -> str:
13
+ """
14
+ Return the provided string but stripped and lower cased.
15
+
16
+ Example
17
+ -------
18
+ >>> striplower(' Foo ')
19
+ 'foo'
20
+
21
+ :param value: String which will be stripped and lowered.
22
+ :returns: Provided string but stripped and lower cased.
23
+ """
24
+
25
+ return value.strip().lower()
@@ -10,6 +10,23 @@ is permitted, for more information consult the project license file.
10
10
  from copy import deepcopy
11
11
 
12
12
  from ..dicts import merge_dicts
13
+ from ..dicts import sort_dict
14
+
15
+
16
+
17
+ DICT1 = {
18
+ 'dict1': 'dict1',
19
+ 'str': 'd1string',
20
+ 'list': ['d1list'],
21
+ 'dict': {'key': 'd1value'},
22
+ 'bool': False}
23
+
24
+ DICT2 = {
25
+ 'dict2': 'dict2',
26
+ 'str': 'd2string',
27
+ 'list': ['d2list'],
28
+ 'dict': {'key': 'd2value'},
29
+ 'bool': True}
13
30
 
14
31
 
15
32
 
@@ -18,19 +35,8 @@ def test_merge_dicts() -> None:
18
35
  Perform various tests associated with relevant routines.
19
36
  """
20
37
 
21
- dict1 = {
22
- 'dict1': 'dict1',
23
- 'str': 'd1string',
24
- 'list': ['d1list'],
25
- 'dict': {'key': 'd1value'},
26
- 'bool': False}
27
-
28
- dict2 = {
29
- 'dict2': 'dict2',
30
- 'str': 'd2string',
31
- 'list': ['d2list'],
32
- 'dict': {'key': 'd2value'},
33
- 'bool': True}
38
+ dict1 = deepcopy(DICT1)
39
+ dict2 = deepcopy(DICT2)
34
40
 
35
41
  dict1['recurse'] = deepcopy(dict1)
36
42
  dict2['recurse'] = deepcopy(dict2)
@@ -100,3 +106,17 @@ def test_merge_dicts() -> None:
100
106
  'list': ['d1list'],
101
107
  'dict': {'key': 'd1value'},
102
108
  'bool': False}}
109
+
110
+
111
+
112
+ def test_sort_dict() -> None:
113
+ """
114
+ Perform various tests associated with relevant routines.
115
+ """
116
+
117
+ assert sort_dict(DICT1) == {
118
+ 'bool': False,
119
+ 'dict': {'key': 'd1value'},
120
+ 'dict1': 'dict1',
121
+ 'list': ['d1list'],
122
+ 'str': 'd1string'}
@@ -0,0 +1,19 @@
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 ..strings import striplower
11
+
12
+
13
+
14
+ def test_striplower() -> None:
15
+ """
16
+ Perform various tests associated with relevant routines.
17
+ """
18
+
19
+ assert striplower(' Foo ') == 'foo'
encommon/utils/sample.py CHANGED
@@ -98,7 +98,7 @@ def load_sample(
98
98
  :param update: Determine whether the sample is updated.
99
99
  :param content: Content which will be processed for JSON.
100
100
  :param default: Callable used when stringifying values.
101
- :param replace: Optional string values to replace in path.
101
+ :param replace: Optional string values to replace in file.
102
102
  :returns: Content after processing using JSON functions.
103
103
  """
104
104
 
encommon/version.txt CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.6.0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Enasis Network
3
+ Copyright (c) 2024 Enasis Network
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: encommon
3
- Version: 0.4.1
3
+ Version: 0.6.0
4
4
  Summary: Enasis Network Common Library
5
5
  License: MIT
6
6
  Classifier: Programming Language :: Python :: 3
@@ -18,14 +18,15 @@ Requires-Dist: snaptime
18
18
 
19
19
  # Enasis Network Common Library
20
20
 
21
- [![](https://img.shields.io/github/actions/workflow/status/enasisnetwork/encommon/build.yml?style=flat-square&label=GitHub%20actions)](https://github.com/enasisnetwork/encommon/actions)
22
- [![](https://img.shields.io/readthedocs/encommon?style=flat-square&label=Read%20the%20Docs)](https://encommon.readthedocs.io/en/stable)
23
- [![](https://img.shields.io/pypi/v/encommon.svg?style=flat-square&label=PyPi%20version)](https://pypi.org/project/encommon)
24
- [![](https://img.shields.io/pypi/dm/encommon?style=flat-square&label=PyPi%20downloads)](https://pypi.org/project/encommon)
25
-
26
21
  Common classes and functions used in various public and private projects for
27
22
  [Enasis Network](https://github.com/enasisnetwork).
28
23
 
24
+ [![](https://img.shields.io/github/actions/workflow/status/enasisnetwork/encommon/build.yml?style=flat-square&label=GitHub%20actions)](https://github.com/enasisnetwork/encommon/actions)<br>
25
+ [![codecov](https://codecov.io/gh/enasisnetwork/encommon/graph/badge.svg?token=7PGOXKJU0E)](https://codecov.io/gh/enasisnetwork/encommon)<br>
26
+ [![](https://img.shields.io/readthedocs/encommon?style=flat-square&label=Read%20the%20Docs)](https://encommon.readthedocs.io/en/stable)<br>
27
+ [![](https://img.shields.io/pypi/v/encommon.svg?style=flat-square&label=PyPi%20version)](https://pypi.org/project/encommon)<br>
28
+ [![](https://img.shields.io/pypi/dm/encommon?style=flat-square&label=PyPi%20downloads)](https://pypi.org/project/encommon)
29
+
29
30
  ## Installing the package
30
31
  Installing stable from the PyPi repository
31
32
  ```
@@ -1,17 +1,17 @@
1
1
  encommon/__init__.py,sha256=VoXUcphq-gcXCraaU47EtXBftF6UVuQPMGr0fuCTt9A,525
2
+ encommon/conftest.py,sha256=z5BMi6KjNuactDRgbh8J8w81V08Ptf6QK2o_bJANRs4,880
2
3
  encommon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- encommon/version.txt,sha256=9iGEzuh4fy9pQcggQaVyXU7cmqKT6-Xb9mRAboLsH-E,6
4
+ encommon/version.txt,sha256=l6XW5UCmEg0Jw53bZn4Ojiusf8wv_vgTuC4I_WA2W84,6
4
5
  encommon/config/__init__.py,sha256=2ic7tK2lOQvqWmmQnMozqxCJcbyQ_sSEHmOUDUFan2U,710
5
6
  encommon/config/common.py,sha256=gaKBgkF7b7UIAhd0ESio0KpG8JfdRpz5BxNgKRptd6A,2041
6
- encommon/config/config.py,sha256=pvvz5lzqaXJV-9-8v8XPXVP8vpHiZ9lzGLx05pjW5gk,4855
7
+ encommon/config/config.py,sha256=-wIkyA6YQGAly0WuXLaOYXENjZYRYgWk_VdUN8mMe8Q,4853
7
8
  encommon/config/files.py,sha256=2DHz7GKOjF8FC26tY0V-E9svNMrlkSUshb2gfxqGgSo,2313
8
9
  encommon/config/logger.py,sha256=2y-VFzgM2pZzEYq48XfvrDPrtUcxyP9QjbH5OG7fv5o,13449
9
- encommon/config/params.py,sha256=8urH47NIIspO5MGkXdOuLRzWpmNqMnKXSagNeiIwkHw,1212
10
+ encommon/config/params.py,sha256=IWQ-UzR8x6VxkcUddC3qhI612IFMfLW44jEjRePXK0c,1825
10
11
  encommon/config/paths.py,sha256=0EpXWn6G9IO6tuZTrWuDq53RI5xMTgDQrAlOjRLILHs,2433
11
12
  encommon/config/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
12
- encommon/config/test/conftest.py,sha256=TNLox448WJSUkG5Lx2PM7LWvLHiaaOvxm6tx6o02pBc,810
13
13
  encommon/config/test/test_common.py,sha256=U6XWfCLxtLmArn8P6h4cmCALzdXxV7IMUxKNU-UhwPw,731
14
- encommon/config/test/test_config.py,sha256=k67kmzoRhakkrB_5xmN-VrLXuELCH4k5ZUHQySxtu_s,2824
14
+ encommon/config/test/test_config.py,sha256=SMe8ZrHRVS7jcyoFB-jBmlYTdUkBT1RrjZ9QlAW1EtE,3292
15
15
  encommon/config/test/test_files.py,sha256=OlGziUPV35yrdn2Ac8tuqmFfjHciWJADdQRvacoJNUc,2298
16
16
  encommon/config/test/test_logger.py,sha256=oLMosbxHq313oSNkdsrJe_kp0YrlcLCErIccg66zXcI,4635
17
17
  encommon/config/test/test_paths.py,sha256=vNWYqiN_wNuFCu1HHEekoJdGGJyRlucDBZTAspwxWhc,2107
@@ -23,38 +23,40 @@ encommon/crypts/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLE
23
23
  encommon/crypts/test/test_crypts.py,sha256=QDhIUVzn-n5z9tk1ZPXbZ4pBx0CRtcfqIyESYVB0kbU,2433
24
24
  encommon/crypts/test/test_hashes.py,sha256=Spixpx2qBi6iSJ8aNgmnNtz04JofUpwU-a_UjpRoiHA,1206
25
25
  encommon/times/__init__.py,sha256=w6LeTybgdsi0oM1EL9ARbAqevX7Tn46JYhbXNAaWzB0,597
26
- encommon/times/common.py,sha256=zDI5ztMkfLmV090jlLLK3hFzGGveasy8I_wNfOQDScg,2500
26
+ encommon/times/common.py,sha256=xLB_GLahYKT-YrVq90RUzmiodJQ4__1YihgZZTnadgg,2506
27
27
  encommon/times/duration.py,sha256=8p-L9OItO80nnd35FYrAXbiUS8RJzavI21lXBrtLaH0,9872
28
28
  encommon/times/parse.py,sha256=ZzranxftlB6bZJ1ivkoUxD53TUfXDDUdpq9jsSJN-88,6411
29
- encommon/times/timers.py,sha256=N9RrnHbNMzz7nlDEgJTmLq7u_93x61MT5Ku8EHmcMEU,3212
29
+ encommon/times/timers.py,sha256=yOVr6deGE5iatNWUwNQCzaXjMlLeYlolx4MmKT0MSHc,6312
30
30
  encommon/times/times.py,sha256=Dfu6ztUsV4X4vHzOC7ds8jtYy0AVj4_R5xB6H-yzemE,9432
31
31
  encommon/times/window.py,sha256=Fx_OJfU9B0IctCyaJ5XH_HxzhGlzeRATwuhI-HlsTPA,8023
32
32
  encommon/times/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
33
33
  encommon/times/test/test_common.py,sha256=nizxgB1scLDEm2o66waK1Ar_Dl5BBMTC-GRV7iDk0_U,1477
34
34
  encommon/times/test/test_duration.py,sha256=rmAhW2otHzQDHF0mBSETHnnL2OSbeAFYEHpDlaUSRnI,3901
35
35
  encommon/times/test/test_parse.py,sha256=TuZG_UbIEez4Ww35vdKIie_yaKp-PiUhsNmr1ZUoGvo,4308
36
- encommon/times/test/test_timers.py,sha256=F8asiUbMcIXkSstrOhQ9wrmdM2oTFAAM4sL50eQB4IA,1456
36
+ encommon/times/test/test_timers.py,sha256=z-ONyKtkAZ1A7w8qgpgx07r-Vsl5jY-pe2oneSF7hyo,2314
37
37
  encommon/times/test/test_times.py,sha256=DJBmRHCPkMLL9-bmc2DMhhf8zcr2rsTVAAQPavD_UmE,1986
38
38
  encommon/times/test/test_window.py,sha256=EWjXR8XREYwKrH-221CBAUwLF9GpvHtuF_CSMdQtUXI,4735
39
- encommon/types/__init__.py,sha256=zdSH4xILpR4FrkACwZ7Cu0Lu5F_YqltRJRhayQAcDGk,324
40
- encommon/types/dicts.py,sha256=76uxhJG7QEO1NViP8Kd_VAPBkcw2Wga1vgPh4ITKt7g,1616
39
+ encommon/types/__init__.py,sha256=l2WKtDs6uC9I3dIGnrzJvz-4JLEETUJOfT509XyMQWs,420
40
+ encommon/types/dicts.py,sha256=zJbfAsL1uiqfouBQrQgcYGoLowtkUd-Vm9536_DVK_E,2208
41
41
  encommon/types/empty.py,sha256=KrH6I0PPljaFBQ1qB1tbxFxZd8DR5rEFYhZqgLzjIsA,2675
42
+ encommon/types/strings.py,sha256=lgrzZuiCnH1UW17EFkLYiou3kQBgs_ZK2R92_dz7gRQ,560
42
43
  encommon/types/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
43
- encommon/types/test/test_dicts.py,sha256=BDuoh75UHeCRdV7lthLfhd8kku_E2Bjir_VeJoxldQM,2348
44
+ encommon/types/test/test_dicts.py,sha256=UHMvrWKnz-bPscq0Vp2uoLLFv4slvQQL2sobe5WUZ7U,2673
44
45
  encommon/types/test/test_empty.py,sha256=YUn0ROFhrWLQ30uROVqroHW4BsnFbzUZjACs3aEvrrI,981
46
+ encommon/types/test/test_strings.py,sha256=WHXf1dnK6Qs2_0UyGYztJxpS29bnR8WKjKsvVO2WCi4,407
45
47
  encommon/utils/__init__.py,sha256=qdr2RDKlmoGrgMhwJCaTrhQXmuD_lmDxlIxOUprnRVs,784
46
48
  encommon/utils/common.py,sha256=UrowELh3PtDzpSS48nGhsAxTS_QUk96-KEJa4MlxiMA,466
47
49
  encommon/utils/match.py,sha256=4L2d2Cvr7vp3odkRCdNQ10OIW8DkEP55_NbQ6bdsReo,2462
48
50
  encommon/utils/paths.py,sha256=4EeaPsVwpv3pzoHeWmiSSGYZEud6hkD27kvbvgSpOPs,3236
49
- encommon/utils/sample.py,sha256=Bm5PXKRc8JmgeQsvthoBHwU1yPkbnB8zS2piI7KWP4M,3169
51
+ encommon/utils/sample.py,sha256=hOhS6A2aB9a5kXfrst7gUSQkxuqEo2J1AFyBsJZQhHE,3169
50
52
  encommon/utils/stdout.py,sha256=0C5NTg8fAB25s5oKmsmV2VSERn22QFCZjqJ1S75SXOM,2779
51
53
  encommon/utils/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
52
54
  encommon/utils/test/test_match.py,sha256=QagKpTFdRo23-Y55fSaJrSMpt5jIebScKbz0h8tivrI,1124
53
55
  encommon/utils/test/test_paths.py,sha256=0ls9gWJ2B487Dr1fHDDFCZPA7gxtv56nFEYHrTkNX-U,1892
54
56
  encommon/utils/test/test_sample.py,sha256=iNV9IxXmA5KJat3jKRiZH3iutHrT6bsibwti60AhICk,1464
55
57
  encommon/utils/test/test_stdout.py,sha256=a060uA8oEHFGoVqdwB5iYxdl4R2TRSgr6Z7pMEbxibs,1675
56
- encommon-0.4.1.dist-info/LICENSE,sha256=04XJC5i4LRUf1A_U1EGCMJLpGodnmOFlh30yu7FAVfs,1071
57
- encommon-0.4.1.dist-info/METADATA,sha256=ymnId20TKS4QbdR_pEnplNsaj0_Tpql_tS4d3evYo9E,2517
58
- encommon-0.4.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
59
- encommon-0.4.1.dist-info/top_level.txt,sha256=bP8q7-5tLDNm-3XPlqn_bDENfYNug5801H_xfz3BEAM,9
60
- encommon-0.4.1.dist-info/RECORD,,
58
+ encommon-0.6.0.dist-info/LICENSE,sha256=otnXKCtMjPlbHs0wgZ_BWULrp3g_2dWQJ6icRk9nkgg,1071
59
+ encommon-0.6.0.dist-info/METADATA,sha256=OJ2Y0-tAC9HmFKQmrcyR5oQHFAVU1rxD9Rt2ssceXAs,2671
60
+ encommon-0.6.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
61
+ encommon-0.6.0.dist-info/top_level.txt,sha256=bP8q7-5tLDNm-3XPlqn_bDENfYNug5801H_xfz3BEAM,9
62
+ encommon-0.6.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5