python-ulid 4.0.0__tar.gz → 4.0.1__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-4.0.0 → python_ulid-4.0.1}/CHANGELOG.rst +8 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/PKG-INFO +1 -1
- {python_ulid-4.0.0 → python_ulid-4.0.1}/tests/test_ulid.py +6 -6
- {python_ulid-4.0.0 → python_ulid-4.0.1}/ulid/__init__.py +6 -6
- {python_ulid-4.0.0 → python_ulid-4.0.1}/.envrc +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/.github/workflows/lint-and-test.yml +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/.github/workflows/publish.yml +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/.gitignore +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/.pre-commit-config.yaml +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/.readthedocs.yml +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/.ruff_defaults.toml +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/AGENTS.md +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/CONTEXT.md +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/CONTRIBUTING.md +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/LICENSE +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/README.rst +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/docs/Makefile +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/docs/requirements.txt +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/docs/source/api.rst +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/docs/source/changelog.rst +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/docs/source/conf.py +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/docs/source/index.rst +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/logo.png +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/pyproject.toml +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/tests/__init__.py +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/tests/test_base32.py +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/tests/test_cli.py +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/ulid/__main__.py +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/ulid/base32.py +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/ulid/constants.py +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/ulid/py.typed +0 -0
- {python_ulid-4.0.0 → python_ulid-4.0.1}/uv.lock +0 -0
|
@@ -5,6 +5,13 @@ Changelog
|
|
|
5
5
|
|
|
6
6
|
Versions follow `Semantic Versioning <http://www.semver.org>`_
|
|
7
7
|
|
|
8
|
+
`4.0.1`_ - 2026-07-20
|
|
9
|
+
---------------------
|
|
10
|
+
Changed
|
|
11
|
+
~~~~~~~
|
|
12
|
+
* Renamed ``ULID.from_uuidv7`` to :meth:`.ULID.from_uuid7` for naming symmetry with
|
|
13
|
+
:meth:`.ULID.to_uuid7`, correcting an inconsistency introduced in 3.2.0.
|
|
14
|
+
|
|
8
15
|
`4.0.0`_ - 2026-07-20
|
|
9
16
|
---------------------
|
|
10
17
|
|
|
@@ -258,6 +265,7 @@ Changed
|
|
|
258
265
|
* The package now has no external dependencies.
|
|
259
266
|
* The test-coverage has been raised to 100%.
|
|
260
267
|
|
|
268
|
+
.. _4.0.1: https://github.com/mdomke/python-ulid/compare/4.0.0...4.0.1
|
|
261
269
|
.. _4.0.0: https://github.com/mdomke/python-ulid/compare/3.2.1...4.0.0
|
|
262
270
|
.. _3.2.1: https://github.com/mdomke/python-ulid/compare/3.2.0...3.2.1
|
|
263
271
|
.. _3.2.0: https://github.com/mdomke/python-ulid/compare/3.1.0...3.2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-ulid
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.1
|
|
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
|
|
@@ -161,7 +161,7 @@ def test_idempotency() -> None:
|
|
|
161
161
|
assert ULID.from_bytes(ulid.bytes) == ulid
|
|
162
162
|
assert ULID.from_str(str(ulid)) == ulid
|
|
163
163
|
assert ULID.from_uuid(ulid.to_uuid()) == ulid
|
|
164
|
-
assert ULID.
|
|
164
|
+
assert ULID.from_uuid7(ulid.to_uuid7(compliant=False)) == ulid
|
|
165
165
|
assert ULID.from_int(int(ulid)) == ulid
|
|
166
166
|
assert ULID.from_hex(ulid.hex) == ulid
|
|
167
167
|
assert ULID.parse(ulid) == ulid
|
|
@@ -209,7 +209,7 @@ def test_uuid7_perfect_roundtrip() -> None:
|
|
|
209
209
|
"""Test perfect round-trip conversion with compliant=False."""
|
|
210
210
|
ulid = ULID()
|
|
211
211
|
uuid7 = ulid.to_uuid7(compliant=False)
|
|
212
|
-
ulid_restored = ULID.
|
|
212
|
+
ulid_restored = ULID.from_uuid7(uuid7)
|
|
213
213
|
# Perfect round-trip: all 128 bits should be identical
|
|
214
214
|
assert ulid_restored == ulid
|
|
215
215
|
assert ulid_restored.bytes == ulid.bytes
|
|
@@ -220,7 +220,7 @@ def test_uuid7_compliant_roundtrip() -> None:
|
|
|
220
220
|
"""Test round-trip with compliant=True preserves timestamp but loses some randomness."""
|
|
221
221
|
ulid = ULID()
|
|
222
222
|
uuid7 = ulid.to_uuid7(compliant=True)
|
|
223
|
-
ulid_restored = ULID.
|
|
223
|
+
ulid_restored = ULID.from_uuid7(uuid7)
|
|
224
224
|
# Timestamp should be perfectly preserved
|
|
225
225
|
assert ulid_restored.milliseconds == ulid.milliseconds
|
|
226
226
|
# Full ULID won't match due to lost randomness in version/variant bits (6 bits lost)
|
|
@@ -236,7 +236,7 @@ def test_uuid7_timestamp_preservation() -> None:
|
|
|
236
236
|
# Test both compliant and non-compliant modes
|
|
237
237
|
for compliant in [False, True]:
|
|
238
238
|
uuid7 = ulid.to_uuid7(compliant=compliant)
|
|
239
|
-
ulid_from_uuid7 = ULID.
|
|
239
|
+
ulid_from_uuid7 = ULID.from_uuid7(uuid7)
|
|
240
240
|
|
|
241
241
|
# Check timestamp is perfectly preserved (exact millisecond match)
|
|
242
242
|
assert ulid_from_uuid7.milliseconds == ulid.milliseconds
|
|
@@ -271,7 +271,7 @@ def test_uuid7_same_millisecond() -> None:
|
|
|
271
271
|
|
|
272
272
|
# Perfect round-trip for all
|
|
273
273
|
for ulid, uuid7 in zip(ulids, uuids, strict=True):
|
|
274
|
-
assert ULID.
|
|
274
|
+
assert ULID.from_uuid7(uuid7) == ulid
|
|
275
275
|
|
|
276
276
|
|
|
277
277
|
def test_from_uuid7_with_external_uuid() -> None:
|
|
@@ -289,7 +289,7 @@ def test_from_uuid7_with_external_uuid() -> None:
|
|
|
289
289
|
uuid_int = (timestamp_ms << 80) | (0x7 << 76) | (rand_a << 64) | (0x2 << 62) | rand_b
|
|
290
290
|
uuid7 = uuid.UUID(bytes=uuid_int.to_bytes(16, byteorder="big"))
|
|
291
291
|
|
|
292
|
-
ulid = ULID.
|
|
292
|
+
ulid = ULID.from_uuid7(uuid7)
|
|
293
293
|
|
|
294
294
|
# Check timestamp is correctly extracted (should be exact since it's in milliseconds)
|
|
295
295
|
assert ulid.milliseconds == timestamp_ms
|
|
@@ -456,9 +456,9 @@ class ULID:
|
|
|
456
456
|
Examples:
|
|
457
457
|
|
|
458
458
|
>>> ulid = ULID()
|
|
459
|
-
>>> uuid7 = ulid.
|
|
460
|
-
>>> assert ULID.
|
|
461
|
-
>>> uuid7_compliant = ulid.
|
|
459
|
+
>>> uuid7 = ulid.to_uuid7() # Perfect round-trip
|
|
460
|
+
>>> assert ULID.from_uuid7(uuid7) == ulid
|
|
461
|
+
>>> uuid7_compliant = ulid.to_uuid7(compliant=True) # RFC 4122 compliant
|
|
462
462
|
>>> uuid7_compliant.version
|
|
463
463
|
7
|
|
464
464
|
"""
|
|
@@ -487,17 +487,17 @@ class ULID:
|
|
|
487
487
|
return uuid.UUID(bytes=uuid_bytes)
|
|
488
488
|
|
|
489
489
|
@classmethod
|
|
490
|
-
def
|
|
490
|
+
def from_uuid7(cls, value: uuid.UUID) -> Self:
|
|
491
491
|
"""Create a new :class:`ULID` from a UUIDv7 (:class:`uuid.UUID` version 7).
|
|
492
492
|
|
|
493
493
|
Extracts the timestamp from the UUIDv7's first 48 bits (milliseconds since epoch)
|
|
494
494
|
and the remaining 80 bits as randomness. The timestamp is always transparently
|
|
495
|
-
preserved, providing perfect round-trip conversion with :meth:`
|
|
495
|
+
preserved, providing perfect round-trip conversion with :meth:`to_uuid7`.
|
|
496
496
|
|
|
497
497
|
Examples:
|
|
498
498
|
|
|
499
499
|
>>> uuid7 = uuid.UUID("01936c5e-f4c0-7000-8000-000000000000")
|
|
500
|
-
>>> ulid = ULID.
|
|
500
|
+
>>> ulid = ULID.from_uuid7(uuid7)
|
|
501
501
|
>>> ulid.datetime
|
|
502
502
|
datetime.datetime(2025, 11, 10, ...)
|
|
503
503
|
"""
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|