90_pickle.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import pickle as pkl
  2. def test(data): # type: ignore
  3. print('-'*50)
  4. b = pkl.dumps(data)
  5. print(b)
  6. o = pkl.loads(b)
  7. print(o)
  8. assert data == o
  9. return o
  10. test(None) # PKL_NONE
  11. test(...) # PKL_ELLIPSIS
  12. test(1) # PKL_INT8
  13. test(277) # PKL_INT16
  14. test(-66666) # PKL_INT32
  15. test(0xffffffffffff) # PKL_INT64
  16. test(1.0) # PKL_FLOAT32
  17. test(1.12312434234) # PKL_FLOAT64
  18. test(True) # PKL_TRUE
  19. test(False) # PKL_FALSE
  20. test("hello") # PKL_STRING
  21. test(b"hello") # PKL_BYTES
  22. from linalg import vec2, vec3, vec2i, vec3i
  23. test(vec2(2/3, 1.0)) # PKL_VEC2
  24. test(vec3(2/3, 1.0, 3.0)) # PKL_VEC3
  25. test(vec2i(1, 2)) # PKL_VEC2I
  26. test(vec3i(1, 2, 3)) # PKL_VEC3I
  27. test(vec3i) # PKL_TYPE
  28. print('-'*50)
  29. from array2d import array2d
  30. a = array2d[int | bool | vec2i].fromlist([
  31. [1, 2, vec2i.LEFT],
  32. [4, True, 6]
  33. ])
  34. a_encoded = pkl.dumps(a)
  35. print(a_encoded)
  36. a_decoded = pkl.loads(a_encoded)
  37. assert isinstance(a_decoded, array2d)
  38. assert a_decoded.width == 3 and a_decoded.height == 2
  39. assert (a == a_decoded).all()
  40. print(a_decoded)
  41. test([1, 2, 3]) # PKL_LIST
  42. test((1, 2, 3)) # PKL_TUPLE
  43. test({1: 2, 3: 4}) # PKL_DICT
  44. # test complex data
  45. test([1, '2', True])
  46. test([1, '2', 3.0, True])
  47. test([1, '2', True, {'key': 4}])
  48. test([1, '2', 3.0, True, {'k1': 4, 'k2': [b'xxxx']}])
  49. # test memo
  50. a = [1, 2, 3, 4, 5, 6, 745]
  51. b = [a] * 10
  52. c = test(b)
  53. assert b == c
  54. assert b is not c
  55. assert c[0] is c[1] and c[1] is c[2]
  56. s1 = 'hello'
  57. s2 = 'world'
  58. a = [s1, s2] * 10
  59. b = test(a)
  60. assert b == a
  61. assert b is not a
  62. assert b[0] is b[2]
  63. assert b[1] is b[3]
  64. from pkpy import TValue
  65. class Base(TValue[int]):
  66. def __eq__(self, other):
  67. return self.value == other.value
  68. def __ne__(self, other):
  69. return self.value != other.value
  70. class TVal(Base): pass # type: ignore
  71. test(TVal(1))
  72. old_bytes = pkl.dumps(TVal(1))
  73. print(old_bytes)
  74. # re-define the class so it will have a new type id
  75. class TVal(Base): pass
  76. # see if we can still load the old data
  77. decoded = pkl.loads(old_bytes)
  78. assert decoded == TVal(1)
  79. print(pkl.dumps(decoded))
  80. # test array2d with TValue
  81. a = array2d[TVal].fromlist([
  82. [TVal(1), TVal(2)],
  83. [TVal(3), 1]])
  84. test(a)
  85. # test __reduce__
  86. class A:
  87. def __init__(self, seed):
  88. self.seed = seed
  89. self.x = seed
  90. self.y = seed + 1
  91. self.z = seed + 2
  92. def __eq__(self, other):
  93. return (self.x, self.y, self.z) == (other.x, other.y, other.z)
  94. def __ne__(self, other):
  95. return (self.x, self.y, self.z) != (other.x, other.y, other.z)
  96. def __repr__(self):
  97. return f"A({self.seed}, x={self.x}, y={self.y}, z={self.z})"
  98. def __reduce__(self):
  99. print('__reduce__() called')
  100. return A, (self.seed,)
  101. test([A(1)]*10)
  102. class Simple:
  103. def __init__(self, x):
  104. self.field1 = x
  105. self.field2 = [...]
  106. def __eq__(self, other): return self.field1 == other.field1
  107. def __ne__(self, other): return self.field1 != other.field1
  108. test(Simple(1))
  109. test([Simple(2)]*10)
  110. from dataclasses import dataclass
  111. @dataclass
  112. class Data:
  113. a: int
  114. b: str = '2'
  115. c: float = 3.0
  116. test(Data(1))
  117. exit()
  118. from pickle import dumps, loads, _wrap, _unwrap
  119. def test(x):
  120. y = dumps(x)
  121. # print(y.decode())
  122. ok = x == loads(y)
  123. if not ok:
  124. _0 = _wrap(x)
  125. _1 = _unwrap(_0)
  126. print('='*50)
  127. print(_0)
  128. print('-'*50)
  129. print(_1)
  130. print('='*50)
  131. assert False
  132. test(1)
  133. test(1.0)
  134. test("hello")
  135. test(True)
  136. test(False)
  137. test(None)
  138. test([1, 2, 3])
  139. test((1, 2, 3))
  140. test({1: 2, 3: 4})
  141. class Foo:
  142. def __init__(self, x, y):
  143. self.x = x
  144. self.y = y
  145. def __eq__(self, __value: object) -> bool:
  146. if not isinstance(__value, Foo):
  147. return False
  148. return self.x == __value.x and self.y == __value.y
  149. def __repr__(self) -> str:
  150. return f"Foo({self.x}, {self.y})"
  151. test(Foo(1, 2))
  152. test(Foo([1, True], 'c'))
  153. from linalg import vec2
  154. test(vec2(1, 2))
  155. a = {1, 2, 3, 4}
  156. test(a)
  157. a = bytes([1, 2, 3, 4])
  158. test(a)
  159. a = [1, 2]
  160. d = {'k': a, 'j': a}
  161. c = loads(dumps(d))
  162. assert c['k'] is c['j']
  163. assert c == d
  164. # test circular references
  165. from collections import deque
  166. a = deque([1, 2, 3])
  167. test(a)
  168. a = [int, float, Foo]
  169. test(a)