python-pickle 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.github/workflows/ruby.yml +27 -0
  4. data/.gitignore +5 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +14 -0
  8. data/Gemfile +15 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +149 -0
  11. data/Rakefile +13 -0
  12. data/gemspec.yml +25 -0
  13. data/lib/python/pickle/byte_array.rb +40 -0
  14. data/lib/python/pickle/deserializer.rb +595 -0
  15. data/lib/python/pickle/exceptions.rb +12 -0
  16. data/lib/python/pickle/instruction.rb +52 -0
  17. data/lib/python/pickle/instructions/add_items.rb +26 -0
  18. data/lib/python/pickle/instructions/append.rb +24 -0
  19. data/lib/python/pickle/instructions/appends.rb +26 -0
  20. data/lib/python/pickle/instructions/bin_bytes.rb +32 -0
  21. data/lib/python/pickle/instructions/bin_bytes8.rb +32 -0
  22. data/lib/python/pickle/instructions/bin_float.rb +29 -0
  23. data/lib/python/pickle/instructions/bin_get.rb +27 -0
  24. data/lib/python/pickle/instructions/bin_int1.rb +29 -0
  25. data/lib/python/pickle/instructions/bin_put.rb +29 -0
  26. data/lib/python/pickle/instructions/bin_string.rb +32 -0
  27. data/lib/python/pickle/instructions/bin_unicode.rb +32 -0
  28. data/lib/python/pickle/instructions/bin_unicode8.rb +32 -0
  29. data/lib/python/pickle/instructions/build.rb +24 -0
  30. data/lib/python/pickle/instructions/byte_array8.rb +32 -0
  31. data/lib/python/pickle/instructions/dict.rb +17 -0
  32. data/lib/python/pickle/instructions/dup.rb +24 -0
  33. data/lib/python/pickle/instructions/empty_dict.rb +26 -0
  34. data/lib/python/pickle/instructions/empty_list.rb +26 -0
  35. data/lib/python/pickle/instructions/empty_set.rb +26 -0
  36. data/lib/python/pickle/instructions/empty_tuple.rb +26 -0
  37. data/lib/python/pickle/instructions/ext1.rb +29 -0
  38. data/lib/python/pickle/instructions/ext2.rb +29 -0
  39. data/lib/python/pickle/instructions/ext4.rb +29 -0
  40. data/lib/python/pickle/instructions/float.rb +24 -0
  41. data/lib/python/pickle/instructions/frame.rb +29 -0
  42. data/lib/python/pickle/instructions/frozen_set.rb +26 -0
  43. data/lib/python/pickle/instructions/get.rb +27 -0
  44. data/lib/python/pickle/instructions/global.rb +62 -0
  45. data/lib/python/pickle/instructions/has_length_and_value.rb +58 -0
  46. data/lib/python/pickle/instructions/has_value.rb +50 -0
  47. data/lib/python/pickle/instructions/int.rb +24 -0
  48. data/lib/python/pickle/instructions/list.rb +24 -0
  49. data/lib/python/pickle/instructions/long.rb +24 -0
  50. data/lib/python/pickle/instructions/long1.rb +32 -0
  51. data/lib/python/pickle/instructions/long4.rb +32 -0
  52. data/lib/python/pickle/instructions/long_bin_get.rb +27 -0
  53. data/lib/python/pickle/instructions/mark.rb +24 -0
  54. data/lib/python/pickle/instructions/memoize.rb +26 -0
  55. data/lib/python/pickle/instructions/new_false.rb +24 -0
  56. data/lib/python/pickle/instructions/new_obj.rb +26 -0
  57. data/lib/python/pickle/instructions/new_obj_ex.rb +26 -0
  58. data/lib/python/pickle/instructions/new_true.rb +24 -0
  59. data/lib/python/pickle/instructions/next_buffer.rb +26 -0
  60. data/lib/python/pickle/instructions/none.rb +24 -0
  61. data/lib/python/pickle/instructions/pop.rb +24 -0
  62. data/lib/python/pickle/instructions/pop_mark.rb +24 -0
  63. data/lib/python/pickle/instructions/proto.rb +29 -0
  64. data/lib/python/pickle/instructions/put.rb +24 -0
  65. data/lib/python/pickle/instructions/readonly_buffer.rb +26 -0
  66. data/lib/python/pickle/instructions/reduce.rb +24 -0
  67. data/lib/python/pickle/instructions/set_item.rb +24 -0
  68. data/lib/python/pickle/instructions/set_items.rb +26 -0
  69. data/lib/python/pickle/instructions/short_bin_bytes.rb +32 -0
  70. data/lib/python/pickle/instructions/short_bin_string.rb +32 -0
  71. data/lib/python/pickle/instructions/short_bin_unicode.rb +32 -0
  72. data/lib/python/pickle/instructions/stack_global.rb +26 -0
  73. data/lib/python/pickle/instructions/stop.rb +24 -0
  74. data/lib/python/pickle/instructions/string.rb +24 -0
  75. data/lib/python/pickle/instructions/tuple.rb +24 -0
  76. data/lib/python/pickle/instructions/tuple1.rb +24 -0
  77. data/lib/python/pickle/instructions/tuple2.rb +24 -0
  78. data/lib/python/pickle/instructions/tuple3.rb +24 -0
  79. data/lib/python/pickle/protocol.rb +56 -0
  80. data/lib/python/pickle/protocol0.rb +399 -0
  81. data/lib/python/pickle/protocol1.rb +183 -0
  82. data/lib/python/pickle/protocol2.rb +229 -0
  83. data/lib/python/pickle/protocol3.rb +163 -0
  84. data/lib/python/pickle/protocol4.rb +285 -0
  85. data/lib/python/pickle/protocol5.rb +218 -0
  86. data/lib/python/pickle/py_class.rb +75 -0
  87. data/lib/python/pickle/py_object.rb +141 -0
  88. data/lib/python/pickle/tuple.rb +19 -0
  89. data/lib/python/pickle/version.rb +6 -0
  90. data/lib/python/pickle.rb +226 -0
  91. data/python-pickle.gemspec +62 -0
  92. data/spec/byte_array_spec.rb +54 -0
  93. data/spec/deserializer_spec.rb +1201 -0
  94. data/spec/fixtures/ascii_str_v3.pkl +0 -0
  95. data/spec/fixtures/ascii_str_v4.pkl +0 -0
  96. data/spec/fixtures/ascii_str_v5.pkl +0 -0
  97. data/spec/fixtures/bin_str_v0.pkl +3 -0
  98. data/spec/fixtures/bin_str_v1.pkl +0 -0
  99. data/spec/fixtures/bin_str_v2.pkl +0 -0
  100. data/spec/fixtures/bin_str_v3.pkl +0 -0
  101. data/spec/fixtures/bin_str_v4.pkl +0 -0
  102. data/spec/fixtures/bin_str_v5.pkl +0 -0
  103. data/spec/fixtures/bytearray_v0.pkl +10 -0
  104. data/spec/fixtures/bytearray_v1.pkl +0 -0
  105. data/spec/fixtures/bytearray_v2.pkl +0 -0
  106. data/spec/fixtures/bytearray_v3.pkl +0 -0
  107. data/spec/fixtures/bytearray_v4.pkl +0 -0
  108. data/spec/fixtures/bytearray_v5.pkl +0 -0
  109. data/spec/fixtures/class_v0.pkl +4 -0
  110. data/spec/fixtures/class_v1.pkl +0 -0
  111. data/spec/fixtures/class_v2.pkl +0 -0
  112. data/spec/fixtures/class_v3.pkl +0 -0
  113. data/spec/fixtures/class_v4.pkl +0 -0
  114. data/spec/fixtures/class_v5.pkl +0 -0
  115. data/spec/fixtures/dict_v0.pkl +6 -0
  116. data/spec/fixtures/dict_v1.pkl +0 -0
  117. data/spec/fixtures/dict_v2.pkl +0 -0
  118. data/spec/fixtures/dict_v3.pkl +0 -0
  119. data/spec/fixtures/dict_v4.pkl +0 -0
  120. data/spec/fixtures/dict_v5.pkl +0 -0
  121. data/spec/fixtures/escaped_str_v0.pkl +3 -0
  122. data/spec/fixtures/escaped_str_v1.pkl +0 -0
  123. data/spec/fixtures/escaped_str_v2.pkl +0 -0
  124. data/spec/fixtures/false_v0.pkl +2 -0
  125. data/spec/fixtures/false_v1.pkl +2 -0
  126. data/spec/fixtures/false_v2.pkl +1 -0
  127. data/spec/fixtures/false_v3.pkl +1 -0
  128. data/spec/fixtures/false_v4.pkl +1 -0
  129. data/spec/fixtures/false_v5.pkl +1 -0
  130. data/spec/fixtures/float_v0.pkl +2 -0
  131. data/spec/fixtures/float_v1.pkl +1 -0
  132. data/spec/fixtures/float_v2.pkl +1 -0
  133. data/spec/fixtures/float_v3.pkl +1 -0
  134. data/spec/fixtures/float_v4.pkl +0 -0
  135. data/spec/fixtures/float_v5.pkl +0 -0
  136. data/spec/fixtures/function_v0.pkl +4 -0
  137. data/spec/fixtures/function_v1.pkl +0 -0
  138. data/spec/fixtures/function_v2.pkl +0 -0
  139. data/spec/fixtures/function_v3.pkl +0 -0
  140. data/spec/fixtures/function_v4.pkl +0 -0
  141. data/spec/fixtures/function_v5.pkl +0 -0
  142. data/spec/fixtures/hex_str_v0.pkl +3 -0
  143. data/spec/fixtures/hex_str_v1.pkl +0 -0
  144. data/spec/fixtures/hex_str_v2.pkl +0 -0
  145. data/spec/fixtures/int_v0.pkl +2 -0
  146. data/spec/fixtures/int_v1.pkl +1 -0
  147. data/spec/fixtures/int_v2.pkl +1 -0
  148. data/spec/fixtures/int_v3.pkl +1 -0
  149. data/spec/fixtures/int_v4.pkl +1 -0
  150. data/spec/fixtures/int_v5.pkl +1 -0
  151. data/spec/fixtures/list_v0.pkl +7 -0
  152. data/spec/fixtures/list_v1.pkl +0 -0
  153. data/spec/fixtures/list_v2.pkl +0 -0
  154. data/spec/fixtures/list_v3.pkl +0 -0
  155. data/spec/fixtures/list_v4.pkl +0 -0
  156. data/spec/fixtures/list_v5.pkl +0 -0
  157. data/spec/fixtures/long_v0.pkl +2 -0
  158. data/spec/fixtures/long_v1.pkl +2 -0
  159. data/spec/fixtures/long_v2.pkl +0 -0
  160. data/spec/fixtures/long_v3.pkl +0 -0
  161. data/spec/fixtures/long_v4.pkl +0 -0
  162. data/spec/fixtures/long_v5.pkl +0 -0
  163. data/spec/fixtures/nested_dict_v0.pkl +12 -0
  164. data/spec/fixtures/nested_dict_v1.pkl +0 -0
  165. data/spec/fixtures/nested_dict_v2.pkl +0 -0
  166. data/spec/fixtures/nested_dict_v3.pkl +0 -0
  167. data/spec/fixtures/nested_dict_v4.pkl +0 -0
  168. data/spec/fixtures/nested_dict_v5.pkl +0 -0
  169. data/spec/fixtures/nested_list_v0.pkl +9 -0
  170. data/spec/fixtures/nested_list_v1.pkl +0 -0
  171. data/spec/fixtures/nested_list_v2.pkl +0 -0
  172. data/spec/fixtures/nested_list_v3.pkl +0 -0
  173. data/spec/fixtures/nested_list_v4.pkl +0 -0
  174. data/spec/fixtures/nested_list_v5.pkl +0 -0
  175. data/spec/fixtures/none_v0.pkl +1 -0
  176. data/spec/fixtures/none_v1.pkl +1 -0
  177. data/spec/fixtures/none_v2.pkl +1 -0
  178. data/spec/fixtures/none_v3.pkl +1 -0
  179. data/spec/fixtures/none_v4.pkl +1 -0
  180. data/spec/fixtures/none_v5.pkl +1 -0
  181. data/spec/fixtures/object_v0.pkl +19 -0
  182. data/spec/fixtures/object_v1.pkl +0 -0
  183. data/spec/fixtures/object_v2.pkl +0 -0
  184. data/spec/fixtures/object_v3.pkl +0 -0
  185. data/spec/fixtures/object_v4.pkl +0 -0
  186. data/spec/fixtures/object_v5.pkl +0 -0
  187. data/spec/fixtures/str_v0.pkl +3 -0
  188. data/spec/fixtures/str_v1.pkl +0 -0
  189. data/spec/fixtures/str_v2.pkl +0 -0
  190. data/spec/fixtures/str_v3.pkl +0 -0
  191. data/spec/fixtures/str_v4.pkl +0 -0
  192. data/spec/fixtures/str_v5.pkl +0 -0
  193. data/spec/fixtures/true_v0.pkl +2 -0
  194. data/spec/fixtures/true_v1.pkl +2 -0
  195. data/spec/fixtures/true_v2.pkl +1 -0
  196. data/spec/fixtures/true_v3.pkl +1 -0
  197. data/spec/fixtures/true_v4.pkl +1 -0
  198. data/spec/fixtures/true_v5.pkl +1 -0
  199. data/spec/fixtures/unicode_str_v0.pkl +3 -0
  200. data/spec/fixtures/unicode_str_v1.pkl +0 -0
  201. data/spec/fixtures/unicode_str_v2.pkl +0 -0
  202. data/spec/fixtures/unicode_str_v3.pkl +0 -0
  203. data/spec/fixtures/unicode_str_v4.pkl +0 -0
  204. data/spec/fixtures/unicode_str_v5.pkl +0 -0
  205. data/spec/generate_pickles2.py +41 -0
  206. data/spec/generate_pickles3.py +40 -0
  207. data/spec/integration/load/protocol0_spec.rb +258 -0
  208. data/spec/integration/load/protocol1_spec.rb +258 -0
  209. data/spec/integration/load/protocol2_spec.rb +258 -0
  210. data/spec/integration/load/protocol3_spec.rb +258 -0
  211. data/spec/integration/load/protocol4_spec.rb +258 -0
  212. data/spec/integration/load/protocol5_spec.rb +258 -0
  213. data/spec/integration/parse/protocol0_spec.rb +467 -0
  214. data/spec/integration/parse/protocol1_spec.rb +459 -0
  215. data/spec/integration/parse/protocol2_spec.rb +471 -0
  216. data/spec/integration/parse/protocol3_spec.rb +407 -0
  217. data/spec/integration/parse/protocol4_spec.rb +439 -0
  218. data/spec/integration/parse/protocol5_spec.rb +419 -0
  219. data/spec/pickle_spec.rb +163 -0
  220. data/spec/protocol0_read_instruction_examples.rb +211 -0
  221. data/spec/protocol0_spec.rb +445 -0
  222. data/spec/protocol1_read_instruction_examples.rb +156 -0
  223. data/spec/protocol1_spec.rb +59 -0
  224. data/spec/protocol2_read_instruction_examples.rb +135 -0
  225. data/spec/protocol2_spec.rb +128 -0
  226. data/spec/protocol3_read_instruction_examples.rb +29 -0
  227. data/spec/protocol3_spec.rb +32 -0
  228. data/spec/protocol4_read_instruction_examples.rb +142 -0
  229. data/spec/protocol4_spec.rb +58 -0
  230. data/spec/protocol5_spec.rb +68 -0
  231. data/spec/py_class_spec.rb +62 -0
  232. data/spec/py_object_spec.rb +149 -0
  233. data/spec/spec_helper.rb +3 -0
  234. data/spec/tuple_spec.rb +18 -0
  235. metadata +325 -0
@@ -0,0 +1,459 @@
1
+ require 'spec_helper'
2
+ require 'python/pickle'
3
+
4
+ describe Python::Pickle do
5
+ let(:fixtures_dir) { File.join(__dir__,'..','..','fixtures') }
6
+
7
+ describe ".parse" do
8
+ context "when given a Pickle protocol 1 stream" do
9
+ let(:io) { File.open(file) }
10
+
11
+ context "and it contains a serialized None" do
12
+ let(:file) { File.join(fixtures_dir,'none_v1.pkl') }
13
+
14
+ it "must return a Python::Pickle::Instructions::NONE" do
15
+ expect(subject.parse(io)).to eq(
16
+ [
17
+ Python::Pickle::Instructions::NONE,
18
+ Python::Pickle::Instructions::STOP
19
+ ]
20
+ )
21
+ end
22
+
23
+ context "and when a block is given" do
24
+ it "must yield each parsed instruction" do
25
+ expect {|b|
26
+ subject.parse(io,&b)
27
+ }.to yield_successive_args(
28
+ Python::Pickle::Instructions::NONE,
29
+ Python::Pickle::Instructions::STOP
30
+ )
31
+ end
32
+ end
33
+ end
34
+
35
+ context "and it contains a serialized True" do
36
+ let(:file) { File.join(fixtures_dir,'true_v1.pkl') }
37
+
38
+ it "must return a Python::Pickle::Instructions::Int containing a true value" do
39
+ expect(subject.parse(io)).to eq(
40
+ [
41
+ Python::Pickle::Instructions::Int.new(true),
42
+ Python::Pickle::Instructions::STOP
43
+ ]
44
+ )
45
+ end
46
+
47
+ context "and when a block is given" do
48
+ it "must yield each parsed instruction" do
49
+ expect {|b|
50
+ subject.parse(io,&b)
51
+ }.to yield_successive_args(
52
+ Python::Pickle::Instructions::Int.new(true),
53
+ Python::Pickle::Instructions::STOP
54
+ )
55
+ end
56
+ end
57
+ end
58
+
59
+ context "and it contains a serialized False" do
60
+ let(:file) { File.join(fixtures_dir,'false_v1.pkl') }
61
+
62
+ it "must return a Python::Pickle::Instructions::Int with a false value" do
63
+ expect(subject.parse(io)).to eq(
64
+ [
65
+ Python::Pickle::Instructions::Int.new(false),
66
+ Python::Pickle::Instructions::STOP
67
+ ]
68
+ )
69
+ end
70
+
71
+ context "and when a block is given" do
72
+ it "must yield each parsed instruction" do
73
+ expect {|b|
74
+ subject.parse(io,&b)
75
+ }.to yield_successive_args(
76
+ Python::Pickle::Instructions::Int.new(false),
77
+ Python::Pickle::Instructions::STOP
78
+ )
79
+ end
80
+ end
81
+ end
82
+
83
+ context "and it contains a serialized integer" do
84
+ let(:file) { File.join(fixtures_dir,'int_v1.pkl') }
85
+
86
+ it "must return a Python::Pickle::Instructions::BinInt1 with the decoded number" do
87
+ expect(subject.parse(io)).to eq(
88
+ [
89
+ Python::Pickle::Instructions::BinInt1.new(42),
90
+ Python::Pickle::Instructions::STOP
91
+ ]
92
+ )
93
+ end
94
+
95
+ context "and when a block is given" do
96
+ it "must yield each parsed instruction" do
97
+ expect {|b|
98
+ subject.parse(io,&b)
99
+ }.to yield_successive_args(
100
+ Python::Pickle::Instructions::BinInt1.new(42),
101
+ Python::Pickle::Instructions::STOP
102
+ )
103
+ end
104
+ end
105
+ end
106
+
107
+ context "and it contains a long integer" do
108
+ let(:file) { File.join(fixtures_dir,'long_v1.pkl') }
109
+
110
+ it "must return a Python::Pickle::Instructions::Long with the decoded number" do
111
+ expect(subject.parse(io)).to eq(
112
+ [
113
+ Python::Pickle::Instructions::Long.new(18446744073709551615),
114
+ Python::Pickle::Instructions::STOP
115
+ ]
116
+ )
117
+ end
118
+
119
+ context "and when a block is given" do
120
+ it "must yield each parsed instruction" do
121
+ expect {|b|
122
+ subject.parse(io,&b)
123
+ }.to yield_successive_args(
124
+ Python::Pickle::Instructions::Long.new(18446744073709551615),
125
+ Python::Pickle::Instructions::STOP
126
+ )
127
+ end
128
+ end
129
+ end
130
+
131
+ context "and it contains a serialized floating-point number" do
132
+ let(:float) { 3.141592653589793 }
133
+ let(:file) { File.join(fixtures_dir,'float_v1.pkl') }
134
+
135
+ it "must return a Python::Pickle::Instructions::BinFloat with the decoded number" do
136
+ expect(subject.parse(io)).to eq(
137
+ [
138
+ Python::Pickle::Instructions::BinFloat.new(float),
139
+ Python::Pickle::Instructions::STOP
140
+ ]
141
+ )
142
+ end
143
+
144
+ context "and when a block is given" do
145
+ it "must yield each parsed instruction" do
146
+ expect {|b|
147
+ subject.parse(io,&b)
148
+ }.to yield_successive_args(
149
+ Python::Pickle::Instructions::BinFloat.new(float),
150
+ Python::Pickle::Instructions::STOP
151
+ )
152
+ end
153
+ end
154
+ end
155
+
156
+ context "and it contains a plain string" do
157
+ let(:string) { "ABC" }
158
+ let(:length) { string.bytesize }
159
+ let(:file) { File.join(fixtures_dir,'str_v1.pkl') }
160
+
161
+ it "must return a Python::Pickle::Instructions::ShortBinString with the decoded number" do
162
+ expect(subject.parse(io)).to eq(
163
+ [
164
+ Python::Pickle::Instructions::ShortBinString.new(length,string),
165
+ Python::Pickle::Instructions::BinPut.new(0),
166
+ Python::Pickle::Instructions::STOP
167
+ ]
168
+ )
169
+ end
170
+
171
+ context "and when a block is given" do
172
+ it "must yield each parsed instruction" do
173
+ expect {|b|
174
+ subject.parse(io,&b)
175
+ }.to yield_successive_args(
176
+ Python::Pickle::Instructions::ShortBinString.new(length,string),
177
+ Python::Pickle::Instructions::BinPut.new(0),
178
+ Python::Pickle::Instructions::STOP
179
+ )
180
+ end
181
+ end
182
+ end
183
+
184
+ context "and it contains a string with backslash-escaped characters" do
185
+ let(:string) { "ABC\t\n\r\\'\"" }
186
+ let(:length) { string.bytesize }
187
+ let(:file) { File.join(fixtures_dir,'escaped_str_v1.pkl') }
188
+
189
+ it "must return a Python::Pickle::Instructions::ShortBinString with the decoded number" do
190
+ expect(subject.parse(io)).to eq(
191
+ [
192
+ Python::Pickle::Instructions::ShortBinString.new(length,string),
193
+ Python::Pickle::Instructions::BinPut.new(0),
194
+ Python::Pickle::Instructions::STOP
195
+ ]
196
+ )
197
+ end
198
+
199
+ context "and when a block is given" do
200
+ it "must yield each parsed instruction" do
201
+ expect {|b|
202
+ subject.parse(io,&b)
203
+ }.to yield_successive_args(
204
+ Python::Pickle::Instructions::ShortBinString.new(length,string),
205
+ Python::Pickle::Instructions::BinPut.new(0),
206
+ Python::Pickle::Instructions::STOP
207
+ )
208
+ end
209
+ end
210
+ end
211
+
212
+ context "and it contains a string with hex-escaped characters" do
213
+ let(:string) { (0..255).map(&:chr).join }
214
+ let(:length) { string.bytesize }
215
+ let(:file) { File.join(fixtures_dir,'bin_str_v1.pkl') }
216
+
217
+ it "must return a Python::Pickle::Instructions::BinString with the decoded number" do
218
+ expect(subject.parse(io)).to eq(
219
+ [
220
+ Python::Pickle::Instructions::BinString.new(length,string),
221
+ Python::Pickle::Instructions::BinPut.new(0),
222
+ Python::Pickle::Instructions::STOP
223
+ ]
224
+ )
225
+ end
226
+
227
+ context "and when a block is given" do
228
+ it "must yield each parsed instruction" do
229
+ expect {|b|
230
+ subject.parse(io,&b)
231
+ }.to yield_successive_args(
232
+ Python::Pickle::Instructions::BinString.new(length,string),
233
+ Python::Pickle::Instructions::BinPut.new(0),
234
+ Python::Pickle::Instructions::STOP
235
+ )
236
+ end
237
+ end
238
+ end
239
+
240
+ context "and it contains a UTF string" do
241
+ let(:string) { "ABC\u265E\u265F\u{1F600}" }
242
+ let(:length) { string.bytesize }
243
+ let(:file) { File.join(fixtures_dir,'unicode_str_v1.pkl') }
244
+
245
+ it "must return a Python::Pickle::Instructions::BinUnicode with the decoded number" do
246
+ expect(subject.parse(io)).to eq(
247
+ [
248
+ Python::Pickle::Instructions::BinUnicode.new(length,string),
249
+ Python::Pickle::Instructions::BinPut.new(0),
250
+ Python::Pickle::Instructions::STOP
251
+ ]
252
+ )
253
+ end
254
+
255
+ context "and when a block is given" do
256
+ it "must yield each parsed instruction" do
257
+ expect {|b|
258
+ subject.parse(io,&b)
259
+ }.to yield_successive_args(
260
+ Python::Pickle::Instructions::BinUnicode.new(length,string),
261
+ Python::Pickle::Instructions::BinPut.new(0),
262
+ Python::Pickle::Instructions::STOP
263
+ )
264
+ end
265
+ end
266
+ end
267
+
268
+ context "and it contains a list type" do
269
+ let(:file) { File.join(fixtures_dir,'list_v1.pkl') }
270
+
271
+ it "must return an Array of parsed instructions" do
272
+ expect(subject.parse(io)).to eq(
273
+ [
274
+ Python::Pickle::Instructions::EMPTY_LIST,
275
+ Python::Pickle::Instructions::BinPut.new(0),
276
+ Python::Pickle::Instructions::MARK,
277
+ Python::Pickle::Instructions::NONE,
278
+ Python::Pickle::Instructions::Int.new(true),
279
+ Python::Pickle::Instructions::Int.new(false),
280
+ Python::Pickle::Instructions::BinInt1.new(42),
281
+ Python::Pickle::Instructions::ShortBinString.new(3,"ABC"),
282
+ Python::Pickle::Instructions::BinPut.new(1),
283
+ Python::Pickle::Instructions::APPENDS,
284
+ Python::Pickle::Instructions::STOP
285
+ ]
286
+ )
287
+ end
288
+
289
+ context "and when a block is given" do
290
+ it "must yield each parsed instruction" do
291
+ expect {|b|
292
+ subject.parse(io,&b)
293
+ }.to yield_successive_args(
294
+ Python::Pickle::Instructions::EMPTY_LIST,
295
+ Python::Pickle::Instructions::BinPut.new(0),
296
+ Python::Pickle::Instructions::MARK,
297
+ Python::Pickle::Instructions::NONE,
298
+ Python::Pickle::Instructions::Int.new(true),
299
+ Python::Pickle::Instructions::Int.new(false),
300
+ Python::Pickle::Instructions::BinInt1.new(42),
301
+ Python::Pickle::Instructions::ShortBinString.new(3,"ABC"),
302
+ Python::Pickle::Instructions::BinPut.new(1),
303
+ Python::Pickle::Instructions::APPENDS,
304
+ Python::Pickle::Instructions::STOP
305
+ )
306
+ end
307
+ end
308
+ end
309
+
310
+ context "and it contains a dict type" do
311
+ let(:file) { File.join(fixtures_dir,'dict_v1.pkl') }
312
+
313
+ it "must return an Array of parsed instructions" do
314
+ expect(subject.parse(io)).to eq(
315
+ [
316
+ Python::Pickle::Instructions::EMPTY_DICT,
317
+ Python::Pickle::Instructions::BinPut.new(0),
318
+ Python::Pickle::Instructions::ShortBinString.new(3,"foo"),
319
+ Python::Pickle::Instructions::BinPut.new(1),
320
+ Python::Pickle::Instructions::ShortBinString.new(3,"bar"),
321
+ Python::Pickle::Instructions::BinPut.new(2),
322
+ Python::Pickle::Instructions::SETITEM,
323
+ Python::Pickle::Instructions::STOP
324
+ ]
325
+ )
326
+ end
327
+
328
+ context "and when a block is given" do
329
+ it "must yield each parsed instruction" do
330
+ expect {|b|
331
+ subject.parse(io,&b)
332
+ }.to yield_successive_args(
333
+ Python::Pickle::Instructions::EMPTY_DICT,
334
+ Python::Pickle::Instructions::BinPut.new(0),
335
+ Python::Pickle::Instructions::ShortBinString.new(3,"foo"),
336
+ Python::Pickle::Instructions::BinPut.new(1),
337
+ Python::Pickle::Instructions::ShortBinString.new(3,"bar"),
338
+ Python::Pickle::Instructions::BinPut.new(2),
339
+ Python::Pickle::Instructions::SETITEM,
340
+ Python::Pickle::Instructions::STOP
341
+ )
342
+ end
343
+ end
344
+ end
345
+
346
+ context "and it contains an object type" do
347
+ let(:file) { File.join(fixtures_dir,'object_v1.pkl') }
348
+
349
+ it "must return an Array of parsed instructions" do
350
+ expect(subject.parse(io)).to eq(
351
+ [
352
+ Python::Pickle::Instructions::Global.new('copy_reg','_reconstructor'),
353
+ Python::Pickle::Instructions::BinPut.new(0),
354
+ Python::Pickle::Instructions::MARK,
355
+ Python::Pickle::Instructions::Global.new('__main__','MyClass'),
356
+ Python::Pickle::Instructions::BinPut.new(1),
357
+ Python::Pickle::Instructions::Global.new('__builtin__','object'),
358
+ Python::Pickle::Instructions::BinPut.new(2),
359
+ Python::Pickle::Instructions::NONE,
360
+ Python::Pickle::Instructions::TUPLE,
361
+ Python::Pickle::Instructions::BinPut.new(3),
362
+ Python::Pickle::Instructions::REDUCE,
363
+ Python::Pickle::Instructions::BinPut.new(4),
364
+ Python::Pickle::Instructions::EMPTY_DICT,
365
+ Python::Pickle::Instructions::BinPut.new(5),
366
+ Python::Pickle::Instructions::MARK,
367
+ Python::Pickle::Instructions::ShortBinString.new(1,'y'),
368
+ Python::Pickle::Instructions::BinPut.new(6),
369
+ Python::Pickle::Instructions::BinInt1.new(66),
370
+ Python::Pickle::Instructions::ShortBinString.new(1,'x'),
371
+ Python::Pickle::Instructions::BinPut.new(7),
372
+ Python::Pickle::Instructions::BinInt1.new(65),
373
+ Python::Pickle::Instructions::SETITEMS,
374
+ Python::Pickle::Instructions::BUILD,
375
+ Python::Pickle::Instructions::STOP
376
+ ]
377
+ )
378
+ end
379
+
380
+ context "and when a block is given" do
381
+ it "must yield each parsed instruction" do
382
+ expect {|b|
383
+ subject.parse(io,&b)
384
+ }.to yield_successive_args(
385
+ Python::Pickle::Instructions::Global.new('copy_reg','_reconstructor'),
386
+ Python::Pickle::Instructions::BinPut.new(0),
387
+ Python::Pickle::Instructions::MARK,
388
+ Python::Pickle::Instructions::Global.new('__main__','MyClass'),
389
+ Python::Pickle::Instructions::BinPut.new(1),
390
+ Python::Pickle::Instructions::Global.new('__builtin__','object'),
391
+ Python::Pickle::Instructions::BinPut.new(2),
392
+ Python::Pickle::Instructions::NONE,
393
+ Python::Pickle::Instructions::TUPLE,
394
+ Python::Pickle::Instructions::BinPut.new(3),
395
+ Python::Pickle::Instructions::REDUCE,
396
+ Python::Pickle::Instructions::BinPut.new(4),
397
+ Python::Pickle::Instructions::EMPTY_DICT,
398
+ Python::Pickle::Instructions::BinPut.new(5),
399
+ Python::Pickle::Instructions::MARK,
400
+ Python::Pickle::Instructions::ShortBinString.new(1,'y'),
401
+ Python::Pickle::Instructions::BinPut.new(6),
402
+ Python::Pickle::Instructions::BinInt1.new(66),
403
+ Python::Pickle::Instructions::ShortBinString.new(1,'x'),
404
+ Python::Pickle::Instructions::BinPut.new(7),
405
+ Python::Pickle::Instructions::BinInt1.new(65),
406
+ Python::Pickle::Instructions::SETITEMS,
407
+ Python::Pickle::Instructions::BUILD,
408
+ Python::Pickle::Instructions::STOP
409
+ )
410
+ end
411
+ end
412
+ end
413
+
414
+ context "and it contains a bytearray type" do
415
+ let(:file) { File.join(fixtures_dir,'bytearray_v1.pkl') }
416
+
417
+ it "must return an Array of parsed instructions" do
418
+ expect(subject.parse(io)).to eq(
419
+ [
420
+ Python::Pickle::Instructions::Global.new('__builtin__','bytearray'),
421
+ Python::Pickle::Instructions::BinPut.new(0),
422
+ Python::Pickle::Instructions::MARK,
423
+ Python::Pickle::Instructions::BinUnicode.new(3,'ABC'),
424
+ Python::Pickle::Instructions::BinPut.new(1),
425
+ Python::Pickle::Instructions::ShortBinString.new(7,'latin-1'),
426
+ Python::Pickle::Instructions::BinPut.new(2),
427
+ Python::Pickle::Instructions::TUPLE,
428
+ Python::Pickle::Instructions::BinPut.new(3),
429
+ Python::Pickle::Instructions::REDUCE,
430
+ Python::Pickle::Instructions::BinPut.new(4),
431
+ Python::Pickle::Instructions::STOP
432
+ ]
433
+ )
434
+ end
435
+
436
+ context "and when a block is given" do
437
+ it "must yield each parsed instruction" do
438
+ expect {|b|
439
+ subject.parse(io,&b)
440
+ }.to yield_successive_args(
441
+ Python::Pickle::Instructions::Global.new('__builtin__','bytearray'),
442
+ Python::Pickle::Instructions::BinPut.new(0),
443
+ Python::Pickle::Instructions::MARK,
444
+ Python::Pickle::Instructions::BinUnicode.new(3,'ABC'),
445
+ Python::Pickle::Instructions::BinPut.new(1),
446
+ Python::Pickle::Instructions::ShortBinString.new(7,'latin-1'),
447
+ Python::Pickle::Instructions::BinPut.new(2),
448
+ Python::Pickle::Instructions::TUPLE,
449
+ Python::Pickle::Instructions::BinPut.new(3),
450
+ Python::Pickle::Instructions::REDUCE,
451
+ Python::Pickle::Instructions::BinPut.new(4),
452
+ Python::Pickle::Instructions::STOP
453
+ )
454
+ end
455
+ end
456
+ end
457
+ end
458
+ end
459
+ end