Use ulid-transform for constructing ulids (#88939)

* Use ulid-transform for constructing ulids

A future PR will use the new library to reduce the storage
overhead of ulids in the database

* tweak

* tweak

* bump
This commit is contained in:
J. Nick Koston 2023-02-28 20:09:47 -06:00 committed by GitHub
parent e0bdb3ecc3
commit 8f6cfc25c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 8 additions and 52 deletions

View file

@ -871,7 +871,7 @@ class Event:
self.origin = origin
self.time_fired = time_fired or dt_util.utcnow()
self.context: Context = context or Context(
id=ulid_util.ulid(dt_util.utc_to_timestamp(self.time_fired))
id=ulid_util.ulid_at_time(dt_util.utc_to_timestamp(self.time_fired))
)
def as_dict(self) -> dict[str, Any]:
@ -1533,7 +1533,7 @@ class StateMachine:
now = dt_util.utcnow()
if context is None:
context = Context(id=ulid_util.ulid(dt_util.utc_to_timestamp(now)))
context = Context(id=ulid_util.ulid_at_time(dt_util.utc_to_timestamp(now)))
state = State(
entity_id,
new_state,

View file

@ -44,6 +44,7 @@ requests==2.28.1
scapy==2.5.0
sqlalchemy==2.0.4
typing-extensions>=4.5.0,<5.0
ulid-transform==0.3.1
voluptuous-serialize==2.6.0
voluptuous==0.13.1
yarl==1.8.1

View file

@ -1,21 +1,11 @@
"""Helpers to generate ulids."""
from __future__ import annotations
from random import getrandbits
import time
from ulid_transform import ulid_at_time, ulid_hex
def ulid_hex() -> str:
"""Generate a ULID in lowercase hex that will work for a UUID.
This ulid should not be used for cryptographically secure
operations.
This string can be converted with https://github.com/ahawker/ulid
ulid.from_uuid(uuid.UUID(ulid_hex))
"""
return f"{int(time.time()*1000):012x}{getrandbits(80):020x}"
__all__ = ["ulid", "ulid_hex", "ulid_at_time"]
def ulid(timestamp: float | None = None) -> str:
@ -35,41 +25,4 @@ def ulid(timestamp: float | None = None) -> str:
import ulid
ulid.parse(ulid_util.ulid())
"""
ulid_bytes = int((timestamp or time.time()) * 1000).to_bytes(
6, byteorder="big"
) + int(getrandbits(80)).to_bytes(10, byteorder="big")
# This is base32 crockford encoding with the loop unrolled for performance
#
# This code is adapted from:
# https://github.com/ahawker/ulid/blob/06289583e9de4286b4d80b4ad000d137816502ca/ulid/base32.py#L102
#
enc = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
return (
enc[(ulid_bytes[0] & 224) >> 5]
+ enc[ulid_bytes[0] & 31]
+ enc[(ulid_bytes[1] & 248) >> 3]
+ enc[((ulid_bytes[1] & 7) << 2) | ((ulid_bytes[2] & 192) >> 6)]
+ enc[((ulid_bytes[2] & 62) >> 1)]
+ enc[((ulid_bytes[2] & 1) << 4) | ((ulid_bytes[3] & 240) >> 4)]
+ enc[((ulid_bytes[3] & 15) << 1) | ((ulid_bytes[4] & 128) >> 7)]
+ enc[(ulid_bytes[4] & 124) >> 2]
+ enc[((ulid_bytes[4] & 3) << 3) | ((ulid_bytes[5] & 224) >> 5)]
+ enc[ulid_bytes[5] & 31]
+ enc[(ulid_bytes[6] & 248) >> 3]
+ enc[((ulid_bytes[6] & 7) << 2) | ((ulid_bytes[7] & 192) >> 6)]
+ enc[(ulid_bytes[7] & 62) >> 1]
+ enc[((ulid_bytes[7] & 1) << 4) | ((ulid_bytes[8] & 240) >> 4)]
+ enc[((ulid_bytes[8] & 15) << 1) | ((ulid_bytes[9] & 128) >> 7)]
+ enc[(ulid_bytes[9] & 124) >> 2]
+ enc[((ulid_bytes[9] & 3) << 3) | ((ulid_bytes[10] & 224) >> 5)]
+ enc[ulid_bytes[10] & 31]
+ enc[(ulid_bytes[11] & 248) >> 3]
+ enc[((ulid_bytes[11] & 7) << 2) | ((ulid_bytes[12] & 192) >> 6)]
+ enc[(ulid_bytes[12] & 62) >> 1]
+ enc[((ulid_bytes[12] & 1) << 4) | ((ulid_bytes[13] & 240) >> 4)]
+ enc[((ulid_bytes[13] & 15) << 1) | ((ulid_bytes[14] & 128) >> 7)]
+ enc[(ulid_bytes[14] & 124) >> 2]
+ enc[((ulid_bytes[14] & 3) << 3) | ((ulid_bytes[15] & 224) >> 5)]
+ enc[ulid_bytes[15] & 31]
)
return ulid_at_time(timestamp or time.time())

View file

@ -50,6 +50,7 @@ dependencies = [
"pyyaml==6.0",
"requests==2.28.1",
"typing-extensions>=4.5.0,<5.0",
"ulid-transform==0.3.1",
"voluptuous==0.13.1",
"voluptuous-serialize==2.6.0",
"yarl==1.8.1",

View file

@ -24,6 +24,7 @@ python-slugify==4.0.1
pyyaml==6.0
requests==2.28.1
typing-extensions>=4.5.0,<5.0
ulid-transform==0.3.1
voluptuous==0.13.1
voluptuous-serialize==2.6.0
yarl==1.8.1