_recattrs.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import pickle
  2. from collections import namedtuple
  3. class RecordLevel:
  4. __slots__ = ("icon", "name", "no")
  5. def __init__(self, name, no, icon):
  6. self.name = name
  7. self.no = no
  8. self.icon = icon
  9. def __repr__(self):
  10. return "(name=%r, no=%r, icon=%r)" % (self.name, self.no, self.icon)
  11. def __format__(self, spec):
  12. return self.name.__format__(spec)
  13. class RecordFile:
  14. __slots__ = ("name", "path")
  15. def __init__(self, name, path):
  16. self.name = name
  17. self.path = path
  18. def __repr__(self):
  19. return "(name=%r, path=%r)" % (self.name, self.path)
  20. def __format__(self, spec):
  21. return self.name.__format__(spec)
  22. class RecordThread:
  23. __slots__ = ("id", "name")
  24. def __init__(self, id_, name):
  25. self.id = id_
  26. self.name = name
  27. def __repr__(self):
  28. return "(id=%r, name=%r)" % (self.id, self.name)
  29. def __format__(self, spec):
  30. return self.id.__format__(spec)
  31. class RecordProcess:
  32. __slots__ = ("id", "name")
  33. def __init__(self, id_, name):
  34. self.id = id_
  35. self.name = name
  36. def __repr__(self):
  37. return "(id=%r, name=%r)" % (self.id, self.name)
  38. def __format__(self, spec):
  39. return self.id.__format__(spec)
  40. class RecordException(
  41. namedtuple("RecordException", ("type", "value", "traceback")) # noqa: PYI024
  42. ):
  43. def __repr__(self):
  44. return "(type=%r, value=%r, traceback=%r)" % (self.type, self.value, self.traceback)
  45. def __reduce__(self):
  46. # The traceback is not picklable, therefore it needs to be removed. Additionally, there's a
  47. # possibility that the exception value is not picklable either. In such cases, we also need
  48. # to remove it. This is done for user convenience, aiming to prevent error logging caused by
  49. # custom exceptions from third-party libraries. If the serialization succeeds, we can reuse
  50. # the pickled value later for optimization (so that it's not pickled twice). It's important
  51. # to note that custom exceptions might not necessarily raise a PickleError, hence the
  52. # generic Exception catch.
  53. try:
  54. pickled_value = pickle.dumps(self.value)
  55. except Exception:
  56. return (RecordException, (self.type, None, None))
  57. else:
  58. return (RecordException._from_pickled_value, (self.type, pickled_value, None))
  59. @classmethod
  60. def _from_pickled_value(cls, type_, pickled_value, traceback_):
  61. try:
  62. # It's safe to use "pickle.loads()" in this case because the pickled value is generated
  63. # by the same code and is not coming from an untrusted source.
  64. value = pickle.loads(pickled_value)
  65. except Exception:
  66. return cls(type_, None, traceback_)
  67. else:
  68. return cls(type_, value, traceback_)