NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1172 most downloaded on PyPI
Universally unique lexicographically sortable identifier
Last release 2 months ago
20 Jul 2026
Release timing varies
gaps range from 2 weeks to 1.5 years
Most releases are documented
notes for 16 of 22 stable releases
Nothing withdrawn
no release was ever pulled
9 years old
22 releases · first in 2017
Renamed ULID.from_uuidv7 to ULID.from_uuid7 for naming symmetry with ULID.to_uuid7 , correcting an inconsistency introduced in 3.2.0 .
ULID.from_uuidv7 to ULID.from_uuid7 for naming symmetry with ULID.to_uuid7, correcting an inconsistency introduced in 3.2.0.⚠️ If you adopted
3.2.0or4.0.0: update calls fromULID.from_uuidv7(...)toULID.from_uuid7(...). This is the only change in this release.
For the full 4.0.0 feature set (the new ULIDGenerator, monotonicity policies, and default_generator), see the 4.0.0 release.
Full changelog: 4.0.0...4.0.1
ValueProvider and the ULID.provider class attribute have been removed. ULID generation is now handled by the new ULIDGenerator together with pluggable
ValueProvider and the ULID.provider class attribute have been removed. ULID generation is now handled by the new ULIDGenerator together with pluggable monotonicity policies. Code that replaced ULID.provider or subclassed ValueProvider must migrate to a custom ULIDGenerator assigned to ulid.default_generator.validate_type decorator was removed. The ULID.from_* constructors still raise TypeError for arguments of the wrong type, so runtime behaviour is unchanged.ULIDGenerator class that encapsulates ULID generation and can be configured with a custom clock, randomness source, and monotonicity policy.StrictMonotonicPolicy (the default), LaxMonotonicPolicy, and PureRandomPolicy — together with the MonotonicityPolicy protocol and the BaseMonotonicPolicy base class for implementing custom policies.ulid.default_generator that can be reassigned to route ULID() and the ULID.from_* constructors through a custom ULIDGenerator.import ulid
from ulid import ULIDGenerator, LaxMonotonicPolicy
# Before (removed):
# ULID.provider = MyValueProvider()
# After:
ulid.default_generator = ULIDGenerator(policy=LaxMonotonicPolicy())alternatively you can just create a generator object with the custom policy and create your ULID values with it
from ulid import ULIDGenerator, LaxMonotonicPolicy
generator = ULIDGenerator(policy=LaxMonotonicPolicy())
generator.generate()Full changelog: 3.2.1...4.0.0
One column per quarter.
Warning
Breaking change: the ValueProvider class and the ULID.provider class attribute have been removed. ULID generation is now handled by the new .ULIDGenerator together with pluggable monotonicity policies. To customize generation, construct a .ULIDGenerator (optionally with a custom clock, randomness source, or policy) and either call its generate() method or assign it to ulid.default_generator.
Added a public .ULIDGenerator class that encapsulates ULID generation and can be configured with a custom clock, randomness source, and monotonicity policy.
Added pluggable monotonicity policies: .StrictMonotonicPolicy (the default), .LaxMonotonicPolicy and .PureRandomPolicy, together with the .MonotonicityPolicy protocol and the .BaseMonotonicPolicy base class for implementing custom policies.
Added a module-level ulid.default_generator that can be reassigned to route ULID() and the ULID.from_* constructors through a custom .ULIDGenerator.
Removed the ValueProvider class and the ULID.provider attribute in favour of .ULIDGenerator and the monotonicity policies. Code that replaced ULID.provider or subclassed ValueProvider must migrate to a custom .ULIDGenerator assigned to ulid.default_generator.
Removed the internal validate_type decorator. The ULID.from_* constructors still raise TypeError for arguments of the wrong type, so runtime behaviour is unchanged.
Fix source distribution build
Fix source distribution build
Corrected the build and publish pipeline and the generated source distribution. This release contains no changes to the library code.
Added transparent bidirectional UUIDv7 conversion methods ( ULID.to_uuid7 and ULID.from_uuidv7 ) @pirate .
ULID.to_uuid7 and ULID.from_uuidv7) @pirate.--uuid7 option to the CLI's show command to convert and output a ULID as an RFC 4122 compliant UUIDv7.typing-extensions only when running on Python < 3.11 @musicinmybrain.uv and poethepoet.uv during synchronization @jaseemabid.Added Python 3.13 to the trove classifiers.
Raise TypeError instead of ValueError if constructor is called with value of wrong type.
TypeError instead of ValueError if constructor is called with value of wrong type.ruff linter rules and switch to hatch fmt.Raise TypeError instead of ValueError if constructor is called with value of wrong type.
Update ruff linter rules and switch to hatch fmt.
Added .ULID.parse-method, which allows to create a .ULID-instance from an arbitrary supported input value. @perrotuerto.
Documentation bug in the example of .ULID.milliseconds @tsugumi-sys.
Ensure that the validation of ULID 's timestamp component aligns more closely with the ULID specification. #27 @somnam
Use stricter validation when a ULID value from user input. When using ULID.from_str() we will check if the characters match the base32 alphabet. In ge
Generate a more accurate JSON schema with Pydantic’s BaseModel.model_json_schema() . This includes a specification for string and byte representations
BaseModel.model_json_schema(). This includes a specification for string and byte representations.Nothing published for this version
ULID objects are now properly serialized when used as Pydantic types @Avihais12344 #21
ULID objects can now be converted to bytes with bytes(ulid).
bytes(ulid).time.time_ns() when generating ULIDs for improved performance #16 #12Added a new flag --uuid4 to the CLI show command, that converts the provided ULID into an RFC 4122 compliant UUID.
--uuid4 to the CLI show command, that converts the provided ULID
into an RFC 4122 compliant UUID.ulid build command allows the use of the special value - for all options to read its
inputs from stdin. E.g. $ date --iso-8601 | python -m ulid build --from-datetime -
01HAT9PVR02T3S13XB48S7GEHE
The new method ULID.to_uuid4 can be used to create an RFC 4122 compliant UUID from an existing ULID #5.
ULID.to_uuid4 can be used to create an RFC 4122 compliant UUID from
an existing ULID #5.validate_types-decorator that is used for all ULID.from_*-methods to check type
correctness at runtime has now better support for type hints.
Thanks to @johnpaulettNothing published for this version
Added __version__ variable to package.
Added support for Python 3.10.
Added __version__ variable to package.
Enable tool based type checking as described in PEP-0561_ by adding the py.typed marker.
Enable tool based type checking as described in `PEP-0561`_ by adding the py.typed marker.
Use GitHub actions instead of Travis.
Nothing published for this version
Added the named constructors .ULID.from_datetime, .ULID.from_timestamp and .ULID.from_hex.
Added type annotations
Added the named constructors .ULID.from_datetime, .ULID.from_timestamp and .ULID.from_hex.
Dropped support for Python 2. Only Python 3.6+ is supported.
The named constructor ULID.new has been removed. Use one of the specifc named constructors instead. For a new .ULID created from the current timestamp use the standard constructor.
# old
ulid = ULID.new()
ulid = ULID.new(time.time())
ulid = ULID.new(datetime.now())
# new
ulid = ULID()
ulid = ULID.from_timestamp(time.time())
ulid = ULID.from_datetime(datetime.now())
The ULID.str and ULID.int methods have been removed in favour of the more Pythonic special dunder-methods. Use str(ulid) and int(ulid) instead.
Added the property .ULID.hex that returns a hex representation of the .ULID.
>>> ULID().hex
'0171caa5459a8631a6894d072c8550a8'
Equality checks and ordering now also work with str-instances.
The package now has no external dependencies.
The test-coverage has been raised to 100%.
Added type annotations
Added the named constructors ULID.from_datetime() , ULID.from_timestamp() and ULID.from_hex() .
Dropped support for Python 2. Only Python 3.6+ is supported.
The named constructor ULID.new has been removed. Use one of the specifc named constructors instead. For a new ULID created from the current timestamp use the standard constructor.
The ULID.str and ULID.int methods have been removed in favour of the more Pythonic special dunder-methods. Use str(ulid) and int(ulid) instead.
Added the property ULID.hex() that returns a hex representation of the ULID .
ULID () . hex '0171caa5459a8631a6894d072c8550a8'
Equality checks and ordering now also work with str -instances.
The package now has no external dependencies.
The test-coverage has been raised to 100%.
On this page
Changelog
4.0.1 - 2026-07-20
Changed
4.0.0 - 2026-07-20
Added
Removed
3.2.1 - 2026-07-17
Fixed
3.2.0 - 2026-07-17
Added
Changed
Fixed
3.1.0 - 2025-08-18
Changed
Fixed
3.0.0 - 2024-10-11
Changed
Added
Fixed
2.7.0 - 2024-06-17
Changed
2.6.0 - 2024-05-26
Changed
2.5.0 - 2024-04-26
Changed
2.4.0 - 2024-04-02
Added
2.3.0 - 2024-03-21
Added
Changed
2.2.0 - 2023-09-21
Added
2.1.0 - 2023-09-21
Added
Changed
2.0.0 - 2023-09-20
Added
Changed
1.1.0 - 2022-03-10
Added
1.0.3 - 2021-07-14
Added
Changed
1.0.0 - 2020-04-30
Added
Changed
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →