Coverage for langsmith/_internal/_uuid.py: 10%
21 statements
« prev ^ index » next coverage.py v7.10.1, created at 2025-12-11 16:15 -0800
« prev ^ index » next coverage.py v7.10.1, created at 2025-12-11 16:15 -0800
1"""UUID helpers backed by uuid-utils."""
3from __future__ import annotations
5import uuid
6import warnings
7from typing import Final
9from uuid_utils.compat import uuid7 as _uuid_utils_uuid7
11_NANOS_PER_SECOND: Final = 1_000_000_000
14def _to_timestamp_and_nanos(nanoseconds: int) -> tuple[int, int]:
15 """Split a nanosecond timestamp into seconds and remaining nanoseconds."""
16 seconds, nanos = divmod(nanoseconds, _NANOS_PER_SECOND)
17 return seconds, nanos
20def uuid7(nanoseconds: int | None = None) -> uuid.UUID:
21 """Generate a UUID from a Unix timestamp in nanoseconds and random bits.
23 UUIDv7 objects feature monotonicity within a millisecond.
25 Args:
26 nanoseconds: Optional ns timestamp. If not provided, uses current time.
27 """
28 # --- 48 --- -- 4 -- --- 12 --- -- 2 -- --- 30 --- - 32 -
29 # unix_ts_ms | version | counter_hi | variant | counter_lo | random
30 #
31 # 'counter = counter_hi | counter_lo' is a 42-bit counter constructed
32 # with Method 1 of RFC 9562, §6.2, and its MSB is set to 0.
33 #
34 # 'random' is a 32-bit random value regenerated for every new UUID.
35 #
36 # If multiple UUIDs are generated within the same millisecond, the LSB
37 # of 'counter' is incremented by 1. When overflowing, the timestamp is
38 # advanced and the counter is reset to a random 42-bit integer with MSB
39 # set to 0.
41 # For now, just delegate to the uuid_utils implementation
42 if nanoseconds is None:
43 return _uuid_utils_uuid7()
44 seconds, nanos = _to_timestamp_and_nanos(nanoseconds)
45 return _uuid_utils_uuid7(timestamp=seconds, nanos=nanos)
48def is_uuid_v7(uuid_obj: uuid.UUID) -> bool:
49 """Check if a UUID is version 7.
51 Args:
52 uuid_obj: The UUID to check.
54 Returns:
55 True if the UUID is version 7, False otherwise.
56 """
57 return uuid_obj.version == 7
60_UUID_V7_WARNING_EMITTED = False
63def warn_if_not_uuid_v7(uuid_obj: uuid.UUID, id_type: str) -> None:
64 """Warn if a UUID is not version 7.
66 Args:
67 uuid_obj: The UUID to check.
68 id_type: The type of ID (e.g., "run_id", "trace_id") for the warning message.
69 """
70 global _UUID_V7_WARNING_EMITTED
71 if not is_uuid_v7(uuid_obj) and not _UUID_V7_WARNING_EMITTED:
72 _UUID_V7_WARNING_EMITTED = True
73 warnings.warn(
74 (
75 "LangSmith now uses UUID v7 for run and trace identifiers. "
76 "This warning appears when passing custom IDs. "
77 "Please use: from langsmith import uuid7\n"
78 " id = uuid7()\n"
79 "Future versions will require UUID v7."
80 ),
81 UserWarning,
82 stacklevel=3,
83 )