uuid.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: euc-jp -*-
00003 
00004 ##
00005 # @file uuid.py
00006 # @brief 
00007 # @date $Date: 2006/06/12 $
00008 # @author Ka-Ping Yee <ping@zesty.ca>
00009 #
00010 # Copyright (C) 2008
00011 #     Task-intelligence Research Group,
00012 #     Intelligent Systems Research Institute,
00013 #     National Institute of
00014 #         Advanced Industrial Science and Technology (AIST), Japan
00015 #     All rights reserved.
00016 
00017 
00018 RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
00019     'reserved for NCS compatibility', 'specified in RFC 4122',
00020     'reserved for Microsoft compatibility', 'reserved for future definition']
00021 
00022 ##
00023 # @if jp
00024 # @class UUID
00025 # @brief UUID保持クラス
00026 # 
00027 # 生成した UUID の情報を保持するためのクラス。
00028 #
00029 # @since 0.4.0
00030 #
00031 # @else
00032 #
00033 # @endif
00034 class UUID(object):
00035 
00036     def __init__(self, hex=None, bytes=None, fields=None, int=None,
00037                        version=None):
00038         r"""Create a UUID from either a string of 32 hexadecimal digits,
00039         a string of 16 bytes as the 'bytes' argument, a tuple of six
00040         integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
00041         8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
00042         the 'fields' argument, or a single 128-bit integer as the 'int'
00043         argument.  When a string of hex digits is given, curly braces,
00044         hyphens, and a URN prefix are all optional.  For example, these
00045         expressions all yield the same UUID:
00046 
00047         UUID('{12345678-1234-5678-1234-567812345678}')
00048         UUID('12345678123456781234567812345678')
00049         UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
00050         UUID(bytes='\x12\x34\x56\x78'*4)
00051         UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
00052         UUID(int=0x12345678123456781234567812345678)
00053 
00054         Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given.
00055         The 'version' argument is optional; if given, the resulting UUID
00056         will have its variant and version number set according to RFC 4122,
00057         overriding bits in the given 'hex', 'bytes', 'fields', or 'int'.
00058         """
00059 
00060         if [hex, bytes, fields, int].count(None) != 3:
00061             raise TypeError('need just one of hex, bytes, fields, or int')
00062         if hex:
00063             hex = hex.replace('urn:', '').replace('uuid:', '')
00064             hex = hex.strip('{}').replace('-', '')
00065             if len(hex) != 32:
00066                 raise ValueError('badly formed hexadecimal UUID string')
00067             int = long(hex, 16)
00068         if bytes:
00069             if len(bytes) != 16:
00070                 raise ValueError('bytes is not a 16-char string')
00071             int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
00072         if fields:
00073             if len(fields) != 6:
00074                 raise ValueError('fields is not a 6-tuple')
00075             (time_low, time_mid, time_hi_version,
00076              clock_seq_hi_variant, clock_seq_low, node) = fields
00077             if not 0 <= time_low < 1<<32L:
00078                 raise ValueError('field 1 out of range (need a 32-bit value)')
00079             if not 0 <= time_mid < 1<<16L:
00080                 raise ValueError('field 2 out of range (need a 16-bit value)')
00081             if not 0 <= time_hi_version < 1<<16L:
00082                 raise ValueError('field 3 out of range (need a 16-bit value)')
00083             if not 0 <= clock_seq_hi_variant < 1<<8L:
00084                 raise ValueError('field 4 out of range (need an 8-bit value)')
00085             if not 0 <= clock_seq_low < 1<<8L:
00086                 raise ValueError('field 5 out of range (need an 8-bit value)')
00087             if not 0 <= node < 1<<48L:
00088                 raise ValueError('field 6 out of range (need a 48-bit value)')
00089             clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low
00090             int = ((time_low << 96L) | (time_mid << 80L) |
00091                    (time_hi_version << 64L) | (clock_seq << 48L) | node)
00092         if int:
00093             if not 0 <= int < 1<<128L:
00094                 raise ValueError('int is out of range (need a 128-bit value)')
00095         if version:
00096             if not 1 <= version <= 5:
00097                 raise ValueError('illegal version number')
00098             # Set the variant to RFC 4122.
00099             int &= ~(0xc000 << 48L)
00100             int |= 0x8000 << 48L
00101             # Set the version number.
00102             int &= ~(0xf000 << 64L)
00103             int |= version << 76L
00104         self.__dict__['int'] = int
00105 
00106     def __cmp__(self, other):
00107         if isinstance(other, UUID):
00108             return cmp(self.int, other.int)
00109         return NotImplemented
00110 
00111     def __hash__(self):
00112         return hash(self.int)
00113 
00114     def __int__(self):
00115         return self.int
00116 
00117     def __repr__(self):
00118         return 'UUID(%r)' % str(self)
00119 
00120     def __setattr__(self, name, value):
00121         raise TypeError('UUID objects are immutable')
00122 
00123     def __str__(self):
00124         hex = '%032x' % self.int
00125         return '%s-%s-%s-%s-%s' % (
00126             hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
00127 
00128     def get_bytes(self):
00129         bytes = ''
00130         for shift in range(0, 128, 8):
00131             bytes = chr((self.int >> shift) & 0xff) + bytes
00132         return bytes
00133 
00134     bytes = property(get_bytes)
00135 
00136     def get_fields(self):
00137         return (self.time_low, self.time_mid, self.time_hi_version,
00138                 self.clock_seq_hi_variant, self.clock_seq_low, self.node)
00139 
00140     fields = property(get_fields)
00141 
00142     def get_time_low(self):
00143         return self.int >> 96L
00144    
00145     time_low = property(get_time_low)
00146 
00147     def get_time_mid(self):
00148         return (self.int >> 80L) & 0xffff
00149 
00150     time_mid = property(get_time_mid)
00151 
00152     def get_time_hi_version(self):
00153         return (self.int >> 64L) & 0xffff
00154     
00155     time_hi_version = property(get_time_hi_version)
00156 
00157     def get_clock_seq_hi_variant(self):
00158         return (self.int >> 56L) & 0xff
00159 
00160     clock_seq_hi_variant = property(get_clock_seq_hi_variant)
00161     
00162     def get_clock_seq_low(self):
00163         return (self.int >> 48L) & 0xff
00164 
00165     clock_seq_low = property(get_clock_seq_low)
00166 
00167     def get_time(self):
00168         return (((self.time_hi_version & 0x0fffL) << 48L) |
00169                 (self.time_mid << 32L) | self.time_low)
00170 
00171     time = property(get_time)
00172 
00173     def get_clock_seq(self):
00174         return (((self.clock_seq_hi_variant & 0x3fL) << 8L) |
00175                 self.clock_seq_low)
00176 
00177     clock_seq = property(get_clock_seq)
00178     
00179     def get_node(self):
00180         return self.int & 0xffffffffffff
00181 
00182     node = property(get_node)
00183 
00184     def get_hex(self):
00185         return '%032x' % self.int
00186 
00187     hex = property(get_hex)
00188 
00189     def get_urn(self):
00190         return 'urn:uuid:' + str(self)
00191 
00192     urn = property(get_urn)
00193 
00194     def get_variant(self):
00195         if not self.int & (0x8000 << 48L):
00196             return RESERVED_NCS
00197         elif not self.int & (0x4000 << 48L):
00198             return RFC_4122
00199         elif not self.int & (0x2000 << 48L):
00200             return RESERVED_MICROSOFT
00201         else:
00202             return RESERVED_FUTURE
00203 
00204     variant = property(get_variant)
00205 
00206     def get_version(self):
00207         # The version bits are only meaningful for RFC 4122 UUIDs.
00208         if self.variant == RFC_4122:
00209             return int((self.int >> 76L) & 0xf)
00210 
00211     version = property(get_version)
00212 
00213 def _ifconfig_getnode():
00214     """Get the hardware address on Unix by running ifconfig."""
00215     import os
00216     dir = '/sbin/'
00217     pipe = os.popen(os.path.join(dir, 'ifconfig'))
00218 
00219     for line in pipe:
00220       words = line.lower().split()
00221       for i in range(len(words)):
00222         if words[i] in ['hwaddr', 'ether']:
00223           return int(words[i + 1].replace(':', ''), 16)
00224 
00225 def _ipconfig_getnode():
00226     """Get the hardware address on Windows by running ipconfig.exe."""
00227     import os, re
00228     dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
00229     try:
00230         import ctypes
00231         buffer = ctypes.create_string_buffer(300)
00232         ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
00233         dirs.insert(0, buffer.value.decode('mbcs'))
00234     except:
00235         pass
00236     for dir in dirs:
00237         try:
00238             pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all')
00239         except IOError:
00240             continue
00241         for line in pipe:
00242             value = line.split(':')[-1].strip().lower()
00243             if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
00244                 return int(value.replace('-', ''), 16)
00245 
00246 def _netbios_getnode():
00247     """Get the hardware address on Windows using NetBIOS calls.
00248     See http://support.microsoft.com/kb/118623 for details."""
00249     import win32wnet, netbios
00250     ncb = netbios.NCB()
00251     ncb.Command = netbios.NCBENUM
00252     ncb.Buffer = adapters = netbios.LANA_ENUM()
00253     adapters._pack()
00254     if win32wnet.Netbios(ncb) != 0:
00255         return
00256     adapters._unpack()
00257     for i in range(adapters.length):
00258         ncb.Reset()
00259         ncb.Command = netbios.NCBRESET
00260         ncb.Lana_num = ord(adapters.lana[i])
00261         if win32wnet.Netbios(ncb) != 0:
00262             continue
00263         ncb.Reset()
00264         ncb.Command = netbios.NCBASTAT
00265         ncb.Lana_num = ord(adapters.lana[i])
00266         ncb.Callname = '*'.ljust(16)
00267         ncb.Buffer = status = netbios.ADAPTER_STATUS()
00268         if win32wnet.Netbios(ncb) != 0:
00269             continue
00270         status._unpack()
00271         bytes = map(ord, status.adapter_address)
00272         return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) +
00273                 (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5])
00274 
00275 # Thanks to Thomas Heller for ctypes and for his help with its use here.
00276 
00277 # If ctypes is available, use it to find system routines for UUID generation.
00278 _uuid_generate_random = _uuid_generate_time = _UuidCreate = None
00279 try:
00280     import ctypes, ctypes.util
00281     _buffer = ctypes.create_string_buffer(16)
00282 
00283     # The uuid_generate_* routines are provided by libuuid on at least
00284     # Linux and FreeBSD, and provided by libc on Mac OS X.
00285     for libname in ['uuid', 'c']:
00286         try:
00287             lib = ctypes.CDLL(ctypes.util.find_library(libname))
00288         except:
00289             continue
00290         if hasattr(lib, 'uuid_generate_random'):
00291             _uuid_generate_random = lib.uuid_generate_random
00292         if hasattr(lib, 'uuid_generate_time'):
00293             _uuid_generate_time = lib.uuid_generate_time
00294 
00295     # On Windows prior to 2000, UuidCreate gives a UUID containing the
00296     # hardware address.  On Windows 2000 and later, UuidCreate makes a
00297     # random UUID and UuidCreateSequential gives a UUID containing the
00298     # hardware address.  These routines are provided by the RPC runtime.
00299     try:
00300         lib = ctypes.windll.rpcrt4
00301     except:
00302         lib = None
00303     _UuidCreate = getattr(lib, 'UuidCreateSequential',
00304                           getattr(lib, 'UuidCreate', None))
00305 except:
00306     pass
00307 
00308 def _unixdll_getnode():
00309     """Get the hardware address on Unix using ctypes."""
00310     _uuid_generate_time(_buffer)
00311     return UUID(bytes=_buffer.raw).node
00312 
00313 def _windll_getnode():
00314     """Get the hardware address on Windows using ctypes."""
00315     if _UuidCreate(_buffer) == 0:
00316         return UUID(bytes=_buffer.raw).node
00317 
00318 def _random_getnode():
00319     """Get a random node ID, with eighth bit set as suggested by RFC 4122."""
00320     import random
00321     return random.randrange(0, 1<<48L) | 0x010000000000L
00322 
00323 _node = None
00324 
00325 def getnode():
00326     """Get the hardware address as a 48-bit integer.  The first time this
00327     runs, it may launch a separate program, which could be quite slow.  If
00328     all attempts to obtain the hardware address fail, we choose a random
00329     48-bit number with its eighth bit set to 1 as recommended in RFC 4122."""
00330 
00331     global _node
00332     if _node:
00333         return _node
00334 
00335     import sys
00336     if sys.platform == 'win32':
00337         getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
00338     else:
00339         getters = [_unixdll_getnode, _ifconfig_getnode]
00340 
00341     for getter in getters + [_random_getnode]:
00342         try:
00343             _node = getter()
00344         except:
00345             continue
00346         if _node:
00347             return _node
00348 
00349 def uuid1(node=None, clock_seq=None):
00350     """Generate a UUID from a host ID, sequence number, and the current time.
00351     If 'node' is not given, getnode() is used to obtain the hardware
00352     address.  If 'clock_seq' is given, it is used as the sequence number;
00353     otherwise a random 14-bit sequence number is chosen."""
00354 
00355     # When the system provides a version-1 UUID generator, use it (but don't
00356     # use UuidCreate here because its UUIDs don't conform to RFC 4122).
00357     if _uuid_generate_time and node is clock_seq is None:
00358         _uuid_generate_time(_buffer)
00359         return UUID(bytes=_buffer.raw)
00360 
00361     import time
00362     nanoseconds = int(time.time() * 1e9)
00363     # 0x01b21dd213814000 is the number of 100-ns intervals between the
00364     # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
00365     timestamp = int(nanoseconds/100) + 0x01b21dd213814000L
00366     if clock_seq is None:
00367         import random
00368         clock_seq = random.randrange(1<<14L) # instead of stable storage
00369     time_low = timestamp & 0xffffffffL
00370     time_mid = (timestamp >> 32L) & 0xffffL
00371     time_hi_version = (timestamp >> 48L) & 0x0fffL
00372     clock_seq_low = clock_seq & 0xffL
00373     clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL
00374     if node is None:
00375         node = getnode()
00376     return UUID(fields=(time_low, time_mid, time_hi_version,
00377                         clock_seq_hi_variant, clock_seq_low, node), version=1)
00378 
00379 def uuid3(namespace, name):
00380     """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
00381     import md5
00382     hash = md5.md5(namespace.bytes + name).digest()
00383     return UUID(bytes=hash[:16], version=3)
00384 
00385 def uuid4():
00386     """Generate a random UUID."""
00387 
00388     # When the system provides a version-4 UUID generator, use it.
00389     if _uuid_generate_random:
00390         _uuid_generate_random(_buffer)
00391         return UUID(bytes=_buffer.raw)
00392 
00393     # Otherwise, get randomness from urandom or the 'random' module.
00394     try:
00395         import os
00396         return UUID(bytes=os.urandom(16), version=4)
00397     except:
00398         import random
00399         bytes = [chr(random.randrange(256)) for i in range(16)]
00400         return UUID(bytes=bytes, version=4)
00401 
00402 def uuid5(namespace, name):
00403     """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
00404     import sha
00405     hash = sha.sha(namespace.bytes + name).digest()
00406     return UUID(bytes=hash[:16], version=5)
00407 
00408 # The following standard UUIDs are for use with uuid3() or uuid5().
00409 
00410 NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
00411 NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
00412 NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
00413 NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')


openrtm_aist_python
Author(s): Shinji Kurihara
autogenerated on Thu Aug 27 2015 14:17:28