python-ulid 2.6.0__tar.gz → 2.7.0__tar.gz
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.
- {python_ulid-2.6.0 → python_ulid-2.7.0}/CHANGELOG.rst +11 -3
- {python_ulid-2.6.0 → python_ulid-2.7.0}/PKG-INFO +1 -1
- {python_ulid-2.6.0 → python_ulid-2.7.0}/tests/test_base32.py +1 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/tests/test_ulid.py +31 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/ulid/__init__.py +2 -8
- {python_ulid-2.6.0 → python_ulid-2.7.0}/ulid/base32.py +3 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/.github/workflows/lint-and-test.yml +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/.github/workflows/publish.yml +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/.gitignore +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/.pre-commit-config.yaml +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/.readthedocs.yml +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/LICENSE +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/README.rst +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/docs/Makefile +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/docs/requirements.txt +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/docs/source/api.rst +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/docs/source/changelog.rst +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/docs/source/conf.py +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/docs/source/index.rst +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/hatch.toml +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/logo.png +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/pyproject.toml +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/tests/__init__.py +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/tests/test_cli.py +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/ulid/__main__.py +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/ulid/constants.py +0 -0
- {python_ulid-2.6.0 → python_ulid-2.7.0}/ulid/py.typed +0 -0
|
@@ -5,13 +5,20 @@ Changelog
|
|
|
5
5
|
|
|
6
6
|
Versions follow `Semantic Versioning <http://www.semver.org>`_
|
|
7
7
|
|
|
8
|
+
`2.7.0`_ - 2024-06-17
|
|
9
|
+
---------------------
|
|
10
|
+
Changed
|
|
11
|
+
~~~~~~~
|
|
12
|
+
* Ensure that the validation of ULID's timestamp component aligns more closely with
|
|
13
|
+
the ULID specification.
|
|
14
|
+
|
|
8
15
|
`2.6.0`_ - 2024-05-26
|
|
9
16
|
---------------------
|
|
10
17
|
Changed
|
|
11
18
|
~~~~~~~
|
|
12
|
-
*
|
|
13
|
-
|
|
14
|
-
ensured that the timestamp part of the ULID is not out of range.
|
|
19
|
+
* Use stricter validation when a :class:`.ULID` value from user input. When using
|
|
20
|
+
:meth:`.ULID.from_str` we will check if the characters match the base32 alphabet. In general,
|
|
21
|
+
it is ensured that the timestamp part of the ULID is not out of range.
|
|
15
22
|
|
|
16
23
|
`2.5.0`_ - 2024-04-26
|
|
17
24
|
---------------------
|
|
@@ -167,6 +174,7 @@ Changed
|
|
|
167
174
|
* The package now has no external dependencies.
|
|
168
175
|
* The test-coverage has been raised to 100%.
|
|
169
176
|
|
|
177
|
+
.. _2.7.0: https://github.com/mdomke/python-ulid/compare/2.6.0...2.7.0
|
|
170
178
|
.. _2.6.0: https://github.com/mdomke/python-ulid/compare/2.5.0...2.6.0
|
|
171
179
|
.. _2.5.0: https://github.com/mdomke/python-ulid/compare/2.4.0...2.5.0
|
|
172
180
|
.. _2.4.0: https://github.com/mdomke/python-ulid/compare/2.3.0...2.4.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: python-ulid
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: Universally unique lexicographically sortable identifier
|
|
5
5
|
Project-URL: Homepage, https://github.com/mdomke/python-ulid
|
|
6
6
|
Project-URL: Documentation, https://python-ulid.readthedocs.io
|
|
@@ -21,6 +21,7 @@ from ulid import constants
|
|
|
21
21
|
(base32.decode, "A" * (constants.REPR_LEN + 1)),
|
|
22
22
|
(base32.decode_timestamp, "A" * (constants.TIMESTAMP_REPR_LEN - 1)),
|
|
23
23
|
(base32.decode_timestamp, "A" * (constants.TIMESTAMP_REPR_LEN + 1)),
|
|
24
|
+
(base32.decode_timestamp, "Z" * constants.TIMESTAMP_REPR_LEN),
|
|
24
25
|
(base32.decode_randomness, "A" * (constants.RANDOMNESS_REPR_LEN - 1)),
|
|
25
26
|
(base32.decode_randomness, "A" * (constants.RANDOMNESS_REPR_LEN + 1)),
|
|
26
27
|
],
|
|
@@ -167,6 +167,37 @@ def test_ulid_invalid_input(constructor: Callable[[Params], ULID], value: Params
|
|
|
167
167
|
constructor(value)
|
|
168
168
|
|
|
169
169
|
|
|
170
|
+
@pytest.mark.parametrize(
|
|
171
|
+
("constructor", "value"),
|
|
172
|
+
[
|
|
173
|
+
(ULID, b"\x00" * 16),
|
|
174
|
+
(ULID.from_timestamp, 0),
|
|
175
|
+
(ULID.from_bytes, b"\x00" * 16),
|
|
176
|
+
(ULID.from_str, "0" * 26),
|
|
177
|
+
(ULID.from_hex, "0" * 32),
|
|
178
|
+
(ULID.from_uuid, uuid.UUID("0" * 32)),
|
|
179
|
+
],
|
|
180
|
+
)
|
|
181
|
+
def test_ulid_min_input(constructor: Callable[[Params], ULID], value: Params) -> None:
|
|
182
|
+
constructor(value)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@pytest.mark.parametrize(
|
|
186
|
+
("constructor", "value"),
|
|
187
|
+
[
|
|
188
|
+
(ULID, b"\xff" * 16),
|
|
189
|
+
(ULID.from_timestamp, 281474976710655),
|
|
190
|
+
(ULID.from_datetime, datetime.max.replace(tzinfo=timezone.utc)),
|
|
191
|
+
(ULID.from_bytes, b"\xff" * 16),
|
|
192
|
+
(ULID.from_str, "7" + "Z" * 25),
|
|
193
|
+
(ULID.from_hex, "f" * 32),
|
|
194
|
+
(ULID.from_uuid, uuid.UUID("f" * 32)),
|
|
195
|
+
],
|
|
196
|
+
)
|
|
197
|
+
def test_ulid_max_input(constructor: Callable[[Params], ULID], value: Params) -> None:
|
|
198
|
+
constructor(value)
|
|
199
|
+
|
|
200
|
+
|
|
170
201
|
def test_pydantic_protocol() -> None:
|
|
171
202
|
ulid = ULID()
|
|
172
203
|
|
|
@@ -74,23 +74,17 @@ class ULID:
|
|
|
74
74
|
|
|
75
75
|
Args:
|
|
76
76
|
value (bytes, None): A sequence of 16 bytes representing an encoded ULID.
|
|
77
|
-
validate (bool): If set to `True` validate if the timestamp part is valid.
|
|
78
77
|
|
|
79
78
|
Raises:
|
|
80
79
|
ValueError: If the provided value is not a valid encoded ULID.
|
|
81
80
|
"""
|
|
82
81
|
|
|
83
|
-
def __init__(self, value: bytes | None = None
|
|
82
|
+
def __init__(self, value: bytes | None = None) -> None:
|
|
84
83
|
if value is not None and len(value) != constants.BYTES_LEN:
|
|
85
84
|
raise ValueError("ULID has to be exactly 16 bytes long.")
|
|
86
85
|
self.bytes: bytes = (
|
|
87
86
|
value or ULID.from_timestamp(time.time_ns() // constants.NANOSECS_IN_MILLISECS).bytes
|
|
88
87
|
)
|
|
89
|
-
if value is not None and validate:
|
|
90
|
-
try:
|
|
91
|
-
self.datetime # noqa: B018
|
|
92
|
-
except ValueError as err:
|
|
93
|
-
raise ValueError("ULID timestamp is out of range.") from err
|
|
94
88
|
|
|
95
89
|
@classmethod
|
|
96
90
|
@validate_type(datetime)
|
|
@@ -137,7 +131,7 @@ class ULID:
|
|
|
137
131
|
>>> ULID.from_uuid(uuid4())
|
|
138
132
|
ULID(27Q506DP7E9YNRXA0XVD8Z5YSG)
|
|
139
133
|
"""
|
|
140
|
-
return cls(value.bytes
|
|
134
|
+
return cls(value.bytes)
|
|
141
135
|
|
|
142
136
|
@classmethod
|
|
143
137
|
@validate_type(bytes)
|
|
@@ -210,6 +210,9 @@ def decode_timestamp(encoded: str) -> bytes:
|
|
|
210
210
|
raise ValueError("ULID timestamp has to be exactly 10 characters long.")
|
|
211
211
|
lut = DECODE
|
|
212
212
|
values: bytes = bytes(encoded, "ascii")
|
|
213
|
+
# https://github.com/ulid/spec?tab=readme-ov-file#overflow-errors-when-parsing-base32-strings
|
|
214
|
+
if lut[values[0]] > 7:
|
|
215
|
+
raise ValueError(f"Timestamp value {encoded} is too large and will overflow 128-bits.")
|
|
213
216
|
return bytes(
|
|
214
217
|
[
|
|
215
218
|
((lut[values[0]] << 5) | lut[values[1]]) & 0xFF,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|