4646
4747import os
4848
49+ from enum import Enum
50+
51+
4952__author__ = 'Ka-Ping Yee <[email protected] >' 5053
5154RESERVED_NCS , RFC_4122 , RESERVED_MICROSOFT , RESERVED_FUTURE = [
5558int_ = int # The built-in int type
5659bytes_ = bytes # The built-in bytes type
5760
58- class UUID (object ):
61+
62+ class SafeUUID (Enum ):
63+ safe = 0
64+ unsafe = - 1
65+ unknown = None
66+
67+
68+ class UUID :
5969 """Instances of the UUID class represent UUIDs as specified in RFC 4122.
6070 UUID objects are immutable, hashable, and usable as dictionary keys.
6171 Converting a UUID to a string with str() yields something in the form
@@ -101,10 +111,15 @@ class UUID(object):
101111
102112 version the UUID version number (1 through 5, meaningful only
103113 when the variant is RFC_4122)
114+
115+ is_safe An enum indicating whether the UUID has been generated in
116+ a way that is safe for multiprocessing applications, via
117+ uuid_generate_time_safe(3).
104118 """
105119
106120 def __init__ (self , hex = None , bytes = None , bytes_le = None , fields = None ,
107- int = None , version = None ):
121+ int = None , version = None ,
122+ * , is_safe = SafeUUID .unknown ):
108123 r"""Create a UUID from either a string of 32 hexadecimal digits,
109124 a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
110125 in little-endian order as the 'bytes_le' argument, a tuple of six
@@ -128,6 +143,10 @@ def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
128143 be given. The 'version' argument is optional; if given, the resulting
129144 UUID will have its variant and version set according to RFC 4122,
130145 overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
146+
147+ is_safe is an enum exposed as an attribute on the instance. It
148+ indicates whether the UUID has been generated in a way that is safe
149+ for multiprocessing applications, via uuid_generate_time_safe(3).
131150 """
132151
133152 if [hex , bytes , bytes_le , fields , int ].count (None ) != 4 :
@@ -182,6 +201,7 @@ def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
182201 int &= ~ (0xf000 << 64 )
183202 int |= version << 76
184203 self .__dict__ ['int' ] = int
204+ self .__dict__ ['is_safe' ] = is_safe
185205
186206 def __eq__ (self , other ):
187207 if isinstance (other , UUID ):
@@ -472,10 +492,17 @@ def _netbios_getnode():
472492 for libname in _libnames :
473493 try :
474494 lib = ctypes .CDLL (ctypes .util .find_library (libname ))
475- except Exception :
495+ except Exception : # pragma: nocover
476496 continue
477- if hasattr (lib , 'uuid_generate_time' ):
497+ # Try to find the safe variety first.
498+ if hasattr (lib , 'uuid_generate_time_safe' ):
499+ _uuid_generate_time = lib .uuid_generate_time_safe
500+ # int uuid_generate_time_safe(uuid_t out);
501+ break
502+ elif hasattr (lib , 'uuid_generate_time' ): # pragma: nocover
478503 _uuid_generate_time = lib .uuid_generate_time
504+ # void uuid_generate_time(uuid_t out);
505+ _uuid_generate_time .restype = None
479506 break
480507 del _libnames
481508
@@ -566,8 +593,12 @@ def uuid1(node=None, clock_seq=None):
566593 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
567594 if _uuid_generate_time and node is clock_seq is None :
568595 _buffer = ctypes .create_string_buffer (16 )
569- _uuid_generate_time (_buffer )
570- return UUID (bytes = bytes_ (_buffer .raw ))
596+ safely_generated = _uuid_generate_time (_buffer )
597+ try :
598+ is_safe = SafeUUID (safely_generated )
599+ except ValueError :
600+ is_safe = SafeUUID .unknown
601+ return UUID (bytes = bytes_ (_buffer .raw ), is_safe = is_safe )
571602
572603 global _last_timestamp
573604 import time
0 commit comments