Source code for sqlspec.utils.uuids

"""UUID and ID generation utilities with optional acceleration.

Provides wrapper functions for UUID construction, uuid3, uuid4, uuid5, uuid6,
uuid7, and nanoid generation. Uses uuid-utils and fastnanoid packages for
performance when available, falling back to the standard library.

When uuid-utils is installed:
    - uuid3, uuid4, uuid5, uuid6, uuid7 use the faster Rust implementation
    - uuid6 and uuid7 provide proper time-ordered UUIDs per RFC 9562

When uuid-utils is NOT installed:
    - uuid3, uuid4, uuid5 fall back silently to stdlib (equivalent output)
    - uuid6, uuid7 fall back to uuid4 with a warning (different UUID version)

When fastnanoid is installed:
    - nanoid() uses the Rust implementation for 21-char URL-safe IDs

When fastnanoid is NOT installed:
    - nanoid() falls back to uuid4().hex with a warning (different format)
"""

import uuid as _uuid_mod
import warnings
from typing import Any, cast
from uuid import NAMESPACE_DNS, NAMESPACE_OID, NAMESPACE_URL, NAMESPACE_X500, UUID
from uuid import uuid3 as _stdlib_uuid3
from uuid import uuid4 as _stdlib_uuid4
from uuid import uuid5 as _stdlib_uuid5

from sqlspec.typing import NANOID_INSTALLED, UUID_UTILS_INSTALLED
from sqlspec.utils.module_loader import import_optional

__all__ = (
    "NAMESPACE_DNS",
    "NAMESPACE_OID",
    "NAMESPACE_URL",
    "NAMESPACE_X500",
    "NANOID_INSTALLED",
    "UUID_UTILS_INSTALLED",
    "nanoid",
    "uuid3",
    "uuid4",
    "uuid5",
    "uuid6",
    "uuid7",
    "uuid_from_bytes",
    "uuid_from_int",
    "uuid_from_string",
)


_uuid_utils_mod: Any | None = import_optional("uuid_utils.compat")
_uuid_utils_native_mod: Any | None = import_optional("uuid_utils")
_fastnanoid_mod: Any | None = import_optional("fastnanoid")


[docs] def uuid_from_string(value: str) -> "UUID": """Construct a stdlib UUID from text, using Rust parsing when available. Args: value: Canonical, hexadecimal, URN, or braced UUID text accepted by ``uuid.UUID`` and ``uuid_utils.UUID``. Returns: A standard-library UUID suitable for native database drivers. """ module = _uuid_utils_native_mod if module is None: return UUID(value) return UUID(int=module.UUID(value).int)
[docs] def uuid_from_bytes(value: bytes) -> "UUID": """Construct a stdlib UUID from its 16-byte representation. The stdlib constructor is retained for this shape because converting a Rust UUID back to the driver-compatible stdlib type is slower. Args: value: UUID bytes in big-endian order. Returns: A standard-library UUID. """ return UUID(bytes=value)
[docs] def uuid_from_int(value: int) -> "UUID": """Construct a stdlib UUID from its 128-bit integer value. Args: value: UUID integer in the inclusive range ``0`` through ``2**128 - 1``. Returns: A standard-library UUID. """ return UUID(int=value)
[docs] def uuid3(name: str, namespace: "UUID | None" = None) -> "UUID": """Generate a deterministic UUID (version 3) using MD5 hash. Uses uuid-utils for performance when available, falls back to standard library uuid.uuid3() silently (equivalent output). Args: name: The name to hash within the namespace. namespace: The namespace UUID. Defaults to NAMESPACE_DNS if not provided. Returns: A deterministic UUID based on namespace and name. """ module = _uuid_utils_mod namespace_value = NAMESPACE_DNS if namespace is None else namespace if module is None: return _stdlib_uuid3(namespace_value, name) return cast("UUID", module.uuid3(namespace_value, name))
[docs] def uuid4() -> "UUID": """Generate a random UUID (version 4). Uses uuid-utils for performance when available, falls back to standard library uuid.uuid4() silently (equivalent output). Returns: A randomly generated UUID. """ module = _uuid_utils_mod if module is None: return _stdlib_uuid4() return cast("UUID", module.uuid4())
[docs] def uuid5(name: str, namespace: "UUID | None" = None) -> "UUID": """Generate a deterministic UUID (version 5) using SHA-1 hash. Uses uuid-utils for performance when available, falls back to standard library uuid.uuid5() silently (equivalent output). Args: name: The name to hash within the namespace. namespace: The namespace UUID. Defaults to NAMESPACE_DNS if not provided. Returns: A deterministic UUID based on namespace and name. """ module = _uuid_utils_mod namespace_value = NAMESPACE_DNS if namespace is None else namespace if module is None: return _stdlib_uuid5(namespace_value, name) return cast("UUID", module.uuid5(namespace_value, name))
[docs] def uuid6() -> "UUID": """Generate a time-ordered UUID (version 6). Uses uuid-utils when available, falls back to Python 3.14+ native uuid.uuid6() or uuid4() with a warning. UUIDv6 is lexicographically sortable by timestamp, making it suitable for database primary keys. It is a reordering of UUIDv1 fields to improve database performance. Returns: A time-ordered UUID, or a random UUID if time-ordered generation unavailable. """ module = _uuid_utils_mod if module is not None: return cast("UUID", module.uuid6()) native_uuid6 = getattr(_uuid_mod, "uuid6", None) if native_uuid6 is not None: return cast("UUID", native_uuid6()) warnings.warn( "uuid-utils not installed and Python < 3.14, falling back to uuid4 for UUID v6 generation. " "Install with: pip install sqlspec[uuid]", UserWarning, stacklevel=2, ) return _stdlib_uuid4()
[docs] def uuid7() -> "UUID": """Generate a time-ordered UUID (version 7). Uses uuid-utils when available, falls back to Python 3.14+ native uuid.uuid7() or uuid4() with a warning. UUIDv7 is the recommended time-ordered UUID format per RFC 9562, providing millisecond precision timestamps. It is designed for modern distributed systems and database primary keys. Returns: A time-ordered UUID, or a random UUID if time-ordered generation unavailable. """ module = _uuid_utils_mod if module is not None: return cast("UUID", module.uuid7()) native_uuid7 = getattr(_uuid_mod, "uuid7", None) if native_uuid7 is not None: return cast("UUID", native_uuid7()) warnings.warn( "uuid-utils not installed and Python < 3.14, falling back to uuid4 for UUID v7 generation. " "Install with: pip install sqlspec[uuid]", UserWarning, stacklevel=2, ) return _stdlib_uuid4()
[docs] def nanoid() -> str: """Generate a Nano ID. Uses fastnanoid for performance when available. When fastnanoid is not installed, falls back to uuid4().hex with a warning. Nano IDs are URL-safe, compact 21-character identifiers suitable for use as primary keys or short identifiers. The default alphabet uses A-Za-z0-9_- characters. Returns: A 21-character Nano ID string, or 32-character UUID hex if fastnanoid unavailable. """ module = _fastnanoid_mod if module is None: warnings.warn( "fastnanoid not installed, falling back to uuid4.hex for Nano ID generation. " "Install with: pip install sqlspec[nanoid]", UserWarning, stacklevel=2, ) return _nanoid_impl() return cast("str", module.generate())
def _nanoid_impl() -> str: return _stdlib_uuid4().hex