edq-utils 0.0.1__py3-none-any.whl → 0.0.3__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.

Potentially problematic release.


This version of edq-utils might be problematic. Click here for more details.

edq/util/time_test.py ADDED
@@ -0,0 +1,107 @@
1
+ import time
2
+ import datetime
3
+
4
+ import edq.testing.unittest
5
+ import edq.util.time
6
+
7
+ TIMEZONE_UTC: datetime.timezone = datetime.timezone.utc
8
+ TIMEZONE_PST: datetime.timezone = datetime.timezone(datetime.timedelta(hours = -7), name = 'PST')
9
+ TIMEZONE_CEST: datetime.timezone = datetime.timezone(datetime.timedelta(hours = 2), name = 'CEST')
10
+
11
+ class TestTime(edq.testing.unittest.BaseTest):
12
+ """ Test time-based operations. """
13
+
14
+ def test_timestamp_now(self):
15
+ """ Test getting a timestamp for the current moment. """
16
+
17
+ start = edq.util.time.Timestamp.now()
18
+ time.sleep(0.01)
19
+ middle = edq.util.time.Timestamp.now()
20
+ time.sleep(0.01)
21
+ end = edq.util.time.Timestamp.now()
22
+
23
+ self.assertLessEqual(start, middle)
24
+ self.assertLessEqual(middle, end)
25
+
26
+ def test_timestamp_pytime_conversion(self):
27
+ """ Test converting between timestamps and Python datetimes. """
28
+
29
+ # [(timestamp, python time), ...]
30
+ test_cases = [
31
+ (edq.util.time.Timestamp(0), datetime.datetime(1970, 1, 1, 0, 0, 0, 0, TIMEZONE_UTC)),
32
+
33
+ (edq.util.time.Timestamp(1755139534019), datetime.datetime(2025, 8, 14, 2, 45, 34, 19000, TIMEZONE_UTC)),
34
+ (edq.util.time.Timestamp(1755139534019), datetime.datetime(2025, 8, 13, 19, 45, 34, 19000, TIMEZONE_PST)),
35
+ (edq.util.time.Timestamp(1755139534019), datetime.datetime(2025, 8, 14, 4, 45, 34, 19000, TIMEZONE_CEST)),
36
+ ]
37
+
38
+ for (i, test_case) in enumerate(test_cases):
39
+ (timestamp, pytime) = test_case
40
+
41
+ with self.subTest(msg = f"Case {i} ('{timestamp}' == '{pytime}'):"):
42
+ convert_pytime = timestamp.to_pytime(pytime.tzinfo)
43
+ self.assertEqual(pytime, convert_pytime, 'pytime')
44
+
45
+ convert_timestamp = edq.util.time.Timestamp.from_pytime(pytime)
46
+ self.assertEqual(timestamp, convert_timestamp, 'timestamp')
47
+
48
+ # Check other time zones.
49
+ # Use string comparisons to ensure the timezone is compared (and not just the UTC time).
50
+ timezones = [
51
+ TIMEZONE_UTC,
52
+ TIMEZONE_PST,
53
+ TIMEZONE_CEST,
54
+ ]
55
+
56
+ for timezone in timezones:
57
+ pytime_pst = pytime.astimezone(timezone).isoformat(timespec = 'milliseconds')
58
+ convert_pytime_pst = timestamp.to_pytime(timezone).isoformat(timespec = 'milliseconds')
59
+ self.assertEqual(pytime_pst, convert_pytime_pst, f"pytime {timezone}")
60
+
61
+ def test_timestamp_pretty(self):
62
+ """ Test the "pretty" representations of timestamps. """
63
+
64
+ # [(timestamp, timezone, pretty short, pretty long), ...]
65
+ test_cases = [
66
+ (edq.util.time.Timestamp(0), TIMEZONE_UTC, "1970-01-01 00:00", "1970-01-01T00:00:00.000+00:00"),
67
+
68
+ (edq.util.time.Timestamp(1755139534019), TIMEZONE_UTC, "2025-08-14 02:45", "2025-08-14T02:45:34.019+00:00"),
69
+ (edq.util.time.Timestamp(1755139534019), TIMEZONE_PST, "2025-08-13 19:45", "2025-08-13T19:45:34.019-07:00"),
70
+ (edq.util.time.Timestamp(1755139534019), TIMEZONE_CEST, "2025-08-14 04:45", "2025-08-14T04:45:34.019+02:00"),
71
+ ]
72
+
73
+ for (i, test_case) in enumerate(test_cases):
74
+ (timestamp, timezone, expected_pretty_short, expected_pretty_long) = test_case
75
+
76
+ with self.subTest(msg = f"Case {i} ('{timestamp}'):"):
77
+ actual_pretty_short = timestamp.pretty(short = True, timezone = timezone)
78
+ actual_pretty_long = timestamp.pretty(short = False, timezone = timezone)
79
+
80
+ self.assertEqual(expected_pretty_short, actual_pretty_short, 'short')
81
+ self.assertEqual(expected_pretty_long, actual_pretty_long, 'long')
82
+
83
+ def test_timestamp_sub(self):
84
+ """ Test subtracting timestamps. """
85
+
86
+ # [(a, b, expected), ...]
87
+ # All values in this structure will be in ints and converted later.
88
+ test_cases = [
89
+ (0, 0, 0),
90
+ (0, 1, -1),
91
+ (1, 0, 1),
92
+
93
+ (100, 100, 0),
94
+ (100, 101, -1),
95
+ (101, 100, 1),
96
+ ]
97
+
98
+ for (i, test_case) in enumerate(test_cases):
99
+ (raw_a, raw_b, raw_expected) = test_case
100
+
101
+ with self.subTest(msg = f"Case {i} ({raw_a} - {raw_b}):"):
102
+ a = edq.util.time.Timestamp(raw_a)
103
+ b = edq.util.time.Timestamp(raw_b)
104
+ expected = edq.util.time.Duration(raw_expected)
105
+
106
+ actual = a - b
107
+ self.assertEqual(expected, actual)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: edq-utils
3
- Version: 0.0.1
3
+ Version: 0.0.3
4
4
  Summary: Common utilities used by EduLinq Python projects.
5
5
  Author-email: Eriq Augustine <eriq@edulinq.org>
6
6
  License: MIT License
@@ -34,8 +34,10 @@ Classifier: Programming Language :: Python :: 3.8
34
34
  Requires-Python: >=3.8
35
35
  Description-Content-Type: text/markdown
36
36
  License-File: LICENSE
37
+ Requires-Dist: json5>=0.9.14
37
38
  Provides-Extra: dev
38
39
  Requires-Dist: mypy>=1.14.1; extra == "dev"
40
+ Requires-Dist: pdoc>=14.7.0; extra == "dev"
39
41
  Requires-Dist: pylint; extra == "dev"
40
42
  Requires-Dist: twine; extra == "dev"
41
43
  Requires-Dist: vermin; extra == "dev"
@@ -0,0 +1,28 @@
1
+ edq/__init__.py,sha256=SgI3o5Z-z1KSX-sg-2ZL2vhNQ-KiMte0ewCvjQv8wWA,86
2
+ edq/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ edq/testing/__init__.py,sha256=IKd3fPU_8d_jP19HxG-zKwxFwn7nqFGGtXOY5slY41c,32
4
+ edq/testing/run.py,sha256=qnqGCEwZP-hY87X99EJw2xoMaTF8QeOf7Lx8JI7oM_4,3843
5
+ edq/testing/unittest.py,sha256=J_sUYGIdP8HDQioQtUPF_H4n2aKf0_XHLdhzs59fvck,1665
6
+ edq/util/__init__.py,sha256=9EFKQE77S-B6OJJKFaMg8k3WkMMUQYlGjlTv6tQmWVo,29
7
+ edq/util/dirent.py,sha256=C-ZTVbOVBlEc71g4l8rMO5EJHv4Lcl9-FH0Kp1B3oc8,10314
8
+ edq/util/dirent_test.py,sha256=oXpAaEhOkEr0zw0fdAPypx7QH1aFbY2Hpox-9OpZjhs,33380
9
+ edq/util/json.py,sha256=p74F5OCxbRv4mvMSkRdy-fYVqAETx5_65IEhesTH8SM,5228
10
+ edq/util/json_test.py,sha256=utUVRbw3z42ke4fpRVI294RrFHcMKms8khVYRkISNk4,8009
11
+ edq/util/pyimport.py,sha256=M1j58vg4b6gTg92Cz5-bns3eQCCIMKDApBclP-iR620,2198
12
+ edq/util/pyimport_test.py,sha256=wuTR5pzVZanWDA2FuVc-Pxyo_GwkGGfFf_qyK6LNQRs,2851
13
+ edq/util/reflection.py,sha256=jPcW6h0fwSDYh04O5rUxlgoF7HK6fVQ2mq7DD9qPrEg,972
14
+ edq/util/time.py,sha256=anoNM_KniARLombv2BnsoHuCzDqMKiDdIzV7RUe2ZOk,2648
15
+ edq/util/time_test.py,sha256=iQZwzVTVQQ4TdXrLb9MUMCYlKrIe8qyF-hiC9YLTaMo,4610
16
+ edq/util/testdata/dirent-operations/a.txt,sha256=h0KPxSKAPTEGXnvOPPA_5HUJZjHl4Hu9eg_eYMTPJcc,2
17
+ edq/util/testdata/dirent-operations/file_empty,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ edq/util/testdata/dirent-operations/symlink_a.txt,sha256=h0KPxSKAPTEGXnvOPPA_5HUJZjHl4Hu9eg_eYMTPJcc,2
19
+ edq/util/testdata/dirent-operations/symlink_file_empty,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ edq/util/testdata/dirent-operations/dir_1/b.txt,sha256=AmOCmYm2_ZVPcrqvL8ZLwuLwHWktTecphuqAj26ZgT8,2
21
+ edq/util/testdata/dirent-operations/dir_1/dir_2/c.txt,sha256=o6XnFfDMV0pzw_m-u2vCTzL_1bZ7OHJEwskJ2neaFHg,2
22
+ edq/util/testdata/dirent-operations/symlink_dir_1/b.txt,sha256=AmOCmYm2_ZVPcrqvL8ZLwuLwHWktTecphuqAj26ZgT8,2
23
+ edq/util/testdata/dirent-operations/symlink_dir_1/dir_2/c.txt,sha256=o6XnFfDMV0pzw_m-u2vCTzL_1bZ7OHJEwskJ2neaFHg,2
24
+ edq_utils-0.0.3.dist-info/licenses/LICENSE,sha256=MS4iYEl4rOxMoprZuc86iYVoyk4YgaVoMt7WmGvVF8w,1064
25
+ edq_utils-0.0.3.dist-info/METADATA,sha256=YoOLw86gdPLaSAy_z9UfftRk83wxjjM-nD7r8H2FsEg,2471
26
+ edq_utils-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ edq_utils-0.0.3.dist-info/top_level.txt,sha256=znBHSj6tgXtcMKrUVtovLli5fIEJCb7d-BMxTLRK4zk,4
28
+ edq_utils-0.0.3.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- edq/__init__.py,sha256=DsAHdxLC16H2VjdFOU5tBx2xT9VnNQ-XbTS24fRCa_w,22
2
- edq/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- edq/util/dirent.py,sha256=Dr4OtB9TvJmiGLrjdiSmsh5Fk8G49jfklh4wdOx13ro,4436
4
- edq/util/dirent_test.py,sha256=FBMHEmcrfR7VILBzgy1cMWrFEp9wNQ5RNbL5vOdezT4,5998
5
- edq/util/testdata/dirent-operations/a.txt,sha256=h0KPxSKAPTEGXnvOPPA_5HUJZjHl4Hu9eg_eYMTPJcc,2
6
- edq/util/testdata/dirent-operations/file_empty,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- edq/util/testdata/dirent-operations/symlinklink_a.txt,sha256=h0KPxSKAPTEGXnvOPPA_5HUJZjHl4Hu9eg_eYMTPJcc,2
8
- edq/util/testdata/dirent-operations/dir_1/b.txt,sha256=AmOCmYm2_ZVPcrqvL8ZLwuLwHWktTecphuqAj26ZgT8,2
9
- edq/util/testdata/dirent-operations/dir_1/dir_2/c.txt,sha256=o6XnFfDMV0pzw_m-u2vCTzL_1bZ7OHJEwskJ2neaFHg,2
10
- edq/util/testdata/dirent-operations/symlinklink_dir_1/b.txt,sha256=AmOCmYm2_ZVPcrqvL8ZLwuLwHWktTecphuqAj26ZgT8,2
11
- edq/util/testdata/dirent-operations/symlinklink_dir_1/dir_2/c.txt,sha256=o6XnFfDMV0pzw_m-u2vCTzL_1bZ7OHJEwskJ2neaFHg,2
12
- edq_utils-0.0.1.dist-info/licenses/LICENSE,sha256=MS4iYEl4rOxMoprZuc86iYVoyk4YgaVoMt7WmGvVF8w,1064
13
- edq_utils-0.0.1.dist-info/METADATA,sha256=Q99RoHQkHjWZEkP-gEdtEaEPE1xoauWVtUXWsE3OlmM,2398
14
- edq_utils-0.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- edq_utils-0.0.1.dist-info/top_level.txt,sha256=znBHSj6tgXtcMKrUVtovLli5fIEJCb7d-BMxTLRK4zk,4
16
- edq_utils-0.0.1.dist-info/RECORD,,