111 if " (ID:" not in attribute: |
114 if " (ID:" not in attribute: |
112 try: |
115 try: |
113 return var[attribute] |
116 return var[attribute] |
114 except Exception: |
117 except Exception: |
115 return getattr(var, attribute, None) |
118 return getattr(var, attribute, None) |
116 |
119 |
117 expectedID = int(attribute.split(" (ID:")[-1][:-1]) |
120 expectedID = int(attribute.split(" (ID:")[-1][:-1]) |
118 for key, value in var.items(): |
121 for key, value in var.items(): |
119 if id(key) == expectedID: |
122 if id(key) == expectedID: |
120 return value |
123 return value |
121 |
124 |
122 return None |
125 return None |
123 |
126 |
124 def keyToStr(self, key): |
127 def keyToStr(self, key): |
125 """ |
128 """ |
126 Public method to get a string representation for a key. |
129 Public method to get a string representation for a key. |
127 |
130 |
128 @param key key to be converted |
131 @param key key to be converted |
129 @type any |
132 @type any |
130 @return string representation of the given key |
133 @return string representation of the given key |
131 @rtype str |
134 @rtype str |
132 """ |
135 """ |
133 if isinstance(key, str): |
136 if isinstance(key, str): |
134 key = repr(key) |
137 key = repr(key) |
135 # Special handling for bytes object |
138 # Special handling for bytes object |
136 # Raw and f-Strings are always converted to str |
139 # Raw and f-Strings are always converted to str |
137 if key[0] == 'b': |
140 if key[0] == "b": |
138 key = key[1:] |
141 key = key[1:] |
139 |
142 |
140 return key # __IGNORE_WARNING_M834__ |
143 return key # __IGNORE_WARNING_M834__ |
141 |
144 |
142 def getVariableList(self, var): |
145 def getVariableList(self, var): |
143 """ |
146 """ |
144 Public method to get the attributes of a variable as a list. |
147 Public method to get the attributes of a variable as a list. |
145 |
148 |
146 @param var variable to be converted |
149 @param var variable to be converted |
147 @type any |
150 @type any |
148 @yield tuple containing the batch start index and a list |
151 @yield tuple containing the batch start index and a list |
149 containing the variable attributes |
152 containing the variable attributes |
150 @ytype tuple of (int, list) |
153 @ytype tuple of (int, list) |
223 if count >= BatchSize: |
227 if count >= BatchSize: |
224 yield start, d |
228 yield start, d |
225 start = idx + 1 |
229 start = idx + 1 |
226 count = 0 |
230 count = 0 |
227 d = [] |
231 d = [] |
228 |
232 |
229 if d: |
233 if d: |
230 yield start, d |
234 yield start, d |
231 |
235 |
232 # in case it has additional fields |
236 # in case it has additional fields |
233 d = super().getVariableList(var) |
237 d = super().getVariableList(var) |
234 yield -1, d |
238 yield -1, d |
235 |
239 |
236 while True: |
240 while True: |
237 yield -2, [] |
241 yield -2, [] |
238 |
242 |
239 |
243 |
240 ############################################################ |
244 ############################################################ |
241 ## Resolver for dict_items, dict_keys and dict_values |
245 ## Resolver for dict_items, dict_keys and dict_values |
242 ############################################################ |
246 ############################################################ |
243 |
247 |
244 |
248 |
245 class DictViewResolver(ListResolver): |
249 class DictViewResolver(ListResolver): |
246 """ |
250 """ |
247 Class used to resolve from dict views. |
251 Class used to resolve from dict views. |
248 """ |
252 """ |
|
253 |
249 def resolve(self, var, attribute): |
254 def resolve(self, var, attribute): |
250 """ |
255 """ |
251 Public method to get an attribute from a variable. |
256 Public method to get an attribute from a variable. |
252 |
257 |
253 @param var variable to extract an attribute or value from |
258 @param var variable to extract an attribute or value from |
254 @type dict_items, dict_keys or dict_values |
259 @type dict_items, dict_keys or dict_values |
255 @param attribute id of the value to extract |
260 @param attribute id of the value to extract |
256 @type str |
261 @type str |
257 @return value of the attribute |
262 @return value of the attribute |
258 @rtype any |
263 @rtype any |
259 """ |
264 """ |
260 return super().resolve(list(var), attribute) |
265 return super().resolve(list(var), attribute) |
261 |
266 |
262 def getVariableList(self, var): |
267 def getVariableList(self, var): |
263 """ |
268 """ |
264 Public method to get the attributes of a variable as a list. |
269 Public method to get the attributes of a variable as a list. |
265 |
270 |
266 @param var variable to be converted |
271 @param var variable to be converted |
267 @type any |
272 @type any |
268 @yield tuple containing the batch start index and a list |
273 @yield tuple containing the batch start index and a list |
269 containing the variable attributes |
274 containing the variable attributes |
270 @ytype tuple of (int, list) |
275 @ytype tuple of (int, list) |
323 if count >= BatchSize: |
329 if count >= BatchSize: |
324 yield start, d |
330 yield start, d |
325 start += count |
331 start += count |
326 count = 0 |
332 count = 0 |
327 d = [] |
333 d = [] |
328 |
334 |
329 if d: |
335 if d: |
330 yield start, d |
336 yield start, d |
331 |
337 |
332 # in case it has additional fields |
338 # in case it has additional fields |
333 d = super().getVariableList(var) |
339 d = super().getVariableList(var) |
334 yield -1, d |
340 yield -1, d |
335 |
341 |
336 while True: |
342 while True: |
337 yield -2, [] |
343 yield -2, [] |
338 |
344 |
339 |
345 |
340 ############################################################ |
346 ############################################################ |
341 ## Resolver for Numpy Arrays |
347 ## Resolver for Numpy Arrays |
342 ############################################################ |
348 ############################################################ |
343 |
349 |
344 |
350 |
345 class NdArrayResolver(BaseResolver): |
351 class NdArrayResolver(BaseResolver): |
346 """ |
352 """ |
347 Class used to resolve from numpy ndarray including some meta data. |
353 Class used to resolve from numpy ndarray including some meta data. |
348 """ |
354 """ |
|
355 |
349 def __isNumeric(self, arr): |
356 def __isNumeric(self, arr): |
350 """ |
357 """ |
351 Private method to check, if an array is of a numeric type. |
358 Private method to check, if an array is of a numeric type. |
352 |
359 |
353 @param arr array to check |
360 @param arr array to check |
354 @type ndarray |
361 @type ndarray |
355 @return flag indicating a numeric array |
362 @return flag indicating a numeric array |
356 @rtype bool |
363 @rtype bool |
357 """ |
364 """ |
358 try: |
365 try: |
359 return arr.dtype.kind in 'biufc' |
366 return arr.dtype.kind in "biufc" |
360 except AttributeError: |
367 except AttributeError: |
361 return False |
368 return False |
362 |
369 |
363 def resolve(self, var, attribute): |
370 def resolve(self, var, attribute): |
364 """ |
371 """ |
365 Public method to get an attribute from a variable. |
372 Public method to get an attribute from a variable. |
366 |
373 |
367 @param var variable to extract an attribute or value from |
374 @param var variable to extract an attribute or value from |
368 @type ndarray |
375 @type ndarray |
369 @param attribute id of the value to extract |
376 @param attribute id of the value to extract |
370 @type str |
377 @type str |
371 @return value of the attribute |
378 @return value of the attribute |
372 @rtype any |
379 @rtype any |
373 """ |
380 """ |
374 if attribute == 'min': |
381 if attribute == "min": |
375 if self.__isNumeric(var): |
382 if self.__isNumeric(var): |
376 return var.min() |
383 return var.min() |
377 else: |
384 else: |
378 return None |
385 return None |
379 |
386 |
380 if attribute == 'max': |
387 if attribute == "max": |
381 if self.__isNumeric(var): |
388 if self.__isNumeric(var): |
382 return var.max() |
389 return var.max() |
383 else: |
390 else: |
384 return None |
391 return None |
385 |
392 |
386 if attribute == 'mean': |
393 if attribute == "mean": |
387 if self.__isNumeric(var): |
394 if self.__isNumeric(var): |
388 return var.mean() |
395 return var.mean() |
389 else: |
396 else: |
390 return None |
397 return None |
391 |
398 |
392 try: |
399 try: |
393 return var[int(attribute)] |
400 return var[int(attribute)] |
394 except Exception: |
401 except Exception: |
395 return getattr(var, attribute, None) |
402 return getattr(var, attribute, None) |
396 |
403 |
397 return None |
404 return None |
398 |
405 |
399 def getVariableList(self, var): |
406 def getVariableList(self, var): |
400 """ |
407 """ |
401 Public method to get the attributes of a variable as a list. |
408 Public method to get the attributes of a variable as a list. |
402 |
409 |
403 @param var variable to be converted |
410 @param var variable to be converted |
404 @type any |
411 @type any |
405 @yield tuple containing the batch start index and a list |
412 @yield tuple containing the batch start index and a list |
406 containing the variable attributes |
413 containing the variable attributes |
407 @ytype tuple of (int, list) |
414 @ytype tuple of (int, list) |
411 try: |
418 try: |
412 len(var) # Check if it's an unsized object, e.g. np.ndarray(()) |
419 len(var) # Check if it's an unsized object, e.g. np.ndarray(()) |
413 allItems = var.tolist() |
420 allItems = var.tolist() |
414 except TypeError: # TypeError: len() of unsized object |
421 except TypeError: # TypeError: len() of unsized object |
415 allItems = [] |
422 allItems = [] |
416 |
423 |
417 for idx, value in enumerate(allItems): |
424 for idx, value in enumerate(allItems): |
418 d.append((str(idx), value)) |
425 d.append((str(idx), value)) |
419 count += 1 |
426 count += 1 |
420 if count >= BatchSize: |
427 if count >= BatchSize: |
421 yield start, d |
428 yield start, d |
422 start += count |
429 start += count |
423 count = 0 |
430 count = 0 |
424 d = [] |
431 d = [] |
425 |
432 |
426 if d: |
433 if d: |
427 yield start, d |
434 yield start, d |
428 |
435 |
429 # in case it has additional fields |
436 # in case it has additional fields |
430 d = super().getVariableList(var) |
437 d = super().getVariableList(var) |
431 |
438 |
432 if var.size > 1024 * 1024: |
439 if var.size > 1024 * 1024: |
433 d.append( |
440 d.append( |
434 ('min', |
441 ("min", "ndarray too big, calculating min would slow down debugging") |
435 'ndarray too big, calculating min would slow down debugging') |
|
436 ) |
442 ) |
437 d.append( |
443 d.append( |
438 ('max', |
444 ("max", "ndarray too big, calculating max would slow down debugging") |
439 'ndarray too big, calculating max would slow down debugging') |
|
440 ) |
445 ) |
441 d.append( |
446 d.append( |
442 ('mean', |
447 ("mean", "ndarray too big, calculating mean would slow down debugging") |
443 'ndarray too big, calculating mean would slow down debugging') |
|
444 ) |
448 ) |
445 elif self.__isNumeric(var): |
449 elif self.__isNumeric(var): |
446 if var.size == 0: |
450 if var.size == 0: |
447 d.append(('min', 'empty array')) |
451 d.append(("min", "empty array")) |
448 d.append(('max', 'empty array')) |
452 d.append(("max", "empty array")) |
449 d.append(('mean', 'empty array')) |
453 d.append(("mean", "empty array")) |
450 else: |
454 else: |
451 d.append(('min', var.min())) |
455 d.append(("min", var.min())) |
452 d.append(('max', var.max())) |
456 d.append(("max", var.max())) |
453 d.append(('mean', var.mean())) |
457 d.append(("mean", var.mean())) |
454 else: |
458 else: |
455 d.append(('min', 'not a numeric object')) |
459 d.append(("min", "not a numeric object")) |
456 d.append(('max', 'not a numeric object')) |
460 d.append(("max", "not a numeric object")) |
457 d.append(('mean', 'not a numeric object')) |
461 d.append(("mean", "not a numeric object")) |
458 |
462 |
459 yield -1, d |
463 yield -1, d |
460 |
464 |
461 while True: |
465 while True: |
462 yield -2, [] |
466 yield -2, [] |
463 |
467 |
464 |
468 |
465 ############################################################ |
469 ############################################################ |
656 attributes = () |
663 attributes = () |
657 # Gently handle exception which could occure as special |
664 # Gently handle exception which could occure as special |
658 # cases, e.g. already deleted C++ objects, str conversion.. |
665 # cases, e.g. already deleted C++ objects, str conversion.. |
659 with contextlib.suppress(Exception): |
666 with contextlib.suppress(Exception): |
660 qttype = type(var).__name__ |
667 qttype = type(var).__name__ |
661 |
668 |
662 if qttype in ('QLabel', 'QPushButton'): |
669 if qttype in ("QLabel", "QPushButton"): |
663 attributes = ('text', ) |
670 attributes = ("text",) |
664 elif qttype == 'QByteArray': |
671 elif qttype == "QByteArray": |
665 d.append(('bytes', bytes(var))) |
672 d.append(("bytes", bytes(var))) |
666 d.append(('hex', "QByteArray", "{0}".format(var.toHex()))) |
673 d.append(("hex", "QByteArray", "{0}".format(var.toHex()))) |
|
674 d.append(("base64", "QByteArray", "{0}".format(var.toBase64()))) |
667 d.append( |
675 d.append( |
668 ('base64', "QByteArray", |
676 ( |
669 "{0}".format(var.toBase64())) |
677 "percent encoding", |
|
678 "QByteArray", |
|
679 "{0}".format(var.toPercentEncoding()), |
|
680 ) |
670 ) |
681 ) |
671 d.append( |
682 elif qttype in ("QPoint", "QPointF"): |
672 ('percent encoding', "QByteArray", |
683 attributes = ("x", "y") |
673 "{0}".format(var.toPercentEncoding())) |
684 elif qttype in ("QRect", "QRectF"): |
674 ) |
685 attributes = ("x", "y", "width", "height") |
675 elif qttype in ('QPoint', 'QPointF'): |
686 elif qttype in ("QSize", "QSizeF"): |
676 attributes = ('x', 'y') |
687 attributes = ("width", "height") |
677 elif qttype in ('QRect', 'QRectF'): |
688 elif qttype == "QColor": |
678 attributes = ('x', 'y', 'width', 'height') |
689 attributes = ("name",) |
679 elif qttype in ('QSize', 'QSizeF'): |
|
680 attributes = ('width', 'height') |
|
681 elif qttype == 'QColor': |
|
682 attributes = ('name', ) |
|
683 r, g, b, a = var.getRgb() |
690 r, g, b, a = var.getRgb() |
684 d.append( |
691 d.append(("rgba", "{0:d}, {1:d}, {2:d}, {3:d}".format(r, g, b, a))) |
685 ('rgba', "{0:d}, {1:d}, {2:d}, {3:d}".format(r, g, b, a)) |
|
686 ) |
|
687 h, s, v, a = var.getHsv() |
692 h, s, v, a = var.getHsv() |
688 d.append( |
693 d.append(("hsva", "{0:d}, {1:d}, {2:d}, {3:d}".format(h, s, v, a))) |
689 ('hsva', "{0:d}, {1:d}, {2:d}, {3:d}".format(h, s, v, a)) |
|
690 ) |
|
691 c, m, y, k, a = var.getCmyk() |
694 c, m, y, k, a = var.getCmyk() |
692 d.append( |
695 d.append( |
693 ('cmyka', |
696 ("cmyka", "{0:d}, {1:d}, {2:d}, {3:d}, {4:d}".format(c, m, y, k, a)) |
694 "{0:d}, {1:d}, {2:d}, {3:d}, {4:d}".format(c, m, y, k, a)) |
|
695 ) |
697 ) |
696 elif qttype in ('QDate', 'QTime', 'QDateTime'): |
698 elif qttype in ("QDate", "QTime", "QDateTime"): |
697 d.append((qttype[1:].lower(), var.toString())) |
699 d.append((qttype[1:].lower(), var.toString())) |
698 elif qttype == 'QDir': |
700 elif qttype == "QDir": |
699 attributes = ('path', 'absolutePath', 'canonicalPath') |
701 attributes = ("path", "absolutePath", "canonicalPath") |
700 elif qttype == 'QFile': |
702 elif qttype == "QFile": |
701 attributes = ('fileName', ) |
703 attributes = ("fileName",) |
702 elif qttype == 'QFont': |
704 elif qttype == "QFont": |
703 attributes = ( |
705 attributes = ("family", "pointSize", "weight", "bold", "italic") |
704 'family', 'pointSize', 'weight', 'bold', 'italic' |
706 elif qttype == "QUrl": |
705 ) |
707 d.append(("url", var.toString())) |
706 elif qttype == 'QUrl': |
708 attributes = ("scheme", "userName", "password", "host", "port", "path") |
707 d.append(('url', var.toString())) |
709 elif qttype == "QModelIndex": |
708 attributes = ('scheme', 'userName', 'password', 'host', 'port', |
|
709 'path') |
|
710 elif qttype == 'QModelIndex': |
|
711 valid = var.isValid() |
710 valid = var.isValid() |
712 d.append(('valid', valid)) |
711 d.append(("valid", valid)) |
713 if valid: |
712 if valid: |
714 d.append(("internalPointer", var.internalPointer())) |
713 d.append(("internalPointer", var.internalPointer())) |
715 attributes = ('row', 'column', 'internalId') |
714 attributes = ("row", "column", "internalId") |
716 elif qttype in ('QRegExp', "QRegularExpression"): |
715 elif qttype in ("QRegExp", "QRegularExpression"): |
717 attributes = ('pattern', ) |
716 attributes = ("pattern",) |
718 |
717 |
719 # GUI stuff |
718 # GUI stuff |
720 elif qttype == 'QAction': |
719 elif qttype == "QAction": |
721 d.append(('shortcut', var.shortcut().toString())) |
720 d.append(("shortcut", var.shortcut().toString())) |
722 attributes = ('objectName', 'text', 'iconText', 'toolTip', |
721 attributes = ("objectName", "text", "iconText", "toolTip", "whatsThis") |
723 'whatsThis') |
722 |
724 |
723 elif qttype == "QKeySequence": |
725 elif qttype == 'QKeySequence': |
724 d.append(("keySequence", var.toString())) |
726 d.append(('keySequence', var.toString())) |
725 |
727 |
|
728 # XML stuff |
726 # XML stuff |
729 elif qttype == 'QDomAttr': |
727 elif qttype == "QDomAttr": |
730 attributes = ('name', 'var') |
728 attributes = ("name", "var") |
731 elif qttype in ('QDomCharacterData', 'QDomComment', 'QDomText'): |
729 elif qttype in ("QDomCharacterData", "QDomComment", "QDomText"): |
732 attributes = ('data', ) |
730 attributes = ("data",) |
733 elif qttype == 'QDomDocument': |
731 elif qttype == "QDomDocument": |
734 d.append(('text', var.toString())) |
732 d.append(("text", var.toString())) |
735 elif qttype == 'QDomElement': |
733 elif qttype == "QDomElement": |
736 attributes = ('tagName', 'text') |
734 attributes = ("tagName", "text") |
737 |
735 |
738 # Networking stuff |
736 # Networking stuff |
739 elif qttype == 'QHostAddress': |
737 elif qttype == "QHostAddress": |
740 d.append(('address', var.toString())) |
738 d.append(("address", var.toString())) |
741 |
739 |
742 # PySide specific |
740 # PySide specific |
743 elif qttype == 'EnumType': # Not in PyQt possible |
741 elif qttype == "EnumType": # Not in PyQt possible |
744 for key, value in var.values.items(): |
742 for key, value in var.values.items(): |
745 d.append((key, int(value))) |
743 d.append((key, int(value))) |
746 |
744 |
747 for attribute in attributes: |
745 for attribute in attributes: |
748 d.append((attribute, getattr(var, attribute)())) |
746 d.append((attribute, getattr(var, attribute)())) |
749 |
747 |
750 # add additional fields |
748 # add additional fields |
751 if qttype != 'EnumType': |
749 if qttype != "EnumType": |
752 d.extend(super().getVariableList(var)) |
750 d.extend(super().getVariableList(var)) |
753 |
751 |
754 yield -1, d |
752 yield -1, d |
755 while True: |
753 while True: |
756 yield -2, [] |
754 yield -2, [] |
757 |
755 |
758 |
756 |
804 def updateTypeMap(): |
802 def updateTypeMap(): |
805 """ |
803 """ |
806 Public function to update the type map based on module imports. |
804 Public function to update the type map based on module imports. |
807 """ |
805 """ |
808 global _TypeMap, _ArrayTypes, _TryArray, _TryNumpy, _TryDjango, _MapCount |
806 global _TypeMap, _ArrayTypes, _TryArray, _TryNumpy, _TryDjango, _MapCount |
809 |
807 |
810 # array.array may not be imported (yet) |
808 # array.array may not be imported (yet) |
811 if _TryArray and 'array' in sys.modules: |
809 if _TryArray and "array" in sys.modules: |
812 import array |
810 import array |
|
811 |
813 _TypeMap.append((array.array, arrayResolver)) |
812 _TypeMap.append((array.array, arrayResolver)) |
814 _TryArray = False |
813 _TryArray = False |
815 |
814 |
816 # numpy may not be imported (yet) |
815 # numpy may not be imported (yet) |
817 if _TryNumpy and 'numpy' in sys.modules: |
816 if _TryNumpy and "numpy" in sys.modules: |
818 import numpy |
817 import numpy |
|
818 |
819 _TypeMap.append((numpy.ndarray, ndarrayResolver)) |
819 _TypeMap.append((numpy.ndarray, ndarrayResolver)) |
820 _TryNumpy = False |
820 _TryNumpy = False |
821 |
821 |
822 # django may not be imported (yet) |
822 # django may not be imported (yet) |
823 if _TryDjango and 'django' in sys.modules: |
823 if _TryDjango and "django" in sys.modules: |
824 from django.utils.datastructures import MultiValueDict |
824 from django.utils.datastructures import MultiValueDict |
|
825 |
825 # it should go before dict |
826 # it should go before dict |
826 _TypeMap.insert(0, (MultiValueDict, multiValueDictResolver)) |
827 _TypeMap.insert(0, (MultiValueDict, multiValueDictResolver)) |
827 _TryDjango = False |
828 _TryDjango = False |
828 |
829 |
829 # If _TypeMap changed, rebuild the _ArrayTypes tuple |
830 # If _TypeMap changed, rebuild the _ArrayTypes tuple |
830 if _MapCount != len(_TypeMap): |
831 if _MapCount != len(_TypeMap): |
831 _ArrayTypes = tuple(typ for typ, _resolver in _TypeMap) |
832 _ArrayTypes = tuple(typ for typ, _resolver in _TypeMap) |
832 _MapCount = len(_TypeMap) |
833 _MapCount = len(_TypeMap) |
833 |
834 |
834 |
835 |
835 def getResolver(obj): |
836 def getResolver(obj): |
836 """ |
837 """ |
837 Public method to get the resolver based on the type info of an object. |
838 Public method to get the resolver based on the type info of an object. |
838 |
839 |
839 @param obj object to get resolver for |
840 @param obj object to get resolver for |
840 @type any |
841 @type any |
841 @return resolver |
842 @return resolver |
842 @rtype BaseResolver |
843 @rtype BaseResolver |
843 """ |
844 """ |
844 # Between PyQt and PySide the returned type is different (class vs. type) |
845 # Between PyQt and PySide the returned type is different (class vs. type) |
845 typeStr = str(type(obj)).split(' ', 1)[-1] |
846 typeStr = str(type(obj)).split(" ", 1)[-1] |
846 typeStr = typeStr[1:-2] |
847 typeStr = typeStr[1:-2] |
847 |
848 |
848 if ( |
849 if typeStr.startswith(ConfigQtNames) and typeStr.endswith(ConfigKnownQtTypes): |
849 typeStr.startswith(ConfigQtNames) and |
|
850 typeStr.endswith(ConfigKnownQtTypes) |
|
851 ): |
|
852 return qtResolver |
850 return qtResolver |
853 |
851 |
854 for typeData, resolver in _TypeMap: # __IGNORE_WARNING_M507__ |
852 for typeData, resolver in _TypeMap: # __IGNORE_WARNING_M507__ |
855 if isinstance(obj, typeData): |
853 if isinstance(obj, typeData): |
856 return resolver |
854 return resolver |
857 |
855 |
858 return defaultResolver |
856 return defaultResolver |
|
857 |
859 |
858 |
860 # |
859 # |
861 # eflag: noqa = Y113 |
860 # eflag: noqa = Y113 |