1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
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
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
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
106 if len(args) == 1:
107 if isinstance(args[0], list):
108
109 for item in args[0]:
110 self[item[0]] = item[1]
111 elif isinstance(args[0], dict):
112
113 self.update(args[0])
114 elif isinstance(args[0], NocaseDict):
115
116 self._data = args[0]._data.copy()
117 elif args[0] is None:
118
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
128 self.update(kwargs)
129
130
131
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
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
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
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
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
199
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
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
236
238 """
239 Return a copied list of the dictionary keys, in their original case.
240 """
241 return list(self.iterkeys())
242
244 """
245 Return a copied list of the dictionary values.
246 """
247 return list(self.itervalues())
248
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
257
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
267 """
268 Return an iterator through the dictionary values.
269 """
270 for item in self._data.iteritems():
271 yield item[1][1]
272
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
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
290
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
329 """
330 Remove all items from the dictionary.
331 """
332 self._data.clear()
333
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
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()
352 return result
353
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
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
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]
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
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
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
477 escaped_str = strvalue.replace("\n","\\n").replace("\r","\\r").\
478 replace("\t","\\t").replace("\f","\\f").replace("\b","\\b")
479
480
481
482 escaped_str = re.sub(r'([^\\])"', r'\1\\"', escaped_str)
483
484
485 escaped_str = re.sub(r'^"$', r'\"', escaped_str)
486
487
488 escaped_str = re.sub(r'\\([^nrtfb"\'])', r'\\\1', escaped_str)
489
490
491 escaped_str = re.sub(r'^\\$', r'\\\\', escaped_str)
492
493
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
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
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
572
573
574
575 self.classname = classname
576 self.host = host
577 self.namespace = namespace
578
580 return CIMClassName(self.classname, host=self.host,
581 namespace=self.namespace)
582
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
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
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
647
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
801
802 if name is None:
803 raise ValueError('Property must have a name')
804
805
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
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:
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:
828 if is_array is None:
829 is_array = False
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
836
837
838 if is_array:
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
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
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
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:
896
897
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:
905 if value is None:
906
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
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
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:
983
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
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
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
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
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
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
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
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
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
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
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
1231
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)
1239 - def keys(self): return self.keybindings.keys()
1241 - def items(self): return self.keybindings.items()
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
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
1261
1262
1263
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
1274
1275
1276
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
1291
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
1307
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
1327
1328
1329
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
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
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
1358
1359 return instancename_xml
1360
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
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
1424
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
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
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
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
1501
1502
1503 return '%s(classname=%r, path=%r, ...)' % \
1504 (self.__class__.__name__, self.classname, self.path)
1505
1506
1507
1508
1510 return key in self.properties
1511
1513 return self.properties[key].value
1514
1516 del self.properties[key]
1517
1519 return len(self.properties)
1520
1522 return self.properties.has_key(key)
1523
1525 return self.properties.keys()
1526
1528 return [v.value for v in self.properties.values()]
1529
1531 return [(k, v.value) for k, v in self.properties.items()]
1532
1535
1537 for k, v in self.properties.iteritems():
1538 yield v.value
1539
1541 for k, v in self.properties.iteritems():
1542 yield (k, v.value)
1543
1545
1546
1547
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
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
1577
1578 props = []
1579
1580 for key, value in self.properties.items():
1581
1582
1583
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
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
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
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
1662 return "%s(classname=%r, ...)" % (self.__class__.__name__,
1663 self.classname)
1664
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
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
1687
1688
1689
1690 s = ' %s\n' % _makequalifiers(self.qualifiers, 4)
1691
1692 s += 'class %s ' % self.classname
1693
1694
1695
1696 if self.superclass is not None:
1697 s += ': %s ' % self.superclass
1698
1699 s += '{\n'
1700
1701
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
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
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
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
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
1769 return '%s(name=%r, return_type=%r, ...)' % \
1770 (self.__class__.__name__, self.name, self.return_type)
1771
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
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
1795
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
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
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
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
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
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
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
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
1951
1952 import __builtin__
1953
1954 if type is None:
1955
1956
1957
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
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
1975
1976 self.type = cim_types.cimtype(value)
1977
1978
1979
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
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
1998 return "%s(name=%r, value=%r, type=%r, ...)" % \
1999 (self.__class__.__name__, self.name, self.value, self.type)
2000
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
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
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
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
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
2096 return "%s(name=%r, type=%r, is_array=%r, ...)" % \
2097 (self.__class__.__name__, self.name, self.type, self.is_array)
2098
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
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
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
2165 """Convert an arbitrary object to CIM xml. Works with cim_obj
2166 objects and builtin types."""
2167
2168
2169
2170 if hasattr(value, 'tocimxml'):
2171 return value.tocimxml()
2172
2173
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
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
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
2206
2207 if type(value) == list:
2208 return map(lambda x: tocimobj(_type, x), value)
2209
2210
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
2223
2224 if _type == 'string':
2225 return value
2226
2227
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
2254
2255 if _type == 'real32':
2256 return cim_types.Real32(value)
2257
2258 if _type == 'real64':
2259 return cim_types.Real64(value)
2260
2261
2262
2263 if _type == 'char16':
2264 raise ValueError('CIMType char16 not handled')
2265
2266
2267
2268 if _type == 'datetime':
2269 return cim_types.CIMDateTime(value)
2270
2271
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
2290
2291
2292
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
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:
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
2358 """Convert a list of named objects into a map indexed by name"""
2359 return dict([(x.name, x) for x in nlist])
2360