diff options
author | Jacek Antonelli | 2009-04-30 13:04:20 -0500 |
---|---|---|
committer | Jacek Antonelli | 2009-04-30 13:07:16 -0500 |
commit | ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e (patch) | |
tree | 8348301d0ac44a524f1819b777686bf086907d76 /linden/indra/lib/python | |
parent | Second Life viewer sources 1.22.11 (diff) | |
download | meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.zip meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.gz meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.bz2 meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.xz |
Second Life viewer sources 1.23.0-RC
Diffstat (limited to 'linden/indra/lib/python')
-rw-r--r-- | linden/indra/lib/python/indra/base/config.py | 29 | ||||
-rw-r--r-- | linden/indra/lib/python/indra/base/llsd.py | 14 | ||||
-rw-r--r-- | linden/indra/lib/python/indra/ipc/servicebuilder.py | 29 | ||||
-rw-r--r-- | linden/indra/lib/python/indra/util/llmanifest.py | 10 | ||||
-rw-r--r-- | linden/indra/lib/python/indra/util/named_query.py | 19 | ||||
-rw-r--r-- | linden/indra/lib/python/uuid.py | 481 |
6 files changed, 561 insertions, 21 deletions
diff --git a/linden/indra/lib/python/indra/base/config.py b/linden/indra/lib/python/indra/base/config.py index d6866fd..adafa29 100644 --- a/linden/indra/lib/python/indra/base/config.py +++ b/linden/indra/lib/python/indra/base/config.py | |||
@@ -27,6 +27,7 @@ $/LicenseInfo$ | |||
27 | """ | 27 | """ |
28 | 28 | ||
29 | import copy | 29 | import copy |
30 | import errno | ||
30 | import os | 31 | import os |
31 | import traceback | 32 | import traceback |
32 | import time | 33 | import time |
@@ -62,6 +63,8 @@ class IndraConfig(object): | |||
62 | self._load() | 63 | self._load() |
63 | 64 | ||
64 | def _load(self): | 65 | def _load(self): |
66 | # if you initialize the IndraConfig with None, no attempt | ||
67 | # is made to load any files | ||
65 | if self._indra_config_file is None: | 68 | if self._indra_config_file is None: |
66 | return | 69 | return |
67 | 70 | ||
@@ -164,22 +167,36 @@ class IndraConfig(object): | |||
164 | """ | 167 | """ |
165 | return copy.deepcopy(self._combined_dict) | 168 | return copy.deepcopy(self._combined_dict) |
166 | 169 | ||
167 | def load(indra_xml_file = None): | 170 | def load(config_xml_file = None): |
168 | global _g_config | 171 | global _g_config |
169 | 172 | ||
170 | if indra_xml_file is None: | 173 | load_default_files = config_xml_file is None |
174 | if load_default_files: | ||
171 | ## going from: | 175 | ## going from: |
172 | ## "/opt/linden/indra/lib/python/indra/base/config.py" | 176 | ## "/opt/linden/indra/lib/python/indra/base/config.py" |
173 | ## to: | 177 | ## to: |
174 | ## "/opt/linden/etc/indra.xml" | 178 | ## "/opt/linden/etc/indra.xml" |
175 | indra_xml_file = realpath( | 179 | config_xml_file = realpath( |
176 | dirname(realpath(__file__)) + "../../../../../../etc/indra.xml") | 180 | dirname(realpath(__file__)) + "../../../../../../etc/indra.xml") |
177 | 181 | ||
178 | try: | 182 | try: |
179 | _g_config = IndraConfig(indra_xml_file) | 183 | _g_config = IndraConfig(config_xml_file) |
180 | except IOError: | 184 | except IOError: |
181 | # indra.xml was not openable, so let's initialize with an empty dict | 185 | # Failure to load passed in file |
182 | # some code relies on config behaving this way | 186 | # or indra.xml default file |
187 | if load_default_files: | ||
188 | try: | ||
189 | config_xml_file = realpath( | ||
190 | dirname(realpath(__file__)) + "../../../../../../etc/globals.xml") | ||
191 | _g_config = IndraConfig(config_xml_file) | ||
192 | return | ||
193 | except IOError: | ||
194 | # Failure to load globals.xml | ||
195 | # fall to code below | ||
196 | pass | ||
197 | |||
198 | # Either failed to load passed in file | ||
199 | # or failed to load all default files | ||
183 | _g_config = IndraConfig(None) | 200 | _g_config = IndraConfig(None) |
184 | 201 | ||
185 | def dump(indra_xml_file, indra_cfg = None, update_in_mem=False): | 202 | def dump(indra_xml_file, indra_cfg = None, update_in_mem=False): |
diff --git a/linden/indra/lib/python/indra/base/llsd.py b/linden/indra/lib/python/indra/base/llsd.py index 4a575fc..9534d59 100644 --- a/linden/indra/lib/python/indra/base/llsd.py +++ b/linden/indra/lib/python/indra/base/llsd.py | |||
@@ -28,6 +28,7 @@ $/LicenseInfo$ | |||
28 | 28 | ||
29 | import datetime | 29 | import datetime |
30 | import base64 | 30 | import base64 |
31 | import string | ||
31 | import struct | 32 | import struct |
32 | import time | 33 | import time |
33 | import types | 34 | import types |
@@ -36,10 +37,13 @@ import re | |||
36 | from indra.util.fastest_elementtree import ElementTreeError, fromstring | 37 | from indra.util.fastest_elementtree import ElementTreeError, fromstring |
37 | from indra.base import lluuid | 38 | from indra.base import lluuid |
38 | 39 | ||
39 | try: | 40 | # cllsd.c in server/server-1.25 has memory leaks, |
40 | import cllsd | 41 | # so disabling cllsd for now |
41 | except ImportError: | 42 | #try: |
42 | cllsd = None | 43 | # import cllsd |
44 | #except ImportError: | ||
45 | # cllsd = None | ||
46 | cllsd = None | ||
43 | 47 | ||
44 | int_regex = re.compile(r"[-+]?\d+") | 48 | int_regex = re.compile(r"[-+]?\d+") |
45 | real_regex = re.compile(r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?") | 49 | real_regex = re.compile(r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?") |
@@ -126,6 +130,7 @@ def date_to_python(node): | |||
126 | if not val: | 130 | if not val: |
127 | val = "1970-01-01T00:00:00Z" | 131 | val = "1970-01-01T00:00:00Z" |
128 | return parse_datestr(val) | 132 | return parse_datestr(val) |
133 | |||
129 | 134 | ||
130 | def uri_to_python(node): | 135 | def uri_to_python(node): |
131 | val = node.text or '' | 136 | val = node.text or '' |
@@ -936,6 +941,7 @@ def parse_notation(something): | |||
936 | 941 | ||
937 | def parse(something): | 942 | def parse(something): |
938 | try: | 943 | try: |
944 | something = string.lstrip(something) #remove any pre-trailing whitespace | ||
939 | if something.startswith('<?llsd/binary?>'): | 945 | if something.startswith('<?llsd/binary?>'): |
940 | return parse_binary(something) | 946 | return parse_binary(something) |
941 | # This should be better. | 947 | # This should be better. |
diff --git a/linden/indra/lib/python/indra/ipc/servicebuilder.py b/linden/indra/lib/python/indra/ipc/servicebuilder.py index b5872de..04ccee7 100644 --- a/linden/indra/lib/python/indra/ipc/servicebuilder.py +++ b/linden/indra/lib/python/indra/ipc/servicebuilder.py | |||
@@ -51,12 +51,10 @@ def build(name, context={}, **kwargs): | |||
51 | > servicebuilder.build('version-manager-version', context, version='1.18.1.2') | 51 | > servicebuilder.build('version-manager-version', context, version='1.18.1.2') |
52 | 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2' | 52 | 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2' |
53 | """ | 53 | """ |
54 | context = context.copy() # shouldn't modify the caller's dictionary | ||
55 | context.update(kwargs) | ||
56 | global _g_builder | 54 | global _g_builder |
57 | if _g_builder is None: | 55 | if _g_builder is None: |
58 | _g_builder = ServiceBuilder() | 56 | _g_builder = ServiceBuilder() |
59 | return _g_builder.buildServiceURL(name, context) | 57 | return _g_builder.buildServiceURL(name, context, **kwargs) |
60 | 58 | ||
61 | class ServiceBuilder(object): | 59 | class ServiceBuilder(object): |
62 | def __init__(self, services_definition = services_config): | 60 | def __init__(self, services_definition = services_config): |
@@ -81,13 +79,36 @@ class ServiceBuilder(object): | |||
81 | else: | 79 | else: |
82 | self.builders[service['name']] = service_builder | 80 | self.builders[service['name']] = service_builder |
83 | 81 | ||
84 | def buildServiceURL(self, name, context): | 82 | def buildServiceURL(self, name, context={}, **kwargs): |
85 | """\ | 83 | """\ |
86 | @brief given the environment on construction, return a service URL. | 84 | @brief given the environment on construction, return a service URL. |
87 | @param name The name of the service. | 85 | @param name The name of the service. |
88 | @param context A dict of name value lookups for the service. | 86 | @param context A dict of name value lookups for the service. |
87 | @param kwargs Any keyword arguments are treated as members of the | ||
88 | context, this allows you to be all 31337 by writing shit like: | ||
89 | servicebuilder.build('name', param=value) | ||
89 | @returns Returns the | 90 | @returns Returns the |
90 | """ | 91 | """ |
92 | context = context.copy() # shouldn't modify the caller's dictionary | ||
93 | context.update(kwargs) | ||
91 | base_url = config.get('services-base-url') | 94 | base_url = config.get('services-base-url') |
92 | svc_path = russ.format(self.builders[name], context) | 95 | svc_path = russ.format(self.builders[name], context) |
93 | return base_url + svc_path | 96 | return base_url + svc_path |
97 | |||
98 | |||
99 | def on_in(query_name, host_key, schema_key): | ||
100 | """\ | ||
101 | @brief Constructs an on/in snippet (for running named queries) | ||
102 | from a schema name and two keys referencing values stored in | ||
103 | indra.xml. | ||
104 | |||
105 | @param query_name Name of the query. | ||
106 | @param host_key Logical name of destination host. Will be | ||
107 | looked up in indra.xml. | ||
108 | @param schema_key Logical name of destination schema. Will | ||
109 | be looked up in indra.xml. | ||
110 | """ | ||
111 | host_name = config.get(host_key) | ||
112 | schema_name = config.get(schema_key) | ||
113 | return '/'.join( ('on', host_name, 'in', schema_name, query_name.lstrip('/')) ) | ||
114 | |||
diff --git a/linden/indra/lib/python/indra/util/llmanifest.py b/linden/indra/lib/python/indra/util/llmanifest.py index 12e33f2..59c84e5 100644 --- a/linden/indra/lib/python/indra/util/llmanifest.py +++ b/linden/indra/lib/python/indra/util/llmanifest.py | |||
@@ -452,7 +452,7 @@ class LLManifest(object): | |||
452 | # *TODO is this gonna be useful? | 452 | # *TODO is this gonna be useful? |
453 | print "Cleaning up " + c | 453 | print "Cleaning up " + c |
454 | 454 | ||
455 | def process_file(self, src, dst, strip=False): | 455 | def process_file(self, src, dst): |
456 | if self.includes(src, dst): | 456 | if self.includes(src, dst): |
457 | # print src, "=>", dst | 457 | # print src, "=>", dst |
458 | for action in self.actions: | 458 | for action in self.actions: |
@@ -460,7 +460,7 @@ class LLManifest(object): | |||
460 | method = getattr(self, methodname, None) | 460 | method = getattr(self, methodname, None) |
461 | if method is not None: | 461 | if method is not None: |
462 | method(src, dst) | 462 | method(src, dst) |
463 | self.file_list.append([src, dst, strip]) | 463 | self.file_list.append([src, dst]) |
464 | return 1 | 464 | return 1 |
465 | else: | 465 | else: |
466 | sys.stdout.write(" (excluding %r, %r)" % (src, dst)) | 466 | sys.stdout.write(" (excluding %r, %r)" % (src, dst)) |
@@ -607,7 +607,7 @@ class LLManifest(object): | |||
607 | d = src_re.sub(d_template, s.replace('\\', '/')) | 607 | d = src_re.sub(d_template, s.replace('\\', '/')) |
608 | yield os.path.normpath(s), os.path.normpath(d) | 608 | yield os.path.normpath(s), os.path.normpath(d) |
609 | 609 | ||
610 | def path(self, src, dst=None, strip=False): | 610 | def path(self, src, dst=None): |
611 | sys.stdout.write("Processing %s => %s ... " % (src, dst)) | 611 | sys.stdout.write("Processing %s => %s ... " % (src, dst)) |
612 | sys.stdout.flush() | 612 | sys.stdout.flush() |
613 | if src == None: | 613 | if src == None: |
@@ -622,7 +622,7 @@ class LLManifest(object): | |||
622 | if self.wildcard_pattern.search(src): | 622 | if self.wildcard_pattern.search(src): |
623 | for s,d in self.expand_globs(src, dst): | 623 | for s,d in self.expand_globs(src, dst): |
624 | assert(s != d) | 624 | assert(s != d) |
625 | count += self.process_file(s, d, strip) | 625 | count += self.process_file(s, d) |
626 | else: | 626 | else: |
627 | # if we're specifying a single path (not a glob), | 627 | # if we're specifying a single path (not a glob), |
628 | # we should error out if it doesn't exist | 628 | # we should error out if it doesn't exist |
@@ -631,7 +631,7 @@ class LLManifest(object): | |||
631 | if os.path.isdir(src): | 631 | if os.path.isdir(src): |
632 | count += self.process_directory(src, dst) | 632 | count += self.process_directory(src, dst) |
633 | else: | 633 | else: |
634 | count += self.process_file(src, dst, strip) | 634 | count += self.process_file(src, dst) |
635 | return count | 635 | return count |
636 | try: | 636 | try: |
637 | count = try_path(os.path.join(self.get_src_prefix(), src)) | 637 | count = try_path(os.path.join(self.get_src_prefix(), src)) |
diff --git a/linden/indra/lib/python/indra/util/named_query.py b/linden/indra/lib/python/indra/util/named_query.py index cbde2d9..688a520 100644 --- a/linden/indra/lib/python/indra/util/named_query.py +++ b/linden/indra/lib/python/indra/util/named_query.py | |||
@@ -47,6 +47,8 @@ except NameError: | |||
47 | from indra.base import llsd | 47 | from indra.base import llsd |
48 | from indra.base import config | 48 | from indra.base import config |
49 | 49 | ||
50 | DEBUG = False | ||
51 | |||
50 | NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq') | 52 | NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq') |
51 | NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX) | 53 | NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX) |
52 | 54 | ||
@@ -63,7 +65,9 @@ def _init_g_named_manager(sql_dir = None): | |||
63 | 65 | ||
64 | # extra fallback directory in case config doesn't return what we want | 66 | # extra fallback directory in case config doesn't return what we want |
65 | if sql_dir is None: | 67 | if sql_dir is None: |
66 | sql_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "web", "dataservice", "sql") | 68 | sql_dir = os.path.abspath( |
69 | os.path.join( | ||
70 | os.path.realpath(os.path.dirname(__file__)), "..", "..", "..", "..", "web", "dataservice", "sql")) | ||
67 | 71 | ||
68 | global _g_named_manager | 72 | global _g_named_manager |
69 | _g_named_manager = NamedQueryManager( | 73 | _g_named_manager = NamedQueryManager( |
@@ -188,6 +192,16 @@ class NamedQuery(object): | |||
188 | ready them for use in LIKE statements""" | 192 | ready them for use in LIKE statements""" |
189 | if sql: | 193 | if sql: |
190 | #print >>sys.stderr, "sql:",sql | 194 | #print >>sys.stderr, "sql:",sql |
195 | |||
196 | # This first sub is to properly escape any % signs that | ||
197 | # are meant to be literally passed through to mysql in the | ||
198 | # query. It leaves any %'s that are used for | ||
199 | # like-expressions. | ||
200 | expr = re.compile("(?<=[^a-zA-Z0-9_-])%(?=[^:])") | ||
201 | sql = expr.sub('%%', sql) | ||
202 | |||
203 | # This should tackle the rest of the %'s in the query, by | ||
204 | # converting them to LIKE clauses. | ||
191 | expr = re.compile("(%?):([a-zA-Z][a-zA-Z0-9_-]*)%") | 205 | expr = re.compile("(%?):([a-zA-Z][a-zA-Z0-9_-]*)%") |
192 | sql = expr.sub(self._prepare_like, sql) | 206 | sql = expr.sub(self._prepare_like, sql) |
193 | expr = re.compile("#:([a-zA-Z][a-zA-Z0-9_-]*)") | 207 | expr = re.compile("#:([a-zA-Z][a-zA-Z0-9_-]*)") |
@@ -339,7 +353,8 @@ class NamedQuery(object): | |||
339 | cursor = connection.cursor() | 353 | cursor = connection.cursor() |
340 | 354 | ||
341 | statement = self.sql(connection, params) | 355 | statement = self.sql(connection, params) |
342 | #print "SQL:", statement | 356 | if DEBUG: |
357 | print "SQL:", statement | ||
343 | rows = cursor.execute(statement) | 358 | rows = cursor.execute(statement) |
344 | 359 | ||
345 | # *NOTE: the expect_rows argument is a very cheesy way to get some | 360 | # *NOTE: the expect_rows argument is a very cheesy way to get some |
diff --git a/linden/indra/lib/python/uuid.py b/linden/indra/lib/python/uuid.py new file mode 100644 index 0000000..48dac84 --- /dev/null +++ b/linden/indra/lib/python/uuid.py | |||
@@ -0,0 +1,481 @@ | |||
1 | r"""UUID objects (universally unique identifiers) according to RFC 4122. | ||
2 | |||
3 | This module provides immutable UUID objects (class UUID) and the functions | ||
4 | uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 | ||
5 | UUIDs as specified in RFC 4122. | ||
6 | |||
7 | If all you want is a unique ID, you should probably call uuid1() or uuid4(). | ||
8 | Note that uuid1() may compromise privacy since it creates a UUID containing | ||
9 | the computer's network address. uuid4() creates a random UUID. | ||
10 | |||
11 | Typical usage: | ||
12 | |||
13 | >>> import uuid | ||
14 | |||
15 | # make a UUID based on the host ID and current time | ||
16 | >>> uuid.uuid1() | ||
17 | UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') | ||
18 | |||
19 | # make a UUID using an MD5 hash of a namespace UUID and a name | ||
20 | >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') | ||
21 | UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') | ||
22 | |||
23 | # make a random UUID | ||
24 | >>> uuid.uuid4() | ||
25 | UUID('16fd2706-8baf-433b-82eb-8c7fada847da') | ||
26 | |||
27 | # make a UUID using a SHA-1 hash of a namespace UUID and a name | ||
28 | >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') | ||
29 | UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') | ||
30 | |||
31 | # make a UUID from a string of hex digits (braces and hyphens ignored) | ||
32 | >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') | ||
33 | |||
34 | # convert a UUID to a string of hex digits in standard form | ||
35 | >>> str(x) | ||
36 | '00010203-0405-0607-0809-0a0b0c0d0e0f' | ||
37 | |||
38 | # get the raw 16 bytes of the UUID | ||
39 | >>> x.bytes | ||
40 | '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' | ||
41 | |||
42 | # make a UUID from a 16-byte string | ||
43 | >>> uuid.UUID(bytes=x.bytes) | ||
44 | UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') | ||
45 | |||
46 | This module works with Python 2.3 or higher.""" | ||
47 | |||
48 | __author__ = 'Ka-Ping Yee <ping@zesty.ca>' | ||
49 | __date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-') | ||
50 | __version__ = '$Revision: 1.30 $'.split()[1] | ||
51 | |||
52 | RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ | ||
53 | 'reserved for NCS compatibility', 'specified in RFC 4122', | ||
54 | 'reserved for Microsoft compatibility', 'reserved for future definition'] | ||
55 | |||
56 | class UUID(object): | ||
57 | """Instances of the UUID class represent UUIDs as specified in RFC 4122. | ||
58 | UUID objects are immutable, hashable, and usable as dictionary keys. | ||
59 | Converting a UUID to a string with str() yields something in the form | ||
60 | '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts | ||
61 | four possible forms: a similar string of hexadecimal digits, or a | ||
62 | string of 16 raw bytes as an argument named 'bytes', or a tuple of | ||
63 | six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and | ||
64 | 48-bit values respectively) as an argument named 'fields', or a single | ||
65 | 128-bit integer as an argument named 'int'. | ||
66 | |||
67 | UUIDs have these read-only attributes: | ||
68 | |||
69 | bytes the UUID as a 16-byte string | ||
70 | |||
71 | fields a tuple of the six integer fields of the UUID, | ||
72 | which are also available as six individual attributes | ||
73 | and two derived attributes: | ||
74 | |||
75 | time_low the first 32 bits of the UUID | ||
76 | time_mid the next 16 bits of the UUID | ||
77 | time_hi_version the next 16 bits of the UUID | ||
78 | clock_seq_hi_variant the next 8 bits of the UUID | ||
79 | clock_seq_low the next 8 bits of the UUID | ||
80 | node the last 48 bits of the UUID | ||
81 | |||
82 | time the 60-bit timestamp | ||
83 | clock_seq the 14-bit sequence number | ||
84 | |||
85 | hex the UUID as a 32-character hexadecimal string | ||
86 | |||
87 | int the UUID as a 128-bit integer | ||
88 | |||
89 | urn the UUID as a URN as specified in RFC 4122 | ||
90 | |||
91 | variant the UUID variant (one of the constants RESERVED_NCS, | ||
92 | RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) | ||
93 | |||
94 | version the UUID version number (1 through 5, meaningful only | ||
95 | when the variant is RFC_4122) | ||
96 | """ | ||
97 | |||
98 | def __init__(self, hex=None, bytes=None, fields=None, int=None, | ||
99 | version=None): | ||
100 | r"""Create a UUID from either a string of 32 hexadecimal digits, | ||
101 | a string of 16 bytes as the 'bytes' argument, a tuple of six | ||
102 | integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, | ||
103 | 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as | ||
104 | the 'fields' argument, or a single 128-bit integer as the 'int' | ||
105 | argument. When a string of hex digits is given, curly braces, | ||
106 | hyphens, and a URN prefix are all optional. For example, these | ||
107 | expressions all yield the same UUID: | ||
108 | |||
109 | UUID('{12345678-1234-5678-1234-567812345678}') | ||
110 | UUID('12345678123456781234567812345678') | ||
111 | UUID('urn:uuid:12345678-1234-5678-1234-567812345678') | ||
112 | UUID(bytes='\x12\x34\x56\x78'*4) | ||
113 | UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) | ||
114 | UUID(int=0x12345678123456781234567812345678) | ||
115 | |||
116 | Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given. | ||
117 | The 'version' argument is optional; if given, the resulting UUID | ||
118 | will have its variant and version number set according to RFC 4122, | ||
119 | overriding bits in the given 'hex', 'bytes', 'fields', or 'int'. | ||
120 | """ | ||
121 | |||
122 | if [hex, bytes, fields, int].count(None) != 3: | ||
123 | raise TypeError('need just one of hex, bytes, fields, or int') | ||
124 | if hex is not None: | ||
125 | hex = hex.replace('urn:', '').replace('uuid:', '') | ||
126 | hex = hex.strip('{}').replace('-', '') | ||
127 | if len(hex) != 32: | ||
128 | raise ValueError('badly formed hexadecimal UUID string') | ||
129 | int = long(hex, 16) | ||
130 | if bytes is not None: | ||
131 | if len(bytes) != 16: | ||
132 | raise ValueError('bytes is not a 16-char string') | ||
133 | int = long(('%02x'*16) % tuple(map(ord, bytes)), 16) | ||
134 | if fields is not None: | ||
135 | if len(fields) != 6: | ||
136 | raise ValueError('fields is not a 6-tuple') | ||
137 | (time_low, time_mid, time_hi_version, | ||
138 | clock_seq_hi_variant, clock_seq_low, node) = fields | ||
139 | if not 0 <= time_low < 1<<32L: | ||
140 | raise ValueError('field 1 out of range (need a 32-bit value)') | ||
141 | if not 0 <= time_mid < 1<<16L: | ||
142 | raise ValueError('field 2 out of range (need a 16-bit value)') | ||
143 | if not 0 <= time_hi_version < 1<<16L: | ||
144 | raise ValueError('field 3 out of range (need a 16-bit value)') | ||
145 | if not 0 <= clock_seq_hi_variant < 1<<8L: | ||
146 | raise ValueError('field 4 out of range (need an 8-bit value)') | ||
147 | if not 0 <= clock_seq_low < 1<<8L: | ||
148 | raise ValueError('field 5 out of range (need an 8-bit value)') | ||
149 | if not 0 <= node < 1<<48L: | ||
150 | raise ValueError('field 6 out of range (need a 48-bit value)') | ||
151 | clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low | ||
152 | int = ((time_low << 96L) | (time_mid << 80L) | | ||
153 | (time_hi_version << 64L) | (clock_seq << 48L) | node) | ||
154 | if int is not None: | ||
155 | if not 0 <= int < 1<<128L: | ||
156 | raise ValueError('int is out of range (need a 128-bit value)') | ||
157 | if version is not None: | ||
158 | if not 1 <= version <= 5: | ||
159 | raise ValueError('illegal version number') | ||
160 | # Set the variant to RFC 4122. | ||
161 | int &= ~(0xc000 << 48L) | ||
162 | int |= 0x8000 << 48L | ||
163 | # Set the version number. | ||
164 | int &= ~(0xf000 << 64L) | ||
165 | int |= version << 76L | ||
166 | self.__dict__['int'] = int | ||
167 | |||
168 | def __cmp__(self, other): | ||
169 | if isinstance(other, UUID): | ||
170 | return cmp(self.int, other.int) | ||
171 | return NotImplemented | ||
172 | |||
173 | def __hash__(self): | ||
174 | return hash(self.int) | ||
175 | |||
176 | def __int__(self): | ||
177 | return self.int | ||
178 | |||
179 | def __repr__(self): | ||
180 | return 'UUID(%r)' % str(self) | ||
181 | |||
182 | def __setattr__(self, name, value): | ||
183 | raise TypeError('UUID objects are immutable') | ||
184 | |||
185 | def __str__(self): | ||
186 | hex = '%032x' % self.int | ||
187 | return '%s-%s-%s-%s-%s' % ( | ||
188 | hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]) | ||
189 | |||
190 | def get_bytes(self): | ||
191 | bytes = '' | ||
192 | for shift in range(0, 128, 8): | ||
193 | bytes = chr((self.int >> shift) & 0xff) + bytes | ||
194 | return bytes | ||
195 | |||
196 | bytes = property(get_bytes) | ||
197 | |||
198 | def get_fields(self): | ||
199 | return (self.time_low, self.time_mid, self.time_hi_version, | ||
200 | self.clock_seq_hi_variant, self.clock_seq_low, self.node) | ||
201 | |||
202 | fields = property(get_fields) | ||
203 | |||
204 | def get_time_low(self): | ||
205 | return self.int >> 96L | ||
206 | |||
207 | time_low = property(get_time_low) | ||
208 | |||
209 | def get_time_mid(self): | ||
210 | return (self.int >> 80L) & 0xffff | ||
211 | |||
212 | time_mid = property(get_time_mid) | ||
213 | |||
214 | def get_time_hi_version(self): | ||
215 | return (self.int >> 64L) & 0xffff | ||
216 | |||
217 | time_hi_version = property(get_time_hi_version) | ||
218 | |||
219 | def get_clock_seq_hi_variant(self): | ||
220 | return (self.int >> 56L) & 0xff | ||
221 | |||
222 | clock_seq_hi_variant = property(get_clock_seq_hi_variant) | ||
223 | |||
224 | def get_clock_seq_low(self): | ||
225 | return (self.int >> 48L) & 0xff | ||
226 | |||
227 | clock_seq_low = property(get_clock_seq_low) | ||
228 | |||
229 | def get_time(self): | ||
230 | return (((self.time_hi_version & 0x0fffL) << 48L) | | ||
231 | (self.time_mid << 32L) | self.time_low) | ||
232 | |||
233 | time = property(get_time) | ||
234 | |||
235 | def get_clock_seq(self): | ||
236 | return (((self.clock_seq_hi_variant & 0x3fL) << 8L) | | ||
237 | self.clock_seq_low) | ||
238 | |||
239 | clock_seq = property(get_clock_seq) | ||
240 | |||
241 | def get_node(self): | ||
242 | return self.int & 0xffffffffffff | ||
243 | |||
244 | node = property(get_node) | ||
245 | |||
246 | def get_hex(self): | ||
247 | return '%032x' % self.int | ||
248 | |||
249 | hex = property(get_hex) | ||
250 | |||
251 | def get_urn(self): | ||
252 | return 'urn:uuid:' + str(self) | ||
253 | |||
254 | urn = property(get_urn) | ||
255 | |||
256 | def get_variant(self): | ||
257 | if not self.int & (0x8000 << 48L): | ||
258 | return RESERVED_NCS | ||
259 | elif not self.int & (0x4000 << 48L): | ||
260 | return RFC_4122 | ||
261 | elif not self.int & (0x2000 << 48L): | ||
262 | return RESERVED_MICROSOFT | ||
263 | else: | ||
264 | return RESERVED_FUTURE | ||
265 | |||
266 | variant = property(get_variant) | ||
267 | |||
268 | def get_version(self): | ||
269 | # The version bits are only meaningful for RFC 4122 UUIDs. | ||
270 | if self.variant == RFC_4122: | ||
271 | return int((self.int >> 76L) & 0xf) | ||
272 | |||
273 | version = property(get_version) | ||
274 | |||
275 | def _ifconfig_getnode(): | ||
276 | """Get the hardware address on Unix by running ifconfig.""" | ||
277 | import os | ||
278 | for dir in ['', '/sbin/', '/usr/sbin']: | ||
279 | try: | ||
280 | path = os.path.join(dir, 'ifconfig') | ||
281 | if os.path.exists(path): | ||
282 | pipe = os.popen(path) | ||
283 | else: | ||
284 | continue | ||
285 | except IOError: | ||
286 | continue | ||
287 | for line in pipe: | ||
288 | words = line.lower().split() | ||
289 | for i in range(len(words)): | ||
290 | if words[i] in ['hwaddr', 'ether']: | ||
291 | return int(words[i + 1].replace(':', ''), 16) | ||
292 | |||
293 | def _ipconfig_getnode(): | ||
294 | """Get the hardware address on Windows by running ipconfig.exe.""" | ||
295 | import os, re | ||
296 | dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] | ||
297 | try: | ||
298 | import ctypes | ||
299 | buffer = ctypes.create_string_buffer(300) | ||
300 | ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300) | ||
301 | dirs.insert(0, buffer.value.decode('mbcs')) | ||
302 | except: | ||
303 | pass | ||
304 | for dir in dirs: | ||
305 | try: | ||
306 | pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all') | ||
307 | except IOError: | ||
308 | continue | ||
309 | for line in pipe: | ||
310 | value = line.split(':')[-1].strip().lower() | ||
311 | if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): | ||
312 | return int(value.replace('-', ''), 16) | ||
313 | |||
314 | def _netbios_getnode(): | ||
315 | """Get the hardware address on Windows using NetBIOS calls. | ||
316 | See http://support.microsoft.com/kb/118623 for details.""" | ||
317 | import win32wnet, netbios | ||
318 | ncb = netbios.NCB() | ||
319 | ncb.Command = netbios.NCBENUM | ||
320 | ncb.Buffer = adapters = netbios.LANA_ENUM() | ||
321 | adapters._pack() | ||
322 | if win32wnet.Netbios(ncb) != 0: | ||
323 | return | ||
324 | adapters._unpack() | ||
325 | for i in range(adapters.length): | ||
326 | ncb.Reset() | ||
327 | ncb.Command = netbios.NCBRESET | ||
328 | ncb.Lana_num = ord(adapters.lana[i]) | ||
329 | if win32wnet.Netbios(ncb) != 0: | ||
330 | continue | ||
331 | ncb.Reset() | ||
332 | ncb.Command = netbios.NCBASTAT | ||
333 | ncb.Lana_num = ord(adapters.lana[i]) | ||
334 | ncb.Callname = '*'.ljust(16) | ||
335 | ncb.Buffer = status = netbios.ADAPTER_STATUS() | ||
336 | if win32wnet.Netbios(ncb) != 0: | ||
337 | continue | ||
338 | status._unpack() | ||
339 | bytes = map(ord, status.adapter_address) | ||
340 | return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) + | ||
341 | (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5]) | ||
342 | |||
343 | # Thanks to Thomas Heller for ctypes and for his help with its use here. | ||
344 | |||
345 | # If ctypes is available, use it to find system routines for UUID generation. | ||
346 | _uuid_generate_random = _uuid_generate_time = _UuidCreate = None | ||
347 | try: | ||
348 | import ctypes, ctypes.util | ||
349 | _buffer = ctypes.create_string_buffer(16) | ||
350 | |||
351 | # The uuid_generate_* routines are provided by libuuid on at least | ||
352 | # Linux and FreeBSD, and provided by libc on Mac OS X. | ||
353 | for libname in ['uuid', 'c']: | ||
354 | try: | ||
355 | lib = ctypes.CDLL(ctypes.util.find_library(libname)) | ||
356 | except: | ||
357 | continue | ||
358 | if hasattr(lib, 'uuid_generate_random'): | ||
359 | _uuid_generate_random = lib.uuid_generate_random | ||
360 | if hasattr(lib, 'uuid_generate_time'): | ||
361 | _uuid_generate_time = lib.uuid_generate_time | ||
362 | |||
363 | # On Windows prior to 2000, UuidCreate gives a UUID containing the | ||
364 | # hardware address. On Windows 2000 and later, UuidCreate makes a | ||
365 | # random UUID and UuidCreateSequential gives a UUID containing the | ||
366 | # hardware address. These routines are provided by the RPC runtime. | ||
367 | try: | ||
368 | lib = ctypes.windll.rpcrt4 | ||
369 | except: | ||
370 | lib = None | ||
371 | _UuidCreate = getattr(lib, 'UuidCreateSequential', | ||
372 | getattr(lib, 'UuidCreate', None)) | ||
373 | except: | ||
374 | pass | ||
375 | |||
376 | def _unixdll_getnode(): | ||
377 | """Get the hardware address on Unix using ctypes.""" | ||
378 | _uuid_generate_time(_buffer) | ||
379 | return UUID(bytes=_buffer.raw).node | ||
380 | |||
381 | def _windll_getnode(): | ||
382 | """Get the hardware address on Windows using ctypes.""" | ||
383 | if _UuidCreate(_buffer) == 0: | ||
384 | return UUID(bytes=_buffer.raw).node | ||
385 | |||
386 | def _random_getnode(): | ||
387 | """Get a random node ID, with eighth bit set as suggested by RFC 4122.""" | ||
388 | import random | ||
389 | return random.randrange(0, 1<<48L) | 0x010000000000L | ||
390 | |||
391 | _node = None | ||
392 | |||
393 | def getnode(): | ||
394 | """Get the hardware address as a 48-bit integer. The first time this | ||
395 | runs, it may launch a separate program, which could be quite slow. If | ||
396 | all attempts to obtain the hardware address fail, we choose a random | ||
397 | 48-bit number with its eighth bit set to 1 as recommended in RFC 4122.""" | ||
398 | |||
399 | global _node | ||
400 | if _node is not None: | ||
401 | return _node | ||
402 | |||
403 | import sys | ||
404 | if sys.platform == 'win32': | ||
405 | getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] | ||
406 | else: | ||
407 | getters = [_unixdll_getnode, _ifconfig_getnode] | ||
408 | |||
409 | for getter in getters + [_random_getnode]: | ||
410 | try: | ||
411 | _node = getter() | ||
412 | except: | ||
413 | continue | ||
414 | if _node is not None: | ||
415 | return _node | ||
416 | |||
417 | def uuid1(node=None, clock_seq=None): | ||
418 | """Generate a UUID from a host ID, sequence number, and the current time. | ||
419 | If 'node' is not given, getnode() is used to obtain the hardware | ||
420 | address. If 'clock_seq' is given, it is used as the sequence number; | ||
421 | otherwise a random 14-bit sequence number is chosen.""" | ||
422 | |||
423 | # When the system provides a version-1 UUID generator, use it (but don't | ||
424 | # use UuidCreate here because its UUIDs don't conform to RFC 4122). | ||
425 | if _uuid_generate_time and node is clock_seq is None: | ||
426 | _uuid_generate_time(_buffer) | ||
427 | return UUID(bytes=_buffer.raw) | ||
428 | |||
429 | import time | ||
430 | nanoseconds = int(time.time() * 1e9) | ||
431 | # 0x01b21dd213814000 is the number of 100-ns intervals between the | ||
432 | # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. | ||
433 | timestamp = int(nanoseconds/100) + 0x01b21dd213814000L | ||
434 | if clock_seq is None: | ||
435 | import random | ||
436 | clock_seq = random.randrange(1<<14L) # instead of stable storage | ||
437 | time_low = timestamp & 0xffffffffL | ||
438 | time_mid = (timestamp >> 32L) & 0xffffL | ||
439 | time_hi_version = (timestamp >> 48L) & 0x0fffL | ||
440 | clock_seq_low = clock_seq & 0xffL | ||
441 | clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL | ||
442 | if node is None: | ||
443 | node = getnode() | ||
444 | return UUID(fields=(time_low, time_mid, time_hi_version, | ||
445 | clock_seq_hi_variant, clock_seq_low, node), version=1) | ||
446 | |||
447 | def uuid3(namespace, name): | ||
448 | """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" | ||
449 | import md5 | ||
450 | hash = md5.md5(namespace.bytes + name).digest() | ||
451 | return UUID(bytes=hash[:16], version=3) | ||
452 | |||
453 | def uuid4(): | ||
454 | """Generate a random UUID.""" | ||
455 | |||
456 | # When the system provides a version-4 UUID generator, use it. | ||
457 | if _uuid_generate_random: | ||
458 | _uuid_generate_random(_buffer) | ||
459 | return UUID(bytes=_buffer.raw) | ||
460 | |||
461 | # Otherwise, get randomness from urandom or the 'random' module. | ||
462 | try: | ||
463 | import os | ||
464 | return UUID(bytes=os.urandom(16), version=4) | ||
465 | except: | ||
466 | import random | ||
467 | bytes = [chr(random.randrange(256)) for i in range(16)] | ||
468 | return UUID(bytes=bytes, version=4) | ||
469 | |||
470 | def uuid5(namespace, name): | ||
471 | """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" | ||
472 | import sha | ||
473 | hash = sha.sha(namespace.bytes + name).digest() | ||
474 | return UUID(bytes=hash[:16], version=5) | ||
475 | |||
476 | # The following standard UUIDs are for use with uuid3() or uuid5(). | ||
477 | |||
478 | NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') | ||
479 | NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8') | ||
480 | NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') | ||
481 | NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8') | ||