Package pywbem :: Module cim_obj
[frames] | no frames]

Source Code for Module pywbem.cim_obj

   1  # 
   2  # (C) Copyright 2003-2007 Hewlett-Packard Development Company, L.P. 
   3  # (C) Copyright 2006-2007 Novell, Inc. 
   4  # 
   5  # This library is free software; you can redistribute it and/or 
   6  # modify it under the terms of the GNU Lesser General Public 
   7  # License as published by the Free Software Foundation; either 
   8  # version 2.1 of the License, or (at your option) any later version. 
   9  # 
  10  # This program is distributed in the hope that it will be useful, but 
  11  # WITHOUT ANY WARRANTY; without even the implied warranty of 
  12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  13  # Lesser General Public License for more details. 
  14  # 
  15  # You should have received a copy of the GNU Lesser General Public 
  16  # License along with this program; if not, write to the Free Software 
  17  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  18  # 
  19  # Author: Tim Potter <tpot@hp.com> 
  20  # Author: Martin Pool <mbp@hp.com> 
  21  # Author: Bart Whiteley <bwhiteley@suse.de> 
  22  # 
  23   
  24  """Representations of CIM objects, and a case-insensitive dictionary. 
  25   
  26  In general we try to map CIM objects directly into Python primitives, 
  27  except when that is not possible or would be ambiguous.  For example, 
  28  CIM class names are simply Python strings, but a class path is 
  29  represented as a special Python object. 
  30   
  31  These objects can also be mapped back into CIM-XML, by their `tocimxml()` 
  32  method which returns a CIM-XML string. 
  33  """ 
  34   
  35  # This module is meant to be safe for 'import *'. 
  36   
  37  import string 
  38  import re 
  39  from types import StringTypes 
  40  from datetime import datetime, timedelta 
  41   
  42  from pywbem import cim_xml, cim_types 
  43   
  44  __all__ = ['NocaseDict', 'cmpname', 'CIMClassName', 'CIMProperty', 
  45             'CIMInstanceName', 'CIMInstance', 'CIMClass', 'CIMMethod', 
  46             'CIMParameter', 'CIMQualifier', 'CIMQualifierDeclaration', 
  47             'tocimxml', 'tocimobj', 'byname'] 
  48   
49 -class NocaseDict(object):
50 """ 51 Yet another implementation of a case-insensitive dictionary. 52 53 Whenever keys are looked up, that is done case-insensitively. Whenever 54 keys are returned, they are returned with the lexical case that was 55 originally specified. 56 57 In addition to the methods listed, the dictionary supports: 58 59 * Retrieval of values based on key: `val = d[key]` 60 61 * Assigning values for a key: `d[key] = val` 62 63 * Deleting a key/value pair: `del d[key]` 64 65 * Equality comparison (`==`, `!=`) 66 67 * Ordering comparison (`<`, `<=`, `>=`, `>`) 68 69 * Containment test: `key in d` 70 71 * For loops: `for key in d` 72 73 * Determining length: `len(d)` 74 """ 75
76 - def __init__(self, *args, **kwargs):
77 """ 78 Initialize the new dictionary from at most one positional argument and 79 optionally from additional keyword arguments. 80 81 Initialization happens in two steps, first from the positional 82 argument: 83 84 * If no positional argument is provided, or if one argument with the 85 value None is provided, the new dictionary will be left empty in 86 this step. 87 88 * If one positional argument of sequence type is provided, the items 89 in that sequence must be tuples of key and value, respectively. 90 The key/value pairs will be put into the new dictionary (without 91 copying them). 92 93 * If one positional argument of dictionary (mapping) or `NocaseDict` 94 type is provided, its key/value pairs are put into the new 95 dictionary (without copying them). 96 97 * Otherwise, `TypeError` is raised. 98 99 After that, any provided keyword arguments are put into the so 100 initialized dictionary as key/value pairs (without copying them). 101 """ 102 103 self._data = {} 104 105 # Step 1: Initialize from at most one positional argument 106 if len(args) == 1: 107 if isinstance(args[0], list): 108 # Initialize from sequence object 109 for item in args[0]: 110 self[item[0]] = item[1] 111 elif isinstance(args[0], dict): 112 # Initialize from mapping object 113 self.update(args[0]) 114 elif isinstance(args[0], NocaseDict): 115 # Initialize from another NocaseDict object 116 self._data = args[0]._data.copy() # pylint: disable=protected-access 117 elif args[0] is None: 118 # Leave empty 119 pass 120 else: 121 raise TypeError("Invalid type for NocaseDict " \ 122 "initialization: %s" % repr(args[0])) 123 elif len(args) > 1: 124 raise TypeError("Too many positional arguments for NocaseDict " \ 125 "initialization: %s" % repr(args)) 126 127 # Step 2: Add any keyword arguments 128 self.update(kwargs)
129 130 # Basic accessor and settor methods 131
132 - def __getitem__(self, key):
133 """ 134 Invoked when retrieving the value for a key, using `val = d[key]`. 135 136 The key is looked up case-insensitively. Raises `KeyError` if the 137 specified key does not exist. Note that __setitem__() ensures that 138 only string typed keys will exist, so the key type is not tested here 139 and specifying non-string typed keys will simply lead to a KeyError. 140 """ 141 k = key 142 if isinstance(key, (str, unicode)): 143 k = k.lower() 144 try: 145 return self._data[k][1] 146 except KeyError: 147 raise KeyError('Key %s not found in %r' % (key, self))
148
149 - def __setitem__(self, key, value):
150 """ 151 Invoked when assigning a value for a key using `d[key] = val`. 152 153 The key is looked up case-insensitively. If the key does not exist, 154 it is added with the new value. Otherwise, its value is overwritten 155 with the new value. 156 157 Raises `TypeError` if the specified key does not have string type. 158 """ 159 if not isinstance(key, (str, unicode)): 160 raise TypeError('NocaseDict key %s must be string type, ' \ 161 'but is %s' % (key, type(key))) 162 k = key.lower() 163 self._data[k] = (key, value)
164
165 - def __delitem__(self, key):
166 """ 167 Invoked when deleting a key/value pair using `del d[key]`. 168 169 The key is looked up case-insensitively. Raises `KeyError` if the 170 specified key does not exist. Note that __setitem__() ensures that 171 only string typed keys will exist, so the key type is not tested here 172 and specifying non-string typed keys will simply lead to a KeyError. 173 """ 174 k = key 175 if isinstance(key, (str, unicode)): 176 k = k.lower() 177 try: 178 del self._data[k] 179 except KeyError: 180 raise KeyError('Key %s not found in %r' % (key, self))
181
182 - def __len__(self):
183 """ 184 Invoked when determining the number of key/value pairs in the 185 dictionary using `len(d)`. 186 """ 187 return len(self._data)
188
189 - def has_key(self, key):
190 """ 191 Return a boolean indicating whether a specific key is in the 192 dictionary. 193 194 The key is looked up case-insensitively. 195 196 This method is deprecated in favor of using `key in d`. 197 """ 198 return key in self # delegate to __contains__()
199
200 - def __contains__(self, key):
201 """ 202 Invoked when determining whether a specific key is in the dictionary 203 using `key in d`. 204 205 The key is looked up case-insensitively. 206 """ 207 k = key 208 if isinstance(key, (str, unicode)): 209 k = k.lower() 210 return k in self._data
211
212 - def get(self, key, default=None):
213 """ 214 Get the value for a specific key, or the specified default value if 215 the key does not exist. 216 217 The key is looked up case-insensitively. 218 """ 219 try: 220 return self[key] 221 except KeyError: 222 return default
223
224 - def setdefault(self, key, default):
225 """ 226 Assign the specified default value for a specific key if the key did 227 not exist and return the value for the key. 228 229 The key is looked up case-insensitively. 230 """ 231 if not self.has_key(key): 232 self[key] = default 233 return self[key]
234 235 # Other accessor expressed in terms of iterators 236
237 - def keys(self):
238 """ 239 Return a copied list of the dictionary keys, in their original case. 240 """ 241 return list(self.iterkeys())
242
243 - def values(self):
244 """ 245 Return a copied list of the dictionary values. 246 """ 247 return list(self.itervalues())
248
249 - def items(self):
250 """ 251 Return a copied list of the dictionary items, where each item is a 252 tuple of its original key and its value. 253 """ 254 return list(self.iteritems())
255 256 # Iterators 257
258 - def iterkeys(self):
259 """ 260 Return an iterator through the dictionary keys in their original 261 case. 262 """ 263 for item in self._data.iteritems(): 264 yield item[1][0]
265
266 - def itervalues(self):
267 """ 268 Return an iterator through the dictionary values. 269 """ 270 for item in self._data.iteritems(): 271 yield item[1][1]
272
273 - def iteritems(self):
274 """ 275 Return an iterator through the dictionary items, where each item is a 276 tuple of its original key and its value. 277 """ 278 for item in self._data.iteritems(): 279 yield item[1]
280
281 - def __iter__(self):
282 """ 283 Invoked when iterating through the dictionary using `for key in d`. 284 285 The returned keys have their original case. 286 """ 287 return self.iterkeys()
288 289 # Other stuff 290
291 - def __repr__(self):
292 """ 293 Invoked when using `repr(d)`. 294 295 The representation hides the implementation data structures and shows 296 a dictionary that can be used for the constructor. 297 """ 298 items = ', '.join([('%r: %r' % (key, value)) 299 for key, value in self.iteritems()]) 300 return 'NocaseDict({%s})' % items
301
302 - def update(self, *args, **kwargs):
303 """ 304 Update the dictionary from sequences of key/value pairs provided in any 305 positional arguments, and from key/value pairs provided in any keyword 306 arguments. The key/value pairs are not copied. 307 308 Each positional argument can be: 309 310 * an object with a method `items()` that returns an iterable of 311 tuples containing key and value. 312 313 * an object without such a method, that is an iterable of tuples 314 containing key and value. 315 316 Each keyword argument is a key/value pair. 317 """ 318 for mapping in args: 319 if hasattr(mapping, 'items'): 320 for k, v in mapping.items(): 321 self[k] = v 322 else: 323 for k, v in mapping: 324 self[k] = v 325 for k, v in kwargs.items(): 326 self[k] = v
327
328 - def clear(self):
329 """ 330 Remove all items from the dictionary. 331 """ 332 self._data.clear()
333
334 - def popitem(self):
335 """ 336 This function does nothing. 337 338 In a standard mapping implementation, it would remove and return an 339 arbitrary item from the dictionary. 340 341 TODO: Why does popitem() do nothing; was it simply not implemented? 342 """ 343 pass
344
345 - def copy(self):
346 """ 347 Return a shallow copy of the dictionary (i.e. the keys and values are 348 not copied). 349 """ 350 result = NocaseDict() 351 result._data = self._data.copy() # pylint: disable=protected-access 352 return result
353
354 - def __eq__(self, other):
355 """ 356 Invoked when two dictionaries are compared for equality or inequality. 357 358 The keys are looked up case-insensitively. 359 360 The comparison is delegated to equality comparison of matching 361 key/value pairs. 362 """ 363 for key, value in self.iteritems(): 364 if not key in other or not other[key] == value: 365 return 0 366 return len(self) == len(other)
367
368 - def __cmp__(self, other):
369 """ 370 Invoked when two dictionaries are compared for equality, inequality, 371 and greater-than/less-than comparisons. 372 373 The keys are looked up case-insensitively. 374 375 `Self` is less than `other`, if: 376 377 * a key in `self` is not in `other`, or 378 379 * the value for a key in `self` is less than the value for that key 380 in `other`, or 381 382 * `self` has less key/value pairs than `other`. 383 """ 384 for key, value in self.iteritems(): 385 if not key in other: 386 return -1 387 rv = cmp(value, other[key]) 388 if rv != 0: 389 return rv 390 return len(self) - len(other)
391
392 -def _intended_value(intended, unspecified, actual, name, msg):
393 """ 394 Return the intended value if the actual value is unspecified or has 395 the intended value already, and otherwise raise a ValueError with the 396 specified error message. 397 398 Arguments: 399 400 * `intended`: The intended value, or sequence of values. The first 401 item in the sequence will act as the intended value, the others 402 are also valid values. 403 * `unspecified`: A value indicating 'unspecified' (usually `None`). 404 * `actual`: The actual value. 405 * `name`: The name of the attribute that this is about, for use in the 406 exception message. 407 * `msg`: A context setting message, for use in the exception message. 408 """ 409 410 if isinstance(intended, (tuple, list)): 411 if actual == unspecified: 412 return intended[0] # the default 413 elif actual in intended: 414 return actual 415 else: 416 raise ValueError(msg + ", but specifies %s=%r (must be one of %r)"\ 417 % (name, actual, intended)) 418 else: 419 if actual == unspecified: 420 return intended 421 elif actual == intended: 422 return actual 423 else: 424 raise ValueError(msg + ", but specifies %s=%r (must be %r)"\ 425 % (name, actual, intended))
426
427 -def cmpname(name1, name2):
428 """ 429 Compare two CIM names. The comparison is done 430 case-insensitively, and one or both of the names may be `None`. 431 """ 432 433 if name1 is None and name2 is None: 434 return 0 435 436 if name1 is None: 437 return -1 438 439 if name2 is None: 440 return 1 441 442 lower_name1 = name1.lower() 443 lower_name2 = name2.lower() 444 445 return cmp(lower_name1, lower_name2)
446
447 -def _makequalifiers(qualifiers, indent):
448 """Return a MOF fragment for a NocaseDict of qualifiers.""" 449 450 if len(qualifiers) == 0: 451 return '' 452 453 return '[%s]' % ',\n '.ljust(indent+2).\ 454 join([q.tomof(indent) for q in sorted(qualifiers.values())])
455
456 -def mofstr(strvalue, indent=7, maxline=80):
457 """Converts the input string value to a MOF literal string value, including 458 the surrounding double quotes. 459 460 In doing so, all characters that have MOF escape characters (except for 461 single quotes) are escaped by adding a leading backslash (\), if not yet 462 present. This conditional behavior is needed for WBEM servers that return 463 the MOF escape sequences in their CIM-XML representation of any strings, 464 instead of converting them to the binary characters as required by the CIM 465 standards. 466 467 Single quotes do not need to be escaped because the returned literal 468 string uses double quotes. 469 470 After escaping, the string is broken into multiple lines, for better 471 readability. The maximum line size is specified via the ``maxline`` 472 argument. The indentation for any spilled over lines (i.e. not the first 473 line) is specified via the ``indent`` argument. 474 """ 475 476 # escape \n, \r, \t, \f, \b 477 escaped_str = strvalue.replace("\n","\\n").replace("\r","\\r").\ 478 replace("\t","\\t").replace("\f","\\f").replace("\b","\\b") 479 480 # escape double quote (") if not already escaped. 481 # TODO: Add support for two consecutive double quotes (""). 482 escaped_str = re.sub(r'([^\\])"', r'\1\\"', escaped_str) 483 484 # escape special case of a single double quote (") 485 escaped_str = re.sub(r'^"$', r'\"', escaped_str) 486 487 # escape backslash (\) not followed by any of: nrtfb"' 488 escaped_str = re.sub(r'\\([^nrtfb"\'])', r'\\\1', escaped_str) 489 490 # escape special case of a single backslash (\) 491 escaped_str = re.sub(r'^\\$', r'\\\\', escaped_str) 492 493 # Break into multiple strings for better readability 494 blankfind = maxline - indent - 2 495 indent_str = ' '.ljust(indent, ' ') 496 ret_str_list = list() 497 if escaped_str == '': 498 ret_str_list.append('""') 499 else: 500 while escaped_str != '': 501 if len(escaped_str) <= blankfind: 502 ret_str_list.append('"' + escaped_str + '"') 503 escaped_str = '' 504 else: 505 splitpos = escaped_str.rfind(' ',0,blankfind) 506 if splitpos < 0: 507 splitpos = blankfind-1 508 ret_str_list.append('"' + escaped_str[0:splitpos+1] + '"') 509 escaped_str = escaped_str[splitpos+1:] 510 511 ret_str = ('\n'+indent_str).join(ret_str_list) 512 return ret_str
513
514 -def moftype(cimtype, refclass):
515 """Converts a CIM type name to MOF syntax.""" 516 517 if cimtype == 'reference': 518 _moftype = refclass + " REF" 519 else: 520 _moftype = cimtype 521 522 return _moftype
523
524 -class CIMClassName(object):
525 """ 526 A CIM class path. 527 528 A CIM class path references a CIM class in a namespace in a WBEM server. 529 Namespace and WBEM server may be unknown. 530 531 :Ivariables: 532 533 ... 534 All parameters of `__init__` are set as instance variables. 535 """ 536
537 - def __init__(self, classname, host=None, namespace=None):
538 """ 539 Initialize the `CIMClassName` object. 540 541 :Parameters: 542 543 classname : `unicode` or UTF-8 encoded `str` 544 Name of the referenced class. 545 546 host : `unicode` or UTF-8 encoded `str` 547 Optional: URL of the WBEM server that contains the CIM namespace 548 of this class path. 549 550 If `None`, the class path will not specify a WBEM server. 551 552 Default: `None`. 553 554 namespace : `unicode` or UTF-8 encoded `str` 555 Optional: Name of the CIM namespace that contains the referenced 556 class. 557 558 If `None`, the class path will not specify a CIM namespace. 559 560 Default: `None`. 561 562 :Raises: 563 :raise TypeError: 564 :raise ValueError: 565 """ 566 567 if not isinstance(classname, StringTypes): 568 raise TypeError('classname argument has an invalid type: %s '\ 569 '(expected string)' % type(classname)) 570 571 # TODO: There are some odd restrictions on what a CIM 572 # classname can look like (i.e must start with a 573 # non-underscore and only one underscore per classname). 574 575 self.classname = classname 576 self.host = host 577 self.namespace = namespace
578
579 - def copy(self):
580 return CIMClassName(self.classname, host=self.host, 581 namespace=self.namespace)
582
583 - def __cmp__(self, other):
584 585 if self is other: 586 return 0 587 elif not isinstance(other, CIMClassName): 588 return 1 589 590 return (cmpname(self.classname, other.classname) or 591 cmpname(self.host, other.host) or 592 cmpname(self.namespace, other.namespace))
593
594 - def __str__(self):
595 596 s = '' 597 598 if self.host is not None: 599 s += '//%s/' % self.host 600 601 if self.namespace is not None: 602 s += '%s:' % self.namespace 603 604 s += self.classname 605 606 return s
607
608 - def __repr__(self):
609 610 r = '%s(classname=%r' % (self.__class__.__name__, self.classname) 611 612 if self.host is not None: 613 r += ', host=%r' % self.host 614 615 if self.namespace is not None: 616 r += ', namespace=%r' % self.namespace 617 618 r += ')' 619 620 return r
621
622 - def tocimxml(self):
623 624 classname = cim_xml.CLASSNAME(self.classname) 625 626 if self.namespace is not None: 627 628 localnsp = cim_xml.LOCALNAMESPACEPATH( 629 [cim_xml.NAMESPACE(ns) 630 for ns in string.split(self.namespace, '/')]) 631 632 if self.host is not None: 633 634 # Classname + namespace + host = CLASSPATH 635 636 return cim_xml.CLASSPATH( 637 cim_xml.NAMESPACEPATH(cim_xml.HOST(self.host), localnsp), 638 classname) 639 640 # Classname + namespace = LOCALCLASSPATH 641 642 return cim_xml.LOCALCLASSPATH(localnsp, classname) 643 644 # Just classname = CLASSNAME 645 646 return cim_xml.CLASSNAME(self.classname)
647
648 -class CIMProperty(object):
649 """ 650 A CIM property. 651 652 The property can be used in a CIM instance (as part of a `CIMInstance` 653 object) or in a CIM class (as part of a `CIMClass` object). 654 655 For properties in CIM instances: 656 657 * The `value` instance variable is the actual value of the property. 658 * Qualifiers are not allowed. 659 660 For properties in CIM classes: 661 662 * The `value` instance variable is the default value for the property. 663 * Qualifiers are allowed. 664 665 Scalar (=non-array) properties may have a value of NULL (= `None`), any 666 primitive CIM type, reference type, and string type with embedded instance 667 or embedded object. 668 669 Array properties may be Null or may have elements with a value of NULL, any 670 primitive CIM type, and string type with embedded instance or embedded 671 object. Reference types are not allowed in property arrays in CIM, as per 672 DMTF DSP0004. 673 674 :Ivariables: 675 676 ... 677 All parameters of `__init__` are set as instance variables. 678 """ 679
680 - def __init__(self, name, value, type=None, 681 class_origin=None, array_size=None, propagated=None, 682 is_array=None, reference_class=None, qualifiers=None, 683 embedded_object=None):
684 """ 685 Initialize the `CIMProperty` object. 686 687 This function infers optional arguments that are not specified (for 688 example, it infers `type` from the Python type of `value` and other 689 information). If the specified arguments are inconsistent, an 690 exception is raised. If an optional argument is needed for some reason, 691 an exception is raised. 692 693 :Parameters: 694 695 name : `unicode` or UTF-8 encoded `str` 696 Name of the property. Must not be `None`. 697 698 value 699 Value of the property (interpreted as actual value when the 700 property object is used in an instance, and as default value when 701 it is used in a class). 702 For valid types for CIM values, see `cim_types`. 703 704 type : string 705 Name of the CIM type of the property (e.g. `'uint8'`). 706 `None` means that the argument is unspecified, causing the 707 corresponding instance variable to be inferred. An exception is 708 raised if it cannot be inferred. 709 710 class_origin : `unicode` or UTF-8 encoded `str` 711 The CIM class origin of the property (the name 712 of the most derived class that defines or overrides the property in 713 the class hierarchy of the class owning the property). 714 `None` means that class origin information is not available. 715 716 array_size : `int` 717 The size of the array property, for fixed-size arrays. 718 `None` means that the array property has variable size. 719 720 propagated : `unicode` or UTF-8 encoded `str` 721 The CIM *propagated* attribute of the property (the effective value 722 of the `Propagated` qualifier of the property, which is a string 723 that specifies the name of the source property from which the 724 property value should be propagated). 725 `None` means that propagation information is not available. 726 727 is_array : `bool` 728 A boolean indicating whether the property is an array (`True`) or a 729 scalar (`False`). 730 `None` means that the argument is unspecified, causing the 731 corresponding instance variable to be inferred from the `value` 732 parameter, and if that is `None` it defaults to `False` (scalar). 733 734 reference_class : `unicode` or UTF-8 encoded `str` 735 The name of the referenced class, for reference properties. 736 `None` means that the argument is unspecified, causing the 737 corresponding instance variable to be inferred. An exception is 738 raised if it cannot be inferred. 739 740 qualifiers : `dict` or `NocaseDict` 741 A dictionary specifying CIM qualifier values. 742 The dictionary keys must be the qualifier names. The dictionary 743 values must be `CIMQualifier` objects specifying the qualifier 744 values. 745 `None` means that there are no qualifier values. In all cases, 746 the `qualifiers` instance variable will be a `NocaseDict` object. 747 748 embedded_object : string 749 A string value indicating the kind of 750 embedded object represented by the property value. The following 751 values are defined for this argument: 752 `'instance'`: The property is declared with the 753 `EmbeddedInstance` qualifier, indicating that the property 754 value is an embedded instance of a known class name (or Null). 755 `'object'`: The property is declared with the 756 `EmbeddedObject` qualifier, indicating that the property 757 value is an embedded object (instance or class) of which the 758 class name is not known (or Null). 759 `None` means that the argument is unspecified, causing the 760 corresponding instance variable to be inferred. An exception is 761 raised if it cannot be inferred. 762 763 Examples: 764 765 * `CIMProperty("MyString", "abc")` 766 -> a string property 767 * `CIMProperty("MyNum", 42, "uint8")` 768 -> a uint8 property 769 * `CIMProperty("MyNum", Uint8(42))` 770 -> a uint8 property 771 * `CIMProperty("MyNumArray", [1,2,3], "uint8")` 772 -> a uint8 array property 773 * `CIMProperty("MyRef", CIMInstanceName(...))` 774 -> a reference property 775 * `CIMProperty("MyEmbObj", CIMClass(...))` 776 -> an embedded object property containing a class 777 * `CIMProperty("MyEmbObj", CIMInstance(...), 778 embedded_object='object')` 779 -> an embedded object property containing an instance 780 * `CIMProperty("MyEmbInst", CIMInstance(...))` 781 -> an embedded instance property 782 * `CIMProperty("MyString", None, "string")` 783 -> a string property that is Null 784 * `CIMProperty("MyNum", None, "uint8")` 785 -> a uint8 property that is Null 786 * `CIMProperty("MyRef", None, reference_class="MyClass")` 787 -> a reference property that is Null 788 * `CIMProperty("MyEmbObj", None, embedded_object='object')` 789 -> an embedded object property that is Null 790 * `CIMProperty("MyEmbInst", None, embedded_object='instance')` 791 -> an embedded instance property that is Null 792 793 :Raises: 794 :raise TypeError: 795 :raise ValueError: 796 """ 797 798 from __builtin__ import type as __type 799 800 # Check `name` 801 802 if name is None: 803 raise ValueError('Property must have a name') 804 805 # General checks: 806 807 if embedded_object not in (None, 'instance', 'object'): 808 raise ValueError('Property %r specifies an invalid ' \ 809 'embedded_object=%r' % (name, embedded_object)) 810 811 if is_array not in (None, True, False): 812 raise ValueError('Property %r specifies an invalid ' \ 813 'is_array=%r' % (name, is_array)) 814 815 # Set up is_array 816 817 if isinstance(value, (list, tuple)): 818 is_array = _intended_value(True, 819 None, is_array, 'is_array', 820 'Property %r has a value that is an array (%s)' % \ 821 (name, __type(value))) 822 elif value is not None: # Scalar value 823 is_array = _intended_value(False, 824 None, is_array, 'is_array', 825 'Property %r has a value that is a scalar (%s)' % \ 826 (name, __type(value))) 827 else: # Null value 828 if is_array is None: 829 is_array = False # For compatibility with old default 830 831 if not is_array and array_size is not None: 832 raise ValueError('Scalar property %r specifies array_size=%r ' \ 833 '(must be None)' % (name, array_size)) 834 835 # Determine type, embedded_object, and reference_class attributes. 836 # Make sure value is CIM-typed. 837 838 if is_array: # Array property 839 if reference_class is not None: 840 raise ValueError( 841 'Array property %r cannot specify reference_class' % name) 842 elif value is None or len(value) == 0 or value[0] is None: 843 # Cannot infer from value, look at embedded_object and type 844 if embedded_object == 'instance': 845 msg = 'Array property %r contains embedded instances' % name 846 type = _intended_value('string', 847 None, type, 'type', msg) 848 elif embedded_object == 'object': 849 msg = 'Array property %r contains embedded objects' % name 850 type = _intended_value('string', 851 None, type, 'type', msg) 852 elif type is not None: 853 # Leave type as specified, but check it for validity 854 dummy_type_obj = cim_types.type_from_name(type) 855 else: 856 raise ValueError( 857 'Cannot infer type of array property %r that is ' \ 858 'Null, empty, or has Null as its first element' % \ 859 name) 860 elif isinstance(value[0], CIMInstance): 861 msg = 'Array property %r contains CIMInstance values' % name 862 type = _intended_value('string', 863 None, type, 'type', msg) 864 embedded_object = _intended_value(('instance', 'object'), 865 None, embedded_object, 'embedded_object', msg) 866 elif isinstance(value[0], CIMClass): 867 msg = 'Array property %r contains CIMClass values' % name 868 type = _intended_value('string', 869 None, type, 'type', msg) 870 embedded_object = _intended_value('object', 871 None, embedded_object, 'embedded_object', msg) 872 elif isinstance(value[0], (datetime, timedelta)): 873 value = [cim_types.CIMDateTime(val) if val is not None 874 else val for val in value] 875 msg = 'Array property %r contains datetime or timedelta ' \ 876 'values' % name 877 type = _intended_value('datetime', 878 None, type, 'type', msg) 879 embedded_object = _intended_value(None, 880 None, embedded_object, 'embedded_object', msg) 881 elif type == 'datetime': 882 value = [cim_types.CIMDateTime(val) if val is not None 883 and not isinstance(val, cim_types.CIMDateTime) 884 else val for val in value] 885 msg = 'Array property %r specifies CIM type %r' % (name, type) 886 embedded_object = _intended_value(None, 887 None, embedded_object, 'embedded_object', msg) 888 elif type is None: 889 # Determine simple type from (non-Null) value 890 type = cim_types.cimtype(value[0]) 891 msg = 'Array property %r contains simple typed values ' \ 892 'with no CIM type specified' % name 893 embedded_object = _intended_value(None, 894 None, embedded_object, 'embedded_object', msg) 895 else: # type is specified and value (= entire array) is not Null 896 # Make sure the array elements are of the corresponding Python 897 # type. 898 value = [cim_types.type_from_name(type)(val) if val is not None 899 else val for val in value] 900 msg = 'Array property %r contains simple typed values ' \ 901 'and specifies CIM type %r' % (name, type) 902 embedded_object = _intended_value(None, 903 None, embedded_object, 'embedded_object', msg) 904 else: # Scalar property 905 if value is None: 906 # Try to infer from embedded_object, reference_class, and type 907 if embedded_object == 'instance': 908 msg = 'Property %r contains embedded instance' % name 909 type = _intended_value('string', 910 None, type, 'type', msg) 911 reference_class = _intended_value(None, 912 None, reference_class, 'reference_class', msg) 913 elif embedded_object == 'object': 914 msg = 'Property %r contains embedded object' % name 915 type = _intended_value('string', 916 None, type, 'type', msg) 917 reference_class = _intended_value(None, 918 None, reference_class, 'reference_class', msg) 919 elif reference_class is not None: 920 msg = 'Property %r is a reference' % name 921 embedded_object = _intended_value(None, 922 None, embedded_object, 'embedded_object', msg) 923 type = _intended_value('reference', 924 None, type, 'type', msg) 925 elif type is not None: 926 # Leave type as specified, but check it for validity 927 dummy_type_obj = cim_types.type_from_name(type) 928 else: 929 raise ValueError('Cannot infer type of simple ' \ 930 'property %r that is Null' % name) 931 elif isinstance(value, CIMInstanceName): 932 msg = 'Property %r has a CIMInstanceName value with ' \ 933 'classname=%r' % (name, value.classname) 934 reference_class = _intended_value(value.classname, 935 None, reference_class, 'reference_class', msg) 936 type = _intended_value('reference', 937 None, type, 'type', msg) 938 embedded_object = _intended_value(None, 939 None, embedded_object, 'embedded_object', msg) 940 elif isinstance(value, CIMInstance): 941 msg = 'Property %r has a CIMInstance value' % name 942 type = _intended_value('string', 943 None, type, 'type', msg) 944 embedded_object = _intended_value(('instance', 'object'), 945 None, embedded_object, 'embedded_object', msg) 946 reference_class = _intended_value(None, 947 None, reference_class, 'reference_class', msg) 948 elif isinstance(value, CIMClass): 949 msg = 'Property %r has a CIMClass value' % name 950 type = _intended_value('string', 951 None, type, 'type', msg) 952 embedded_object = _intended_value('object', 953 None, embedded_object, 'embedded_object', msg) 954 reference_class = _intended_value(None, 955 None, reference_class, 'reference_class', msg) 956 elif isinstance(value, (datetime, timedelta)): 957 value = cim_types.CIMDateTime(value) 958 msg = 'Property %r has a datetime or timedelta value' % name 959 type = _intended_value('datetime', 960 None, type, 'type', msg) 961 embedded_object = _intended_value(None, 962 None, embedded_object, 'embedded_object', msg) 963 reference_class = _intended_value(None, 964 None, reference_class, 'reference_class', msg) 965 elif type == 'datetime': 966 if not isinstance(value, cim_types.CIMDateTime): 967 value = cim_types.CIMDateTime(value) 968 msg = 'Property %r specifies CIM type %r' % (name, type) 969 embedded_object = _intended_value(None, 970 None, embedded_object, 'embedded_object', msg) 971 reference_class = _intended_value(None, 972 None, reference_class, 'reference_class', msg) 973 elif type is None: 974 # Determine simple type from (non-Null) value 975 type = cim_types.cimtype(value) 976 msg = 'Property %r has a simple typed value ' \ 977 'with no CIM type specified' % name 978 embedded_object = _intended_value(None, 979 None, embedded_object, 'embedded_object', msg) 980 reference_class = _intended_value(None, 981 None, reference_class, 'reference_class', msg) 982 else: # type is specified and value is not Null 983 # Make sure the value is of the corresponding Python type. 984 _type_obj = cim_types.type_from_name(type) 985 value = _type_obj(value) 986 msg = 'Property %r has a simple typed value ' \ 987 'and specifies CIM type %r' % (name, type) 988 embedded_object = _intended_value(None, 989 None, embedded_object, 'embedded_object', msg) 990 reference_class = _intended_value(None, 991 None, reference_class, 'reference_class', msg) 992 993 # Initialize members 994 self.name = name 995 self.value = value 996 self.type = type 997 self.class_origin = class_origin 998 self.array_size = array_size 999 self.propagated = propagated 1000 self.is_array = is_array 1001 self.reference_class = reference_class 1002 self.qualifiers = NocaseDict(qualifiers) 1003 self.embedded_object = embedded_object
1004
1005 - def copy(self):
1006 1007 return CIMProperty(self.name, 1008 self.value, 1009 type=self.type, 1010 class_origin=self.class_origin, 1011 array_size=self.array_size, 1012 propagated=self.propagated, 1013 is_array=self.is_array, 1014 reference_class=self.reference_class, 1015 qualifiers=self.qualifiers.copy())
1016
1017 - def __repr__(self):
1018 1019 return '%s(name=%r, value=%r, type=%r, class_origin=%r, ' \ 1020 'array_size=%r, propagated=%r, is_array=%r, ' \ 1021 'reference_class=%r, qualifiers=%r, embedded_object=%r)' % \ 1022 (self.__class__.__name__, self.name, self.value, self.type, 1023 self.class_origin, self.array_size, self.propagated, 1024 self.is_array, self.reference_class, self.qualifiers, 1025 self.embedded_object)
1026
1027 - def tocimxml(self):
1028 1029 if self.is_array: 1030 1031 value = self.value 1032 if value is not None: 1033 if value: 1034 if self.embedded_object is not None: 1035 value = [v.tocimxml().toxml() for v in value] 1036 value = cim_xml.VALUE_ARRAY( 1037 [cim_xml.VALUE( 1038 cim_types.atomic_to_cim_xml(v)) for v in value]) 1039 1040 return cim_xml.PROPERTY_ARRAY( 1041 self.name, 1042 self.type, 1043 value, 1044 self.array_size, 1045 self.class_origin, 1046 self.propagated, 1047 qualifiers=[q.tocimxml() for q in self.qualifiers.values()], 1048 embedded_object=self.embedded_object) 1049 1050 elif self.type == 'reference': 1051 1052 value_reference = None 1053 if self.value is not None: 1054 value_reference = cim_xml.VALUE_REFERENCE(self.value.tocimxml()) 1055 1056 return cim_xml.PROPERTY_REFERENCE( 1057 self.name, 1058 value_reference, 1059 reference_class=self.reference_class, 1060 class_origin=self.class_origin, 1061 propagated=self.propagated, 1062 qualifiers=[q.tocimxml() for q in self.qualifiers.values()]) 1063 1064 else: 1065 value = self.value 1066 if value is not None: 1067 if self.embedded_object is not None: 1068 value = value.tocimxml().toxml() 1069 else: 1070 value = cim_types.atomic_to_cim_xml(value) 1071 value = cim_xml.VALUE(value) 1072 1073 return cim_xml.PROPERTY( 1074 self.name, 1075 self.type, 1076 value, 1077 class_origin=self.class_origin, 1078 propagated=self.propagated, 1079 qualifiers=[q.tocimxml() for q in self.qualifiers.values()], 1080 embedded_object=self.embedded_object)
1081
1082 - def __cmp__(self, other):
1083 1084 if self is other: 1085 return 0 1086 elif not isinstance(other, self.__class__): 1087 return 1 1088 1089 return (cmpname(self.name, other.name) 1090 or cmp(self.value, other.value) 1091 or cmp(self.type, other.type) 1092 or cmp(self.class_origin, other.class_origin) 1093 or cmp(self.array_size, other.array_size) 1094 or cmp(self.propagated, other.propagated) 1095 or cmp(self.qualifiers, other.qualifiers) 1096 or cmp(self.is_array, other.is_array) 1097 or cmpname(self.reference_class, other.reference_class))
1098
1099 -class CIMInstanceName(object):
1100 """ 1101 A CIM instance path (aka *instance name*). 1102 1103 A CIM instance path references a CIM instance in a namespace in a WBEM 1104 server. 1105 Namespace and WBEM server may be unknown. 1106 1107 This object can be used like a dictionary to retrieve the key bindings. 1108 1109 :Ivariables: 1110 1111 ... 1112 All parameters of `__init__` are set as instance variables. 1113 """ 1114
1115 - def __init__(self, classname, keybindings=None, host=None, namespace=None):
1116 """ 1117 Initialize the `CIMInstanceName` object. 1118 1119 :Parameters: 1120 1121 classname : `unicode` or UTF-8 encoded `str` 1122 Name of the creation class of the referenced instance. 1123 1124 keybindings : `dict` or `NocaseDict` 1125 Optional: Dictionary of key bindings, specifying key properties 1126 that identify the referenced instance. 1127 The dictionary must contain one item for each key property, where: 1128 1129 - its key is the property name. 1130 - its value is the property value, as a CIM typed value as 1131 described in `cim_types`. 1132 1133 If `None`, an empty dictionary of key bindings will be created. 1134 1135 Default: `None`. 1136 1137 host : `unicode` or UTF-8 encoded `str` 1138 Optional: URL of the WBEM server that contains the CIM namespace 1139 of this instance path. 1140 1141 If `None`, the instance path will not specify a WBEM server. 1142 1143 Default: `None`. 1144 1145 namespace : `unicode` or UTF-8 encoded `str` 1146 Optional: Name of the CIM namespace that contains the referenced 1147 instance. 1148 1149 If `None`, the instance path will not specify a CIM namespace. 1150 1151 Default: `None`. 1152 1153 :Raises: 1154 :raise TypeError: 1155 :raise ValueError: 1156 """ 1157 1158 if classname is None: 1159 raise ValueError('Instance path must have a class name') 1160 1161 self.classname = classname 1162 self.keybindings = NocaseDict(keybindings) 1163 self.host = host 1164 self.namespace = namespace
1165
1166 - def copy(self):
1167 1168 result = CIMInstanceName(self.classname) 1169 result.keybindings = self.keybindings.copy() 1170 result.host = self.host 1171 result.namespace = self.namespace 1172 1173 return result
1174
1175 - def __cmp__(self, other):
1176 1177 if self is other: 1178 return 0 1179 elif not isinstance(other, CIMInstanceName): 1180 return 1 1181 1182 return (cmpname(self.classname, other.classname) or 1183 cmp(self.keybindings, other.keybindings) or 1184 cmpname(self.host, other.host) or 1185 cmpname(self.namespace, other.namespace))
1186
1187 - def __str__(self):
1188 1189 s = '' 1190 1191 if self.host is not None: 1192 s += '//%s/' % self.host 1193 1194 if self.namespace is not None: 1195 s += '%s:' % self.namespace 1196 1197 s += '%s.' % self.classname 1198 1199 for key, value in self.keybindings.items(): 1200 1201 s += '%s=' % key 1202 1203 if isinstance(value, (int, long, bool, float)): 1204 s += str(value) 1205 elif isinstance(value, CIMInstanceName): 1206 s += '"%s"' % str(value).replace('\\', '\\\\').replace( 1207 '"', '\\"') 1208 else: 1209 s += '"%s"' % value 1210 1211 s += ',' 1212 1213 return s[:-1]
1214
1215 - def __repr__(self):
1216 1217 r = '%s(classname=%r, keybindings=%r' % \ 1218 (self.__class__.__name__, self.classname, self.keybindings) 1219 1220 if self.host is not None: 1221 r += ', host=%r' % self.host 1222 1223 if self.namespace is not None: 1224 r += ', namespace=%r' % self.namespace 1225 1226 r += ')' 1227 1228 return r
1229 1230 # A whole bunch of dictionary methods that map to the equivalent 1231 # operation on self.keybindings. 1232
1233 - def __getitem__(self, key): return self.keybindings[key]
1234 - def __contains__(self, key): return key in self.keybindings
1235 - def __delitem__(self, key): del self.keybindings[key]
1236 - def __setitem__(self, key, value): self.keybindings[key] = value
1237 - def __len__(self): return len(self.keybindings)
1238 - def has_key(self, key): return self.keybindings.has_key(key)
1239 - def keys(self): return self.keybindings.keys()
1240 - def values(self): return self.keybindings.values()
1241 - def items(self): return self.keybindings.items()
1242 - def iterkeys(self): return self.keybindings.iterkeys()
1243 - def itervalues(self): return self.keybindings.itervalues()
1244 - def iteritems(self): return self.keybindings.iteritems()
1245 - def update(self, *args, **kwargs): self.keybindings.update(*args, **kwargs)
1246
1247 - def get(self, key, default=None):
1248 """ 1249 Get the value of a specific key property, or the specified default 1250 value if a key binding with that name does not exist. 1251 """ 1252 return self.keybindings.get(key, default)
1253
1254 - def tocimxml(self):
1255 """Generate a CIM-XML representation of the instance name (class name 1256 and key bindings).""" 1257 1258 if type(self.keybindings) == str: 1259 1260 # Class with single key string property 1261 1262 # This cannot happen; self.keybindings is always a NocaseDict: 1263 # TODO: Remove this if clause after verifying that it works. 1264 raise TypeError("Unexpected: keybindings has string type: %s" % \ 1265 repr(self.keybindings)) 1266 1267 instancename_xml = cim_xml.INSTANCENAME( 1268 self.classname, 1269 cim_xml.KEYVALUE(self.keybindings, 'string')) 1270 1271 elif isinstance(self.keybindings, (long, float, int)): 1272 1273 # Class with single key numeric property 1274 1275 # This cannot happen; self.keybindings is always a NocaseDict: 1276 # TODO: Remove this if clause after verifying that it works. 1277 raise TypeError("Unexpected: keybindings has numeric type: %s" % \ 1278 repr(self.keybindings)) 1279 1280 instancename_xml = cim_xml.INSTANCENAME( 1281 self.classname, 1282 cim_xml.KEYVALUE(str(self.keybindings), 'numeric')) 1283 1284 elif isinstance(self.keybindings, NocaseDict): 1285 1286 kbs = [] 1287 1288 for kb in self.keybindings.items(): 1289 1290 # Keybindings can be integers, booleans, strings or 1291 # value references. 1292 1293 if hasattr(kb[1], 'tocimxml'): 1294 kbs.append(cim_xml.KEYBINDING( 1295 kb[0], 1296 cim_xml.VALUE_REFERENCE(kb[1].tocimxml()))) 1297 continue 1298 1299 if type(kb[1]) == bool: 1300 _type = 'boolean' 1301 if kb[1]: 1302 value = 'TRUE' 1303 else: 1304 value = 'FALSE' 1305 elif isinstance(kb[1], (long, float, int)): 1306 # pywbem.cim_type.{Sint32, Real64, ... } derive from 1307 # long or float 1308 _type = 'numeric' 1309 value = str(kb[1]) 1310 elif isinstance(kb[1], basestring): 1311 _type = 'string' 1312 value = kb[1].decode('utf-8') if isinstance(kb[1], str) \ 1313 else kb[1] 1314 else: 1315 raise TypeError('Invalid keybinding type for keybinding '\ 1316 '%s: %s' % (kb[0], type(kb[1]))) 1317 1318 kbs.append(cim_xml.KEYBINDING( 1319 kb[0], 1320 cim_xml.KEYVALUE(value, _type))) 1321 1322 instancename_xml = cim_xml.INSTANCENAME(self.classname, kbs) 1323 1324 else: 1325 1326 # Value reference 1327 1328 # This cannot happen; self.keybindings is always a NocaseDict: 1329 # TODO: Remove this if clause after verifying that it works. 1330 raise TypeError("Unexpected: keybindings has type: %s" % \ 1331 repr(self.keybindings)) 1332 1333 instancename_xml = cim_xml.INSTANCENAME( 1334 self.classname, 1335 cim_xml.VALUE_REFERENCE(self.keybindings.tocimxml())) 1336 1337 # Instance name plus namespace = LOCALINSTANCEPATH 1338 1339 if self.host is None and self.namespace is not None: 1340 return cim_xml.LOCALINSTANCEPATH( 1341 cim_xml.LOCALNAMESPACEPATH( 1342 [cim_xml.NAMESPACE(ns) 1343 for ns in string.split(self.namespace, '/')]), 1344 instancename_xml) 1345 1346 # Instance name plus host and namespace = INSTANCEPATH 1347 1348 if self.host is not None and self.namespace is not None: 1349 return cim_xml.INSTANCEPATH( 1350 cim_xml.NAMESPACEPATH( 1351 cim_xml.HOST(self.host), 1352 cim_xml.LOCALNAMESPACEPATH([ 1353 cim_xml.NAMESPACE(ns) 1354 for ns in string.split(self.namespace, '/')])), 1355 instancename_xml) 1356 1357 # Just a regular INSTANCENAME 1358 1359 return instancename_xml
1360
1361 -class CIMInstance(object):
1362 """ 1363 A CIM instance, optionally including its instance path. 1364 1365 This object can be used like a dictionary to retrieve the property values. 1366 1367 :Ivariables: 1368 1369 ... 1370 All parameters of `__init__` are set as instance variables. 1371 """ 1372
1373 - def __init__(self, classname, properties={}, qualifiers={}, 1374 path=None, property_list=None):
1375 """ 1376 Initialize the `CIMInstance` object. 1377 1378 :Parameters: 1379 1380 classname : `unicode` or UTF-8 encoded `str` 1381 Name of the creation class of the instance. 1382 1383 properties : `dict` or `NocaseDict` 1384 Optional: Dictionary of properties, specifying property values of 1385 the instance. 1386 The dictionary must contain one item for each property, where: 1387 1388 - its key is the property name. 1389 - its value is a `CIMProperty` object representing the property 1390 value. 1391 1392 qualifiers : `dict` or `NocaseDict` 1393 Optional: Dictionary of qualifier values of the instance. 1394 Note that CIM-XML has deprecated the presence of qualifier values 1395 on CIM instances. 1396 1397 path : `CIMInstanceName` 1398 Optional: Instance path of the instance. 1399 1400 If `None`, the instance is not addressable or the instance path is 1401 unknown or not needed. 1402 1403 Default: `None`. 1404 1405 property_list : list of strings 1406 Optional: List of property names for use by some operations on this 1407 object. 1408 1409 :Raises: 1410 :raise TypeError: 1411 :raise ValueError: 1412 """ 1413 1414 self.classname = classname 1415 self.qualifiers = NocaseDict(qualifiers) 1416 # TODO: Add support for accepting qualifiers as plain dict 1417 self.path = path 1418 if property_list is not None: 1419 self.property_list = [x.lower() for x in property_list] 1420 else: 1421 self.property_list = None 1422 1423 # Assign initialised property values and run through 1424 # __setitem__ to enforce CIM types for each property. 1425 1426 self.properties = NocaseDict() 1427 [self.__setitem__(k, v) for k, v in properties.items()]
1428
1429 - def update(self, *args, **kwargs):
1430 """D.update(E, **F) -> None. 1431 1432 Update D from E and F: for k in E: D[k] = E[k] 1433 (if E has keys else: for (k, v) in E: D[k] = v) 1434 then: for k in F: D[k] = F[k] """ 1435 1436 for mapping in args: 1437 if hasattr(mapping, 'items'): 1438 for k, v in mapping.items(): 1439 self[k] = v 1440 else: 1441 for (k, v) in mapping: 1442 self[k] = v 1443 for k, v in kwargs.items(): 1444 self[k] = v
1445
1446 - def update_existing(self, *args, **kwargs):
1447 """Update property values iff the property previously exists. 1448 1449 Update D from E and F: for k in E: D[k] = E[k] 1450 (if E has keys else: for (k, v) in E: D[k] = v) 1451 then: for k in F: D[k] = F[k] 1452 1453 Like update, but properties that are not already present in the 1454 instance are skipped. """ 1455 1456 for mapping in args: 1457 if hasattr(mapping, 'items'): 1458 for k, v in mapping.items(): 1459 try: 1460 prop = self.properties[k] 1461 except KeyError: 1462 continue 1463 prop.value = tocimobj(prop.type, v) 1464 else: 1465 for (k, v) in mapping: 1466 try: 1467 prop = self.properties[k] 1468 except KeyError: 1469 continue 1470 prop.value = tocimobj(prop.type, v) 1471 for k, v in kwargs.items(): 1472 try: 1473 prop = self.properties[k] 1474 except KeyError: 1475 continue 1476 prop.value = tocimobj(prop.type, v)
1477
1478 - def copy(self):
1479 1480 result = CIMInstance(self.classname) 1481 result.properties = self.properties.copy() 1482 result.qualifiers = self.qualifiers.copy() 1483 result.path = (self.path is not None and \ 1484 [self.path.copy()] or [None])[0] 1485 1486 return result
1487
1488 - def __cmp__(self, other):
1489 1490 if self is other: 1491 return 0 1492 elif not isinstance(other, CIMInstance): 1493 return 1 1494 1495 return (cmpname(self.classname, other.classname) or 1496 cmp(self.path, other.path) or 1497 cmp(self.properties, other.properties) or 1498 cmp(self.qualifiers, other.qualifiers))
1499
1500 - def __repr__(self):
1501 # Don't show all the properties and qualifiers because they're 1502 # just too big 1503 return '%s(classname=%r, path=%r, ...)' % \ 1504 (self.__class__.__name__, self.classname, self.path)
1505 1506 # A whole bunch of dictionary methods that map to the equivalent 1507 # operation on self.properties. 1508
1509 - def __contains__(self, key):
1510 return key in self.properties
1511
1512 - def __getitem__(self, key):
1513 return self.properties[key].value
1514
1515 - def __delitem__(self, key):
1516 del self.properties[key]
1517
1518 - def __len__(self):
1519 return len(self.properties)
1520
1521 - def has_key(self, key):
1522 return self.properties.has_key(key)
1523
1524 - def keys(self):
1525 return self.properties.keys()
1526
1527 - def values(self):
1528 return [v.value for v in self.properties.values()]
1529
1530 - def items(self):
1531 return [(k, v.value) for k, v in self.properties.items()]
1532
1533 - def iterkeys(self):
1534 return self.properties.iterkeys()
1535
1536 - def itervalues(self):
1537 for k, v in self.properties.iteritems(): 1538 yield v.value
1539
1540 - def iteritems(self):
1541 for k, v in self.properties.iteritems(): 1542 yield (k, v.value)
1543
1544 - def __setitem__(self, key, value):
1545 1546 # Don't let anyone set integer or float values. You must use 1547 # a subclass from the cim_type module. 1548 1549 if type(value) == int or type(value) == float or type(value) == long: 1550 raise TypeError('Type of numeric value must be a CIM type but is '\ 1551 '%s' % type(value)) 1552 1553 if self.property_list is not None and key.lower() not in \ 1554 self.property_list: 1555 if self.path is not None and key not in self.path.keybindings: 1556 return 1557 # Convert value to appropriate PyWBEM type 1558 1559 if isinstance(value, CIMProperty): 1560 v = value 1561 else: 1562 v = CIMProperty(key, value) 1563 1564 self.properties[key] = v 1565 if self.path is not None and key in self.path.keybindings: 1566 self.path[key] = v.value
1567
1568 - def get(self, key, default=None):
1569 """ 1570 Get the value of a specific property, or the specified default 1571 value if a property with that name does not exist. 1572 """ 1573 prop = self.properties.get(key, None) 1574 return default if prop is None else prop.value
1575
1576 - def tocimxml(self):
1577 1578 props = [] 1579 1580 for key, value in self.properties.items(): 1581 1582 # Value has already been converted into a CIM object 1583 # property type (e.g for creating null property values). 1584 1585 if isinstance(value, CIMProperty): 1586 props.append(value) 1587 continue 1588 1589 props.append(CIMProperty(key, value)) 1590 1591 instance_xml = cim_xml.INSTANCE( 1592 self.classname, 1593 properties=[p.tocimxml() for p in props], 1594 qualifiers=[q.tocimxml() for q in self.qualifiers.values()]) 1595 1596 if self.path is None: 1597 return instance_xml 1598 1599 return cim_xml.VALUE_NAMEDINSTANCE(self.path.tocimxml(), 1600 instance_xml)
1601
1602 - def tomof(self):
1603 1604 def _prop2mof(_type, value): 1605 if value is None: 1606 val = 'NULL' 1607 elif isinstance(value, list): 1608 val = '{' 1609 for i, x in enumerate(value): 1610 if i > 0: 1611 val += ', ' 1612 val += _prop2mof(_type, x) 1613 val += '}' 1614 elif _type == 'string': 1615 val = mofstr(value) 1616 else: 1617 val = str(value) 1618 return val
1619 1620 s = 'instance of %s {\n' % self.classname 1621 for p in self.properties.values(): 1622 s += '\t%s = %s;\n' % (p.name, _prop2mof(p.type, p.value)) 1623 s += '};\n' 1624 1625 return s
1626 1627
1628 -class CIMClass(object):
1629 """ 1630 A CIM class. 1631 1632 :Ivariables: 1633 1634 ... 1635 All parameters of `__init__` are set as instance variables. 1636 """ 1637
1638 - def __init__(self, classname, properties={}, methods={}, 1639 superclass=None, qualifiers={}):
1640 """ 1641 Initialize the `CIMClass` object. 1642 1643 TODO: add description 1644 """ 1645 self.classname = classname 1646 self.properties = NocaseDict(properties) 1647 self.qualifiers = NocaseDict(qualifiers) 1648 self.methods = NocaseDict(methods) 1649 self.superclass = superclass
1650
1651 - def copy(self):
1652 1653 result = CIMClass(self.classname) 1654 result.properties = self.properties.copy() 1655 result.methods = self.methods.copy() 1656 result.superclass = self.superclass 1657 result.qualifiers = self.qualifiers.copy() 1658 1659 return result
1660
1661 - def __repr__(self):
1662 return "%s(classname=%r, ...)" % (self.__class__.__name__, 1663 self.classname)
1664
1665 - def __cmp__(self, other):
1666 1667 if self is other: 1668 return 0 1669 elif not isinstance(other, CIMClass): 1670 return 1 1671 1672 return (cmpname(self.classname, other.classname) 1673 or cmpname(self.superclass, other.superclass) 1674 or cmp(self.properties, other.properties) 1675 or cmp(self.qualifiers, other.qualifiers) 1676 or cmp(self.methods, other.methods))
1677
1678 - def tocimxml(self):
1679 return cim_xml.CLASS( 1680 self.classname, 1681 properties=[p.tocimxml() for p in self.properties.values()], 1682 methods=[m.tocimxml() for m in self.methods.values()], 1683 qualifiers=[q.tocimxml() for q in self.qualifiers.values()], 1684 superclass=self.superclass)
1685
1686 - def tomof(self):
1687 1688 # Class definition 1689 1690 s = ' %s\n' % _makequalifiers(self.qualifiers, 4) 1691 1692 s += 'class %s ' % self.classname 1693 1694 # Superclass 1695 1696 if self.superclass is not None: 1697 s += ': %s ' % self.superclass 1698 1699 s += '{\n' 1700 1701 # Properties 1702 1703 for p in self.properties.values(): 1704 if p.is_array and p.array_size is not None: 1705 array_str = "[%s]" % p.array_size 1706 else: 1707 array_str = '' 1708 s += '\n' 1709 s += ' %s\n' % (_makequalifiers(p.qualifiers, 7)) 1710 s += ' %s %s%s;\n' % (moftype(p.type, p.reference_class), 1711 p.name, array_str) 1712 1713 # Methods 1714 1715 for m in self.methods.values(): 1716 s += '\n' 1717 s += ' %s\n' % m.tomof() 1718 1719 s += '};\n' 1720 1721 return s
1722
1723 -class CIMMethod(object):
1724 """ 1725 A CIM method. 1726 1727 :Ivariables: 1728 1729 ... 1730 All parameters of `__init__` are set as instance variables. 1731 """ 1732
1733 - def __init__(self, methodname, return_type=None, parameters={}, 1734 class_origin=None, propagated=False, qualifiers={}):
1735 """ 1736 Initialize the `CIMMethod` object. 1737 1738 TODO: add description 1739 """ 1740 self.name = methodname 1741 self.return_type = return_type 1742 self.parameters = NocaseDict(parameters) 1743 self.class_origin = class_origin 1744 self.propagated = propagated 1745 self.qualifiers = NocaseDict(qualifiers)
1746
1747 - def copy(self):
1748 1749 result = CIMMethod(self.name, 1750 return_type=self.return_type, 1751 class_origin=self.class_origin, 1752 propagated=self.propagated) 1753 1754 result.parameters = self.parameters.copy() 1755 result.qualifiers = self.qualifiers.copy() 1756 1757 return result
1758
1759 - def tocimxml(self):
1760 return cim_xml.METHOD( 1761 self.name, 1762 parameters=[p.tocimxml() for p in self.parameters.values()], 1763 return_type=self.return_type, 1764 class_origin=self.class_origin, 1765 propagated=self.propagated, 1766 qualifiers=[q.tocimxml() for q in self.qualifiers.values()])
1767
1768 - def __repr__(self):
1769 return '%s(name=%r, return_type=%r, ...)' % \ 1770 (self.__class__.__name__, self.name, self.return_type)
1771
1772 - def __cmp__(self, other):
1773 1774 if self is other: 1775 return 0 1776 elif not isinstance(other, CIMMethod): 1777 return 1 1778 1779 return (cmpname(self.name, other.name) or 1780 cmp(self.parameters, other.parameters) or 1781 cmp(self.qualifiers, other.qualifiers) or 1782 cmp(self.class_origin, other.class_origin) or 1783 cmp(self.propagated, other.propagated) or 1784 cmp(self.return_type, other.return_type))
1785
1786 - def tomof(self):
1787 1788 s = '' 1789 1790 s += ' %s\n' % (_makequalifiers(self.qualifiers, 7)) 1791 1792 if self.return_type is not None: 1793 s += '%s ' % moftype(self.return_type, None) 1794 # CIM-XML does not support methods returning reference types 1795 # (the CIM architecture does). 1796 1797 s += '%s(\n' % (self.name) 1798 s += string.join( 1799 [' '+p.tomof() for p in self.parameters.values()], ',\n') 1800 s += ');\n' 1801 1802 return s
1803
1804 -class CIMParameter(object):
1805 """ 1806 A CIM parameter. 1807 1808 :Ivariables: 1809 1810 ... 1811 All parameters of `__init__` are set as instance variables. 1812 """ 1813
1814 - def __init__(self, name, type, reference_class=None, is_array=None, 1815 array_size=None, qualifiers={}, value=None):
1816 """ 1817 Initialize the `CIMParameter` object. 1818 1819 TODO: add description 1820 """ 1821 self.name = name 1822 self.type = type 1823 self.reference_class = reference_class 1824 self.is_array = is_array 1825 self.array_size = array_size 1826 self.qualifiers = NocaseDict(qualifiers) 1827 self.value = value
1828
1829 - def copy(self):
1830 1831 result = CIMParameter(self.name, 1832 self.type, 1833 reference_class=self.reference_class, 1834 is_array=self.is_array, 1835 array_size=self.array_size, 1836 value=self.value) 1837 1838 result.qualifiers = self.qualifiers.copy() 1839 1840 return result
1841
1842 - def __repr__(self):
1843 1844 return '%s(name=%r, type=%r, reference_class=%r, is_array=%r, ...)' % \ 1845 (self.__class__.__name__, self.name, self.type, 1846 self.reference_class, self.is_array)
1847
1848 - def __cmp__(self, other):
1849 1850 if self is other: 1851 return 0 1852 elif not isinstance(other, self.__class__): 1853 return 1 1854 1855 return (cmpname(self.name, other.name) or 1856 cmp(self.type, other.type) or 1857 cmpname(self.reference_class, other.reference_class) or 1858 cmp(self.is_array, other.is_array) or 1859 cmp(self.array_size, other.array_size) or 1860 cmp(self.qualifiers, other.qualifiers) or 1861 cmp(self.value, other.value))
1862
1863 - def tocimxml(self):
1864 1865 if self.type == 'reference': 1866 1867 if self.is_array: 1868 1869 array_size = None 1870 1871 if self.array_size is not None: 1872 array_size = str(self.array_size) 1873 1874 return cim_xml.PARAMETER_REFARRAY( 1875 self.name, 1876 self.reference_class, 1877 array_size, 1878 qualifiers=[q.tocimxml() 1879 for q in self.qualifiers.values()]) 1880 1881 else: 1882 1883 return cim_xml.PARAMETER_REFERENCE( 1884 self.name, 1885 self.reference_class, 1886 qualifiers=[q.tocimxml() 1887 for q in self.qualifiers.values()]) 1888 1889 elif self.is_array: 1890 1891 array_size = None 1892 1893 if self.array_size is not None: 1894 array_size = str(self.array_size) 1895 1896 return cim_xml.PARAMETER_ARRAY( 1897 self.name, 1898 self.type, 1899 array_size, 1900 qualifiers=[q.tocimxml() for q in self.qualifiers.values()]) 1901 1902 else: 1903 1904 return cim_xml.PARAMETER( 1905 self.name, 1906 self.type, 1907 qualifiers=[q.tocimxml() for q in self.qualifiers.values()])
1908
1909 - def tomof(self):
1910 if self.is_array and self.array_size is not None: 1911 array_str = "[%s]" % self.array_size 1912 else: 1913 array_str = '' 1914 s = '\n' 1915 s += ' %s\n' % (_makequalifiers(self.qualifiers, 10)) 1916 s += ' %s %s%s' % (moftype(self.type, self.reference_class), 1917 self.name, array_str) 1918 return s
1919
1920 -class CIMQualifier(object):
1921 """ 1922 A CIM qualifier value. 1923 1924 A qualifier represents metadata on a class, method, property, etc., and 1925 specifies information such as a documentation string or whether a property 1926 is a key. 1927 1928 :Ivariables: 1929 1930 ... 1931 All parameters of `__init__` are set as instance variables. 1932 """ 1933
1934 - def __init__(self, name, value, type=None, propagated=None, 1935 overridable=None, tosubclass=None, toinstance=None, 1936 translatable=None):
1937 """ 1938 Initialize the `CIMQualifier` object. 1939 1940 TODO: add description 1941 """ 1942 self.name = name 1943 self.type = type 1944 self.propagated = propagated 1945 self.overridable = overridable 1946 self.tosubclass = tosubclass 1947 self.toinstance = toinstance 1948 self.translatable = translatable 1949 1950 # Determine type of value if not specified 1951 1952 import __builtin__ 1953 1954 if type is None: 1955 1956 # Can't work out what is going on if type and value are 1957 # both not set. 1958 1959 if value is None: 1960 raise TypeError('Null qualifier "%s" must have a type' % name) 1961 1962 if __builtin__.type(value) == list: 1963 1964 # Determine type for list value 1965 1966 if len(value) == 0: 1967 raise TypeError('Empty qualifier array "%s" must have a '\ 1968 'type' % name) 1969 1970 self.type = cim_types.cimtype(value[0]) 1971 1972 else: 1973 1974 # Determine type for regular value 1975 1976 self.type = cim_types.cimtype(value) 1977 1978 # Don't let anyone set integer or float values. You must use 1979 # a subclass from the cim_type module. 1980 1981 if __builtin__.type(value) in (int, float, long): 1982 raise TypeError('Must use a CIM type for numeric qualifiers.') 1983 1984 self.value = value
1985
1986 - def copy(self):
1987 1988 return CIMQualifier(self.name, 1989 self.value, 1990 type=self.type, 1991 propagated=self.propagated, 1992 overridable=self.overridable, 1993 tosubclass=self.tosubclass, 1994 toinstance=self.toinstance, 1995 translatable=self.translatable)
1996
1997 - def __repr__(self):
1998 return "%s(name=%r, value=%r, type=%r, ...)" % \ 1999 (self.__class__.__name__, self.name, self.value, self.type)
2000
2001 - def __cmp__(self, other):
2002 2003 if self is other: 2004 return 0 2005 elif not isinstance(other, CIMQualifier): 2006 return 1 2007 2008 return (cmpname(self.name, other.name) or 2009 cmp(self.value, other.value) or 2010 cmp(self.type, other.type) or 2011 cmp(self.propagated, other.propagated) or 2012 cmp(self.overridable, other.overridable) or 2013 cmp(self.tosubclass, other.tosubclass) or 2014 cmp(self.toinstance, other.toinstance) or 2015 cmp(self.translatable, other.translatable))
2016
2017 - def tocimxml(self):
2018 2019 value = None 2020 2021 if type(self.value) == list: 2022 value = cim_xml.VALUE_ARRAY([cim_xml.VALUE(v) for v in self.value]) 2023 elif self.value is not None: 2024 value = cim_xml.VALUE(self.value) 2025 2026 return cim_xml.QUALIFIER(self.name, 2027 self.type, 2028 value, 2029 propagated=self.propagated, 2030 overridable=self.overridable, 2031 tosubclass=self.tosubclass, 2032 toinstance=self.toinstance, 2033 translatable=self.translatable)
2034
2035 - def tomof(self, indent=7):
2036 2037 def valstr(v): 2038 if isinstance(v, basestring): 2039 return mofstr(v, indent) 2040 return str(v)
2041 2042 if type(self.value) == list: 2043 return '%s {' % self.name + \ 2044 ', '.join([valstr(v) for v in self.value]) + '}' 2045 2046 return '%s (%s)' % (self.name, valstr(self.value))
2047
2048 -class CIMQualifierDeclaration(object):
2049 """ 2050 A CIM qualifier type. 2051 2052 A qualifier type is the declaration of a qualifier. 2053 2054 :Ivariables: 2055 2056 ... 2057 All parameters of `__init__` are set as instance variables. 2058 """ 2059 2060 # TODO: Scope and qualifier flavors 2061
2062 - def __init__(self, name, type, value=None, is_array=False, 2063 array_size=None, scopes={}, 2064 overridable=None, tosubclass=None, toinstance=None, 2065 translatable=None):
2066 """ 2067 Initialize the `CIMQualifierDeclaration` object. 2068 2069 TODO: add description 2070 """ 2071 self.name = name 2072 self.type = type 2073 self.value = value 2074 self.is_array = is_array 2075 self.array_size = array_size 2076 self.scopes = NocaseDict(scopes) 2077 self.overridable = overridable 2078 self.tosubclass = tosubclass 2079 self.toinstance = toinstance 2080 self.translatable = translatable
2081
2082 - def copy(self):
2083 2084 return CIMQualifierDeclaration(self.name, 2085 self.type, 2086 value=self.value, 2087 is_array=self.is_array, 2088 array_size=self.array_size, 2089 scopes=self.scopes, 2090 overridable=self.overridable, 2091 tosubclass=self.tosubclass, 2092 toinstance=self.toinstance, 2093 translatable=self.translatable)
2094
2095 - def __repr__(self):
2096 return "%s(name=%r, type=%r, is_array=%r, ...)" % \ 2097 (self.__class__.__name__, self.name, self.type, self.is_array)
2098
2099 - def __cmp__(self, other):
2100 2101 if self is other: 2102 return 0 2103 elif not isinstance(other, CIMQualifierDeclaration): 2104 return 1 2105 2106 return (cmpname(self.name, other.name) or 2107 cmp(self.type, other.type) or 2108 cmp(self.value, other.value) or 2109 cmp(self.is_array, other.is_array) or 2110 cmp(self.array_size, other.array_size) or 2111 cmp(self.scopes, other.scopes) or 2112 cmp(self.overridable, other.overridable) or 2113 cmp(self.tosubclass, other.tosubclass) or 2114 cmp(self.toinstance, other.toinstance) or 2115 cmp(self.translatable, other.translatable))
2116
2117 - def tocimxml(self):
2118 2119 return cim_xml.QUALIFIER_DECLARATION(self.name, 2120 self.type, 2121 self.value, 2122 is_array=self.is_array, 2123 array_size=self.array_size, 2124 qualifier_scopes=self.scopes, 2125 overridable=self.overridable, 2126 tosubclass=self.tosubclass, 2127 toinstance=self.toinstance, 2128 translatable=self.translatable)
2129
2130 - def tomof(self):
2131 mof = 'Qualifier %s : %s' % (self.name, self.type) 2132 if self.is_array: 2133 mof += '[' 2134 if self.array_size is not None: 2135 mof += str(self.array_size) 2136 mof += ']' 2137 if self.value is not None: 2138 if isinstance(self.value, list): 2139 mof += ' = {' 2140 mof += ', '.join([cim_types.atomic_to_cim_xml( 2141 tocimobj(self.type, x)) for x in self.value]) 2142 mof += '}' 2143 else: 2144 mof += ' = %s' % cim_types.atomic_to_cim_xml( 2145 tocimobj(self.type, self.value)) 2146 mof += ',\n ' 2147 mof += 'Scope(' 2148 mof += ', '.join([x.lower() for x, y in self.scopes.items() if y]) + ')' 2149 if not self.overridable and not self.tosubclass \ 2150 and not self.toinstance and not self.translatable: 2151 mof += ';' 2152 return mof 2153 mof += ',\n Flavor(' 2154 mof += self.overridable and 'EnableOverride' or 'DisableOverride' 2155 mof += ', ' 2156 mof += self.tosubclass and 'ToSubclass' or 'Restricted' 2157 if self.toinstance: 2158 mof += ', ToInstance' 2159 if self.translatable: 2160 mof += ', Translatable' 2161 mof += ');' 2162 return mof
2163
2164 -def tocimxml(value):
2165 """Convert an arbitrary object to CIM xml. Works with cim_obj 2166 objects and builtin types.""" 2167 2168 # Python cim_obj object 2169 2170 if hasattr(value, 'tocimxml'): 2171 return value.tocimxml() 2172 2173 # CIMType or builtin type 2174 2175 if isinstance(value, (cim_types.CIMType, unicode, int)): 2176 return cim_xml.VALUE(unicode(value)) 2177 2178 if isinstance(value, str): 2179 return cim_xml.VALUE(value.decode('utf-8')) 2180 2181 if isinstance(value, bool): 2182 if value: 2183 return cim_xml.VALUE('TRUE') 2184 else: 2185 return cim_xml.VALUE('FALSE') 2186 2187 # List of values 2188 2189 if type(value) == list: 2190 return cim_xml.VALUE_ARRAY(map(tocimxml, value)) 2191 2192 raise ValueError("Can't convert %s (%s) to CIM XML" % (value, type(value)))
2193 2194
2195 -def tocimobj(_type, value):
2196 """Convert a CIM type and a string value into an appropriate 2197 builtin type.""" 2198 2199 if value is None or _type is None: 2200 return None 2201 2202 if _type != 'string' and isinstance(value, basestring) and not value: 2203 return None 2204 2205 # Lists of values 2206 2207 if type(value) == list: 2208 return map(lambda x: tocimobj(_type, x), value) 2209 2210 # Boolean type 2211 2212 if _type == 'boolean': 2213 if isinstance(value, bool): 2214 return value 2215 elif isinstance(value, basestring): 2216 if value.lower() == 'true': 2217 return True 2218 elif value.lower() == 'false': 2219 return False 2220 raise ValueError('Invalid boolean value: "%s"' % value) 2221 2222 # String type 2223 2224 if _type == 'string': 2225 return value 2226 2227 # Integer types 2228 2229 if _type == 'uint8': 2230 return cim_types.Uint8(value) 2231 2232 if _type == 'sint8': 2233 return cim_types.Sint8(value) 2234 2235 if _type == 'uint16': 2236 return cim_types.Uint16(value) 2237 2238 if _type == 'sint16': 2239 return cim_types.Sint16(value) 2240 2241 if _type == 'uint32': 2242 return cim_types.Uint32(value) 2243 2244 if _type == 'sint32': 2245 return cim_types.Sint32(value) 2246 2247 if _type == 'uint64': 2248 return cim_types.Uint64(value) 2249 2250 if _type == 'sint64': 2251 return cim_types.Sint64(value) 2252 2253 # Real types 2254 2255 if _type == 'real32': 2256 return cim_types.Real32(value) 2257 2258 if _type == 'real64': 2259 return cim_types.Real64(value) 2260 2261 # Char16 2262 2263 if _type == 'char16': 2264 raise ValueError('CIMType char16 not handled') 2265 2266 # Datetime 2267 2268 if _type == 'datetime': 2269 return cim_types.CIMDateTime(value) 2270 2271 # REF 2272 def partition(s, seq): 2273 """ S.partition(sep) -> (head, sep, tail) 2274 2275 Searches for the separator sep in S, and returns the part before it, 2276 the separator itself, and the part after it. If the separator is not 2277 found, returns S and two empty strings. 2278 """ 2279 try: 2280 return s.partition(seq) 2281 except AttributeError: 2282 try: 2283 idx = s.index(seq) 2284 except ValueError: 2285 return (s, '', '') 2286 return (s[:idx], seq, s[idx+len(seq):])
2287 2288 if _type == 'reference': 2289 # TODO doesn't handle double-quoting, as in refs to refs. Example: 2290 # r'ex_composedof.composer="ex_sampleClass.label1=9921,' + 2291 # 'label2=\"SampleLabel\"",component="ex_sampleClass.label1=0121,' + 2292 # 'label2=\"Component\""') 2293 if isinstance(value, (CIMInstanceName, CIMClassName)): 2294 return value 2295 elif isinstance(value, basestring): 2296 ns = host = None 2297 head, sep, tail = partition(value, '//') 2298 if sep and head.find('"') == -1: 2299 # we have a namespace type 2300 head, sep, tail = partition(tail, '/') 2301 host = head 2302 else: 2303 tail = head 2304 head, sep, tail = partition(tail, ':') 2305 if sep: 2306 ns = head 2307 else: 2308 tail = head 2309 head, sep, tail = partition(tail, '.') 2310 if not sep: 2311 return CIMClassName(head, host=host, namespace=ns) 2312 classname = head 2313 kb = {} 2314 while tail: 2315 head, sep, tail = partition(tail, ',') 2316 if head.count('"') == 1: # quoted string contains comma 2317 tmp, sep, tail = partition(tail, '"') 2318 head = '%s,%s' % (head, tmp) 2319 tail = partition(tail, ',')[2] 2320 head = head.strip() 2321 key, sep, val = partition(head, '=') 2322 if sep: 2323 cn, s, k = partition(key, '.') 2324 if s: 2325 if cn != classname: 2326 raise ValueError('Invalid object path: "%s"' % \ 2327 value) 2328 key = k 2329 val = val.strip() 2330 if val[0] == '"' and val[-1] == '"': 2331 val = val.strip('"') 2332 else: 2333 if val.lower() in ('true', 'false'): 2334 val = val.lower() == 'true' 2335 elif val.isdigit(): 2336 val = int(val) 2337 else: 2338 try: 2339 val = float(val) 2340 except ValueError: 2341 try: 2342 val = cim_types.CIMDateTime(val) 2343 except ValueError: 2344 raise ValueError('Invalid key binding: %s'\ 2345 % val) 2346 2347 2348 kb[key] = val 2349 return CIMInstanceName(classname, host=host, namespace=ns, 2350 keybindings=kb) 2351 else: 2352 raise ValueError('Invalid reference value: "%s"' % value) 2353 2354 raise ValueError('Invalid CIM type: "%s"' % _type) 2355 2356
2357 -def byname(nlist):
2358 """Convert a list of named objects into a map indexed by name""" 2359 return dict([(x.name, x) for x in nlist])
2360