encommon 0.7.6__py3-none-any.whl → 0.8.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 (53) hide show
  1. encommon/config/__init__.py +6 -0
  2. encommon/config/common.py +18 -14
  3. encommon/config/config.py +21 -14
  4. encommon/config/files.py +13 -7
  5. encommon/config/logger.py +94 -88
  6. encommon/config/params.py +4 -4
  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 +5 -4
  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.1.dist-info}/METADATA +1 -1
  49. encommon-0.8.1.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.1.dist-info}/LICENSE +0 -0
  52. {encommon-0.7.6.dist-info → encommon-0.8.1.dist-info}/WHEEL +0 -0
  53. {encommon-0.7.6.dist-info → encommon-0.8.1.dist-info}/top_level.txt +0 -0
@@ -11,6 +11,10 @@ from typing import Literal
11
11
  from typing import Union
12
12
  from typing import get_args
13
13
 
14
+ from ..types.strings import COMMAS
15
+ from ..types.strings import SEMPTY
16
+ from ..types.strings import SPACED
17
+
14
18
 
15
19
 
16
20
  DURAGROUP = Literal[
@@ -33,7 +37,7 @@ DURAUNITS = Union[
33
37
 
34
38
  class Duration:
35
39
  """
36
- Convert provided the seconds into a human friendly format.
40
+ Convert the provided seconds in a human friendly format.
37
41
 
38
42
  Example
39
43
  -------
@@ -52,8 +56,8 @@ class Duration:
52
56
 
53
57
  :param seconds: Period in seconds that will be iterated.
54
58
  :param smart: Determines if we hide seconds after minute.
55
- :param groups: Determine the amount of groups to show,
56
- ensuring the larger units are returned before smaller.
59
+ :param groups: Determine the quantity of groups to show,
60
+ ensuring larger units are returned before smaller.
57
61
  """
58
62
 
59
63
  __source: float
@@ -122,7 +126,7 @@ class Duration:
122
126
  """
123
127
  Built-in method representing numeric value for instance.
124
128
 
125
- :returns: Numeric representation for values from instance.
129
+ :returns: Numeric representation for value in instance.
126
130
  """
127
131
 
128
132
  return int(self.__source)
@@ -134,7 +138,7 @@ class Duration:
134
138
  """
135
139
  Built-in method representing numeric value for instance.
136
140
 
137
- :returns: Numeric representation for values from instance.
141
+ :returns: Numeric representation for value in instance.
138
142
  """
139
143
 
140
144
  return float(self.__source)
@@ -326,7 +330,7 @@ class Duration:
326
330
  source = self.__source
327
331
  seconds = int(source)
328
332
 
329
- returned: dict[DURAUNITS, int] = {}
333
+ units: dict[DURAUNITS, int] = {}
330
334
 
331
335
  groups: dict[DURAGROUP, int] = {
332
336
  'year': 31536000,
@@ -337,60 +341,67 @@ class Duration:
337
341
  'minute': 60}
338
342
 
339
343
 
340
- for key, value in groups.items():
344
+ items = groups.items()
345
+
346
+ for key, value in items:
341
347
 
342
348
  if seconds < value:
343
349
  continue
344
350
 
345
351
  _value = seconds // value
346
-
347
- returned[key] = _value
348
-
349
352
  seconds %= value
350
353
 
354
+ units[key] = _value
355
+
351
356
 
352
- if (source < 60
353
- or (seconds >= 1
354
- and source > 60)):
355
- returned['second'] = seconds
357
+ if ((seconds >= 1
358
+ and source > 60)
359
+ or source < 60):
360
+ units['second'] = seconds
356
361
 
357
- if (self.__smart
358
- and 'second' in returned
359
- and len(returned) >= 2):
360
- del returned['second']
362
+ if ('second' in units
363
+ and len(units) >= 2
364
+ and self.__smart):
365
+ del units['second']
361
366
 
362
367
 
363
- items = (
364
- list(returned.items())
368
+ _groups = (
369
+ list(units.items())
365
370
  [:self.__groups])
366
371
 
367
372
  if short is False:
368
- return dict(items)
373
+ return dict(_groups)
369
374
 
370
375
  return {
371
376
  DURAMAPS[k]: v
372
- for k, v in items}
377
+ for k, v in _groups}
373
378
 
374
379
 
375
380
  def __duration(
376
381
  self,
377
- delim: str = ' ',
382
+ delim: str = SPACED,
378
383
  short: bool = True,
379
384
  ) -> str:
380
385
  """
381
- Return the compact format calculated from source duration.
386
+ Return the compact format determined by source duration.
382
387
 
383
388
  :param delim: Optional delimiter for between the groups.
384
389
  :param short: Determine if we should use the short hand.
385
- :returns: Compact format calculated from source duration.
390
+ :returns: Compact format determined by source duration.
386
391
  """
387
392
 
388
393
  parts: list[str] = []
389
394
 
390
395
  groups = self.units(short)
391
- spaced = '' if short else ' '
392
396
 
393
- for part, value in groups.items():
397
+ space = (
398
+ SEMPTY if short
399
+ else SPACED)
400
+
401
+
402
+ items = groups.items()
403
+
404
+ for part, value in items:
394
405
 
395
406
  unit: str = part
396
407
 
@@ -399,7 +410,8 @@ class Duration:
399
410
  unit += 's'
400
411
 
401
412
  parts.append(
402
- f'{value}{spaced}{unit}')
413
+ f'{value}{space}{unit}')
414
+
403
415
 
404
416
  return delim.join(parts)
405
417
 
@@ -409,9 +421,9 @@ class Duration:
409
421
  self,
410
422
  ) -> str:
411
423
  """
412
- Return the compact format calculated from source duration.
424
+ Return the compact format determined by source duration.
413
425
 
414
- :returns: Compact format calculated from source duration.
426
+ :returns: Compact format determined by source duration.
415
427
  """
416
428
 
417
429
  return self.__duration()
@@ -422,12 +434,13 @@ class Duration:
422
434
  self,
423
435
  ) -> str:
424
436
  """
425
- Return the compact format calculated from source duration.
437
+ Return the compact format determined by source duration.
426
438
 
427
- :returns: Compact format calculated from source duration.
439
+ :returns: Compact format determined by source duration.
428
440
  """
429
441
 
430
- return self.short.replace(' ', '')
442
+ return self.short.replace(
443
+ SPACED, SEMPTY)
431
444
 
432
445
 
433
446
  @property
@@ -435,12 +448,13 @@ class Duration:
435
448
  self,
436
449
  ) -> str:
437
450
  """
438
- Return the verbose format calculated from source duration.
451
+ Return the verbose format determined by source duration.
439
452
 
440
- :returns: Compact format calculated from source duration.
453
+ :returns: Verbose format determined by source duration.
441
454
  """
442
455
 
443
456
  if self.__source < 60:
444
457
  return 'just now'
445
458
 
446
- return self.__duration(', ', False)
459
+ return self.__duration(
460
+ COMMAS, False)
encommon/times/parse.py CHANGED
@@ -15,7 +15,6 @@ from typing import Optional
15
15
  from typing import TYPE_CHECKING
16
16
 
17
17
  from dateutil import parser
18
- from dateutil.tz import gettz
19
18
 
20
19
  from snaptime import snap
21
20
 
@@ -23,6 +22,7 @@ from .common import NUMERISH
23
22
  from .common import PARSABLE
24
23
  from .common import SNAPABLE
25
24
  from .common import STRINGNOW
25
+ from .common import findtz
26
26
  from .common import strptime
27
27
  from .common import utcdatetime
28
28
 
@@ -87,14 +87,7 @@ def parse_time( # noqa: CFQ004
87
87
  and re_match(NUMERISH, source)):
88
88
  source = float(source)
89
89
 
90
-
91
- if tzname is not None:
92
- tzinfo = gettz(tzname)
93
- else:
94
- tzinfo = timezone.utc
95
-
96
- if tzinfo is None:
97
- raise ValueError('tzname')
90
+ tzinfo = findtz(tzname)
98
91
 
99
92
 
100
93
  if isinstance(source, (int, float)):
@@ -129,7 +122,7 @@ def parse_time( # noqa: CFQ004
129
122
  .astimezone(timezone.utc))
130
123
 
131
124
 
132
- raise ValueError('source')
125
+ raise ValueError('source') # NOCVR
133
126
 
134
127
 
135
128
 
@@ -159,13 +152,10 @@ def shift_time(
159
152
  :returns: Python datetime object containing related time.
160
153
  """
161
154
 
162
- anchor = parse_time(anchor, tzname=tzname)
163
-
164
- parsed = snap(anchor, notate)
165
-
166
- assert isinstance(parsed, datetime)
155
+ anchor = parse_time(
156
+ anchor, tzname=tzname)
167
157
 
168
- return parsed
158
+ return snap(anchor, notate)
169
159
 
170
160
 
171
161
 
@@ -195,18 +185,14 @@ def string_time(
195
185
  :returns: Python datetime object containing related time.
196
186
  """
197
187
 
198
- parsed: Optional[datetime] = None
199
-
200
188
  if formats is not None:
201
189
  with suppress(ValueError):
202
- parsed = strptime(source, formats)
203
-
204
- if parsed is None:
205
- parsed = parser.parse(source)
190
+ return strptime(source, formats)
206
191
 
207
- assert isinstance(parsed, datetime)
192
+ parsed = parser.parse(source)
208
193
 
209
- return parse_time(parsed, tzname=tzname)
194
+ return parse_time(
195
+ parsed, tzname=tzname)
210
196
 
211
197
 
212
198
 
@@ -234,4 +220,6 @@ def since_time(
234
220
 
235
221
  delta = stop - start
236
222
 
237
- return abs(delta.total_seconds())
223
+ since = delta.total_seconds()
224
+
225
+ return abs(since)
@@ -11,6 +11,9 @@ from dateutil.tz import gettz
11
11
 
12
12
  from pytest import raises
13
13
 
14
+ from ..common import STAMP_SIMPLE
15
+ from ..common import UNIXEPOCH
16
+ from ..common import findtz
14
17
  from ..common import strptime
15
18
  from ..common import utcdatetime
16
19
 
@@ -28,6 +31,8 @@ def test_utcdatetime() -> None:
28
31
  assert dtime.month == 1
29
32
  assert dtime.day == 1
30
33
  assert dtime.hour == 0
34
+ assert dtime.minute == 0
35
+ assert dtime.second == 0
31
36
 
32
37
 
33
38
  dtime = utcdatetime(
@@ -38,41 +43,67 @@ def test_utcdatetime() -> None:
38
43
  assert dtime.month == 1
39
44
  assert dtime.day == 1
40
45
  assert dtime.hour == 6
46
+ assert dtime.minute == 0
47
+ assert dtime.second == 0
41
48
 
42
49
 
43
- assert utcdatetime().year >= 2023
44
50
 
51
+ def test_strptime() -> None:
52
+ """
53
+ Perform various tests associated with relevant routines.
54
+ """
45
55
 
46
56
 
47
- def test_strptime() -> None:
57
+ parsed = strptime(
58
+ UNIXEPOCH, STAMP_SIMPLE)
59
+
60
+ assert parsed.year == 1970
61
+ assert parsed.month == 1
62
+ assert parsed.day == 1
63
+ assert parsed.hour == 0
64
+ assert parsed.minute == 0
65
+ assert parsed.second == 0
66
+
67
+
68
+
69
+ def test_strptime_raises() -> None:
48
70
  """
49
71
  Perform various tests associated with relevant routines.
50
72
  """
51
73
 
74
+ _raises = raises(ValueError)
52
75
 
53
- dtime = strptime('1970', '%Y')
76
+ with _raises as reason:
77
+ strptime('foo', '%Y')
54
78
 
55
- assert dtime.year == 1970
56
- assert dtime.month == 1
57
- assert dtime.day == 1
58
- assert dtime.hour == 0
79
+ _reason = str(reason.value)
59
80
 
81
+ assert _reason == 'invalid'
60
82
 
61
- dtime = strptime('1970', ['%Y'])
62
83
 
63
- assert dtime.year == 1970
64
- assert dtime.month == 1
65
- assert dtime.day == 1
66
- assert dtime.hour == 0
67
84
 
85
+ def test_findtz() -> None:
86
+ """
87
+ Perform various tests associated with relevant routines.
88
+ """
68
89
 
69
90
 
70
- def test_strptime_raises() -> None:
91
+ tzinfo = findtz('UTC')
92
+
93
+ assert 'UTC' in str(tzinfo)
94
+
95
+
96
+
97
+ def test_findtz_raises() -> None:
71
98
  """
72
99
  Perform various tests associated with relevant routines.
73
100
  """
74
101
 
75
- with raises(ValueError) as reason:
76
- strptime('foo', '%Y')
102
+ _raises = raises(ValueError)
103
+
104
+ with _raises as reason:
105
+ findtz('foo')
106
+
107
+ _reason = str(reason.value)
77
108
 
78
- assert str(reason.value) == 'invalid'
109
+ assert _reason == 'tzname'
@@ -8,6 +8,7 @@ is permitted, for more information consult the project license file.
8
8
 
9
9
 
10
10
  from ..duration import Duration
11
+ from ...types.strings import COMMAS
11
12
 
12
13
 
13
14
 
@@ -16,9 +17,10 @@ def test_Duration() -> None:
16
17
  Perform various tests associated with relevant routines.
17
18
  """
18
19
 
19
- duration = Duration(95401)
20
+ durate = Duration(95401)
20
21
 
21
- attrs = list(duration.__dict__)
22
+
23
+ attrs = list(durate.__dict__)
22
24
 
23
25
  assert attrs == [
24
26
  '_Duration__source',
@@ -26,91 +28,94 @@ def test_Duration() -> None:
26
28
  '_Duration__groups']
27
29
 
28
30
 
29
- assert repr(duration) == (
30
- 'Duration('
31
- 'seconds=95401.0, '
32
- 'smart=True, '
33
- 'groups=7)')
31
+ assert repr(durate)[:23] == (
32
+ 'Duration(seconds=95401.')
34
33
 
35
- assert isinstance(hash(duration), int)
36
- assert str(duration) == '1d2h30m'
34
+ assert hash(durate) > 0
37
35
 
36
+ assert str(durate) == '1d2h30m'
38
37
 
39
- assert int(duration) == 95401
40
- assert float(duration) == 95401
41
38
 
42
- assert duration + 1 == 95402
43
- assert duration + duration == 190802
44
- assert duration - 1 == 95400
45
- assert duration - duration == 0
39
+ assert int(durate) == 95401
40
+ assert float(durate) == 95401
46
41
 
47
- assert duration == duration
48
- assert duration != Duration(60)
49
- assert duration != 'invalid'
42
+ assert durate + 1 == 95402
43
+ assert durate + durate == 190802
44
+ assert durate - 1 == 95400
45
+ assert durate - durate == 0
50
46
 
51
- assert duration > Duration(95400)
52
- assert duration >= Duration(95401)
53
- assert duration < Duration(95402)
54
- assert duration <= Duration(95401)
47
+ assert durate == durate
48
+ assert durate != Duration(60)
49
+ assert durate != 'invalid'
55
50
 
51
+ assert durate > Duration(95400)
52
+ assert durate >= Duration(95401)
53
+ assert durate < Duration(95402)
54
+ assert durate <= Duration(95401)
56
55
 
57
- assert duration.source == 95401
58
- assert duration.smart is True
59
- assert duration.groups == 7
60
56
 
61
- assert duration.short == '1d 2h 30m'
62
- assert duration.compact == '1d2h30m'
63
- assert duration.verbose == (
64
- '1 day, 2 hours, 30 minutes')
57
+ assert durate.source == 95401
58
+
59
+ assert durate.smart is True
65
60
 
66
- assert duration.units() == {
61
+ assert durate.groups == 7
62
+
63
+ assert durate.units() == {
67
64
  'day': 1,
68
65
  'hour': 2,
69
66
  'minute': 30}
70
67
 
68
+ assert durate.short == '1d 2h 30m'
69
+
70
+ assert durate.compact == '1d2h30m'
71
+
72
+ assert durate.verbose == (
73
+ '1 day, 2 hours, 30 minutes')
74
+
75
+
71
76
 
72
- duration = Duration(
77
+ def test_Duration_cover() -> None:
78
+ """
79
+ Perform various tests associated with relevant routines.
80
+ """
81
+
82
+ durate = Duration(
73
83
  seconds=7501,
74
84
  smart=False)
75
85
 
76
- assert duration.short == '2h 5m 1s'
77
- assert duration.compact == '2h5m1s'
78
- assert duration.verbose == (
86
+ assert durate.short == '2h 5m 1s'
87
+ assert durate.compact == '2h5m1s'
88
+ assert durate.verbose == (
79
89
  '2 hours, 5 minutes, 1 second')
80
90
 
81
91
 
82
- duration = Duration(
92
+ durate = Duration(
93
+ groups=3,
83
94
  seconds=694800,
84
- smart=False,
85
- groups=3)
95
+ smart=False)
86
96
 
87
- assert duration.short == '1w 1d 1h'
88
- assert duration.compact == '1w1d1h'
89
- assert duration.verbose == (
97
+ assert durate.short == '1w 1d 1h'
98
+ assert durate.compact == '1w1d1h'
99
+ assert durate.verbose == (
90
100
  '1 week, 1 day, 1 hour')
91
101
 
92
102
 
93
- duration = Duration(36295261)
103
+ durate = Duration(36295261)
94
104
 
95
- assert duration.units() == {
96
- 'year': 1,
97
- 'week': 3,
98
- 'month': 1,
99
- 'day': 4,
100
- 'hour': 2,
101
- 'minute': 1}
105
+ units = durate.units(False)
106
+ assert units == {
107
+ 'year': 1, 'week': 3,
108
+ 'month': 1, 'day': 4,
109
+ 'hour': 2, 'minute': 1}
102
110
 
103
- assert duration.units(True) == {
104
- 'y': 1,
105
- 'w': 3,
106
- 'mon': 1,
107
- 'd': 4,
108
- 'h': 2,
109
- 'm': 1}
111
+ units = durate.units(True)
112
+ assert units == {
113
+ 'y': 1, 'w': 3, 'mon': 1,
114
+ 'd': 4, 'h': 2, 'm': 1}
110
115
 
111
116
 
112
117
 
113
- def test_Duration_cover() -> None:
118
+ def test_Duration_iterate() -> None:
114
119
  """
115
120
  Perform various tests associated with relevant routines.
116
121
  """
@@ -126,52 +131,72 @@ def test_Duration_cover() -> None:
126
131
 
127
132
  expects = {
128
133
 
129
- year: ('1y', '1 year'),
130
- year + 1: ('1y', '1 year'),
134
+ year: (
135
+ '1y', '1 year'),
136
+ year + 1: (
137
+ '1y', '1 year'),
131
138
  year - 1: (
132
139
  '12mon4d23h59m',
133
140
  '12 months, 4 days'),
134
141
 
135
- quarter: ('3mon', '3 months'),
136
- quarter + 1: ('3mon', '3 months'),
142
+ quarter: (
143
+ '3mon', '3 months'),
144
+ quarter + 1: (
145
+ '3mon', '3 months'),
137
146
  quarter - 1: (
138
147
  '2mon4w1d23h59m',
139
148
  '2 months, 4 weeks'),
140
149
 
141
- month: ('1mon', '1 month'),
142
- month + 1: ('1mon', '1 month'),
150
+ month: (
151
+ '1mon', '1 month'),
152
+ month + 1: (
153
+ '1mon', '1 month'),
143
154
  month - 1: (
144
155
  '4w1d23h59m',
145
156
  '4 weeks, 1 day'),
146
157
 
147
- week: ('1w', '1 week'),
148
- week + 1: ('1w', '1 week'),
158
+ week: (
159
+ '1w', '1 week'),
160
+ week + 1: (
161
+ '1w', '1 week'),
149
162
  week - 1: (
150
163
  '6d23h59m',
151
164
  '6 days, 23 hours'),
152
165
 
153
- day: ('1d', '1 day'),
154
- day + 1: ('1d', '1 day'),
166
+ day: (
167
+ '1d', '1 day'),
168
+ day + 1: (
169
+ '1d', '1 day'),
155
170
  day - 1: (
156
171
  '23h59m',
157
172
  '23 hours, 59 minutes'),
158
173
 
159
- hour: ('1h', '1 hour'),
160
- hour + 1: ('1h', '1 hour'),
161
- hour - 1: ('59m', '59 minutes'),
174
+ hour: (
175
+ '1h', '1 hour'),
176
+ hour + 1: (
177
+ '1h', '1 hour'),
178
+ hour - 1: (
179
+ '59m', '59 minutes'),
180
+
181
+ second: (
182
+ '1m', '1 minute'),
183
+ second + 1: (
184
+ '1m', '1 minute'),
185
+ second - 1: (
186
+ '59s', 'just now')}
162
187
 
163
- second: ('1m', '1 minute'),
164
- second + 1: ('1m', '1 minute'),
165
- second - 1: ('59s', 'just now')}
166
188
 
189
+ items = expects.items()
167
190
 
168
- for source, expect in expects.items():
191
+ for source, expect in items:
169
192
 
170
- duration = Duration(source)
171
- assert duration.compact == expect[0]
193
+ durate = Duration(source)
172
194
 
173
- duration = Duration(source)
174
- verbose = ', '.join(
175
- duration.verbose.split(', ')[:2])
195
+ compact, verbose = expect
196
+ _compact = durate.compact
197
+ _verbose = COMMAS.join(
198
+ durate.verbose
199
+ .split(', ')[:2])
176
200
 
177
- assert verbose == expect[1]
201
+ assert _compact == compact
202
+ assert _verbose == verbose