Skip to content

Commit

Permalink
Add std library compatible UUID generation functions (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
aminalaee authored Oct 27, 2023
1 parent a235db5 commit 888809d
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 0 deletions.
46 changes: 46 additions & 0 deletions python/uuid_utils/compat/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import uuid

import uuid_utils


def uuid1(node=None, clock_seq=None):
"""Generate a UUID from a host ID, sequence number, and the current time.
If 'node' is not given, getnode() is used to obtain the hardware
address. If 'clock_seq' is given, it is used as the sequence number;
otherwise a random 14-bit sequence number is chosen."""
return uuid.UUID(int=uuid_utils.uuid1(node, clock_seq).int)


def uuid3(namespace, name):
"""Generate a UUID from the MD5 hash of a namespace UUID and a name."""
namespace = uuid_utils.UUID(namespace.hex) if namespace else namespace
return uuid.UUID(int=uuid_utils.uuid3(namespace, name).int)


def uuid4():
"""Generate a random UUID."""
return uuid.UUID(int=uuid_utils.uuid4().int)


def uuid5(namespace, name):
"""Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
namespace = uuid_utils.UUID(namespace.hex) if namespace else namespace
return uuid.UUID(int=uuid_utils.uuid5(namespace, name).int)


def uuid6(node=None, timestamp=None):
"""Generate a version 6 UUID using the given timestamp and a host ID.
This is similar to version 1 UUIDs,
except that it is lexicographically sortable by timestamp.
"""
return uuid.UUID(int=uuid_utils.uuid6(node, timestamp).int)


def uuid7(timestamp=None):
"""Generate a version 7 UUID using a time value and random bytes."""
return uuid.UUID(int=uuid_utils.uuid7(timestamp).int)


def uuid8(bytes):
"""Generate a custom UUID comprised almost entirely of user-supplied bytes.."""
return uuid.UUID(bytes=uuid_utils.uuid8(bytes).bytes)
41 changes: 41 additions & 0 deletions python/uuid_utils/compat/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from uuid import UUID

from typing_extensions import TypeAlias

# Because UUID has properties called int and bytes we need to rename these temporarily.
_Int: TypeAlias = int
_Bytes: TypeAlias = bytes

def uuid1(node: _Int | None = None, clock_seq: _Int | None = None) -> UUID:
"""Generate a UUID from a host ID, sequence number, and the current time.
If 'node' is not given, getnode() is used to obtain the hardware
address. If 'clock_seq' is given, it is used as the sequence number;
otherwise a random 14-bit sequence number is chosen."""
...

def uuid3(namespace: UUID, name: str) -> UUID:
"""Generate a UUID from the MD5 hash of a namespace UUID and a name."""
...

def uuid4() -> UUID:
"""Generate a random UUID."""
...

def uuid5(namespace: UUID, name: str) -> UUID:
"""Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
...

def uuid6(node: _Int | None = None, timestamp: _Int | None = None) -> UUID:
"""Generate a version 6 UUID using the given timestamp and a host ID.
This is similar to version 1 UUIDs,
except that it is lexicographically sortable by timestamp.
"""
...

def uuid7(timestamp: _Int | None = None) -> UUID:
"""Generate a version 7 UUID using a time value and random bytes."""
...

def uuid8(bytes: _Bytes) -> UUID:
"""Generate a custom UUID comprised almost entirely of user-supplied bytes.."""
...
Empty file added tests/test_compat/__init__.py
Empty file.
23 changes: 23 additions & 0 deletions tests/test_compat/test_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import uuid
from typing import Callable

import pytest

from uuid_utils.compat import uuid1, uuid3, uuid4, uuid5, uuid6, uuid7, uuid8


@pytest.mark.parametrize("generator", [uuid1, uuid4, uuid6, uuid7])
def test_uuid(generator: Callable[..., uuid.UUID]) -> None:
assert isinstance(generator(), uuid.UUID)


def test_uuid3() -> None:
assert isinstance(uuid3(uuid.NAMESPACE_DNS, "python.org"), uuid.UUID)


def test_uuid5() -> None:
assert isinstance(uuid5(uuid.NAMESPACE_DNS, "python.org"), uuid.UUID)


def test_uuid8() -> None:
assert isinstance(uuid8(b"1234567812345678"), uuid.UUID)

0 comments on commit 888809d

Please sign in to comment.