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,467 @@
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 0 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_v0.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_v0.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_v0.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_v0.pkl') }
85
+
86
+ it "must return a Python::Pickle::Instructions::Int with the decoded number" do
87
+ expect(subject.parse(io)).to eq(
88
+ [
89
+ Python::Pickle::Instructions::Int.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::Int.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_v0.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_v0.pkl') }
134
+
135
+ it "must return a Python::Pickle::Instructions::Float with the decoded number" do
136
+ expect(subject.parse(io)).to eq(
137
+ [
138
+ Python::Pickle::Instructions::Float.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::Float.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(:file) { File.join(fixtures_dir,'str_v0.pkl') }
159
+
160
+ it "must return a Python::Pickle::Instructions::String with the decoded number" do
161
+ expect(subject.parse(io)).to eq(
162
+ [
163
+ Python::Pickle::Instructions::String.new(string),
164
+ Python::Pickle::Instructions::Put.new(0),
165
+ Python::Pickle::Instructions::STOP
166
+ ]
167
+ )
168
+ end
169
+
170
+ context "and when a block is given" do
171
+ it "must yield each parsed instruction" do
172
+ expect {|b|
173
+ subject.parse(io,&b)
174
+ }.to yield_successive_args(
175
+ Python::Pickle::Instructions::String.new(string),
176
+ Python::Pickle::Instructions::Put.new(0),
177
+ Python::Pickle::Instructions::STOP
178
+ )
179
+ end
180
+ end
181
+ end
182
+
183
+ context "and it contains a string with backslash-escaped characters" do
184
+ let(:string) { "ABC\t\n\r\\'\"" }
185
+ let(:file) { File.join(fixtures_dir,'escaped_str_v0.pkl') }
186
+
187
+ it "must return a Python::Pickle::Instructions::String with the decoded number" do
188
+ expect(subject.parse(io)).to eq(
189
+ [
190
+ Python::Pickle::Instructions::String.new(string),
191
+ Python::Pickle::Instructions::Put.new(0),
192
+ Python::Pickle::Instructions::STOP
193
+ ]
194
+ )
195
+ end
196
+
197
+ context "and when a block is given" do
198
+ it "must yield each parsed instruction" do
199
+ expect {|b|
200
+ subject.parse(io,&b)
201
+ }.to yield_successive_args(
202
+ Python::Pickle::Instructions::String.new(string),
203
+ Python::Pickle::Instructions::Put.new(0),
204
+ Python::Pickle::Instructions::STOP
205
+ )
206
+ end
207
+ end
208
+ end
209
+
210
+ context "and it contains a string with hex-escaped characters" do
211
+ let(:string) { (0..255).map(&:chr).join }
212
+ let(:file) { File.join(fixtures_dir,'bin_str_v0.pkl') }
213
+
214
+ it "must return a Python::Pickle::Instructions::String with the decoded number" do
215
+ expect(subject.parse(io)).to eq(
216
+ [
217
+ Python::Pickle::Instructions::String.new(string),
218
+ Python::Pickle::Instructions::Put.new(0),
219
+ Python::Pickle::Instructions::STOP
220
+ ]
221
+ )
222
+ end
223
+
224
+ context "and when a block is given" do
225
+ it "must yield each parsed instruction" do
226
+ expect {|b|
227
+ subject.parse(io,&b)
228
+ }.to yield_successive_args(
229
+ Python::Pickle::Instructions::String.new(string),
230
+ Python::Pickle::Instructions::Put.new(0),
231
+ Python::Pickle::Instructions::STOP
232
+ )
233
+ end
234
+ end
235
+ end
236
+
237
+ context "and it contains a UTF string" do
238
+ let(:string) { "ABC\u265E\u265F\u{1F600}" }
239
+ let(:file) { File.join(fixtures_dir,'unicode_str_v0.pkl') }
240
+
241
+ it "must return a Python::Pickle::Instructions::String with the decoded number" do
242
+ expect(subject.parse(io)).to eq(
243
+ [
244
+ Python::Pickle::Instructions::String.new(string),
245
+ Python::Pickle::Instructions::Put.new(0),
246
+ Python::Pickle::Instructions::STOP
247
+ ]
248
+ )
249
+ end
250
+
251
+ context "and when a block is given" do
252
+ it "must yield each parsed instruction" do
253
+ expect {|b|
254
+ subject.parse(io,&b)
255
+ }.to yield_successive_args(
256
+ Python::Pickle::Instructions::String.new(string),
257
+ Python::Pickle::Instructions::Put.new(0),
258
+ Python::Pickle::Instructions::STOP
259
+ )
260
+ end
261
+ end
262
+ end
263
+
264
+ context "and it contains a list type" do
265
+ let(:file) { File.join(fixtures_dir,'list_v0.pkl') }
266
+
267
+ it "must return an Array of parsed instructions" do
268
+ expect(subject.parse(io)).to eq(
269
+ [
270
+ Python::Pickle::Instructions::MARK,
271
+ Python::Pickle::Instructions::LIST,
272
+ Python::Pickle::Instructions::Put.new(0),
273
+ Python::Pickle::Instructions::NONE,
274
+ Python::Pickle::Instructions::APPEND,
275
+ Python::Pickle::Instructions::Int.new(true),
276
+ Python::Pickle::Instructions::APPEND,
277
+ Python::Pickle::Instructions::Int.new(false),
278
+ Python::Pickle::Instructions::APPEND,
279
+ Python::Pickle::Instructions::Int.new(42),
280
+ Python::Pickle::Instructions::APPEND,
281
+ Python::Pickle::Instructions::String.new("ABC"),
282
+ Python::Pickle::Instructions::Put.new(1),
283
+ Python::Pickle::Instructions::APPEND,
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::MARK,
295
+ Python::Pickle::Instructions::LIST,
296
+ Python::Pickle::Instructions::Put.new(0),
297
+ Python::Pickle::Instructions::NONE,
298
+ Python::Pickle::Instructions::APPEND,
299
+ Python::Pickle::Instructions::Int.new(true),
300
+ Python::Pickle::Instructions::APPEND,
301
+ Python::Pickle::Instructions::Int.new(false),
302
+ Python::Pickle::Instructions::APPEND,
303
+ Python::Pickle::Instructions::Int.new(42),
304
+ Python::Pickle::Instructions::APPEND,
305
+ Python::Pickle::Instructions::String.new("ABC"),
306
+ Python::Pickle::Instructions::Put.new(1),
307
+ Python::Pickle::Instructions::APPEND,
308
+ Python::Pickle::Instructions::STOP
309
+ )
310
+ end
311
+ end
312
+ end
313
+
314
+ context "and it contains a dict type" do
315
+ let(:file) { File.join(fixtures_dir,'dict_v0.pkl') }
316
+
317
+ it "must return an Array of parsed instructions" do
318
+ expect(subject.parse(io)).to eq(
319
+ [
320
+ Python::Pickle::Instructions::MARK,
321
+ Python::Pickle::Instructions::DICT,
322
+ Python::Pickle::Instructions::Put.new(0),
323
+ Python::Pickle::Instructions::String.new("foo"),
324
+ Python::Pickle::Instructions::Put.new(1),
325
+ Python::Pickle::Instructions::String.new("bar"),
326
+ Python::Pickle::Instructions::Put.new(2),
327
+ Python::Pickle::Instructions::SETITEM,
328
+ Python::Pickle::Instructions::STOP
329
+ ]
330
+ )
331
+ end
332
+
333
+ context "and when a block is given" do
334
+ it "must yield each parsed instruction" do
335
+ expect {|b|
336
+ subject.parse(io,&b)
337
+ }.to yield_successive_args(
338
+ Python::Pickle::Instructions::MARK,
339
+ Python::Pickle::Instructions::DICT,
340
+ Python::Pickle::Instructions::Put.new(0),
341
+ Python::Pickle::Instructions::String.new("foo"),
342
+ Python::Pickle::Instructions::Put.new(1),
343
+ Python::Pickle::Instructions::String.new("bar"),
344
+ Python::Pickle::Instructions::Put.new(2),
345
+ Python::Pickle::Instructions::SETITEM,
346
+ Python::Pickle::Instructions::STOP
347
+ )
348
+ end
349
+ end
350
+ end
351
+
352
+ context "and it contains an object type" do
353
+ let(:file) { File.join(fixtures_dir,'object_v0.pkl') }
354
+
355
+ it "must return an Array of parsed instructions" do
356
+ expect(subject.parse(io)).to eq(
357
+ [
358
+ Python::Pickle::Instructions::Global.new('copy_reg','_reconstructor'),
359
+ Python::Pickle::Instructions::Put.new(0),
360
+ Python::Pickle::Instructions::MARK,
361
+ Python::Pickle::Instructions::Global.new('__main__','MyClass'),
362
+ Python::Pickle::Instructions::Put.new(1),
363
+ Python::Pickle::Instructions::Global.new('__builtin__','object'),
364
+ Python::Pickle::Instructions::Put.new(2),
365
+ Python::Pickle::Instructions::NONE,
366
+ Python::Pickle::Instructions::TUPLE,
367
+ Python::Pickle::Instructions::Put.new(3),
368
+ Python::Pickle::Instructions::REDUCE,
369
+ Python::Pickle::Instructions::Put.new(4),
370
+ Python::Pickle::Instructions::MARK,
371
+ Python::Pickle::Instructions::DICT,
372
+ Python::Pickle::Instructions::Put.new(5),
373
+ Python::Pickle::Instructions::String.new('y'),
374
+ Python::Pickle::Instructions::Put.new(6),
375
+ Python::Pickle::Instructions::Int.new(66),
376
+ Python::Pickle::Instructions::SETITEM,
377
+ Python::Pickle::Instructions::String.new('x'),
378
+ Python::Pickle::Instructions::Put.new(7),
379
+ Python::Pickle::Instructions::Int.new(65),
380
+ Python::Pickle::Instructions::SETITEM,
381
+ Python::Pickle::Instructions::BUILD,
382
+ Python::Pickle::Instructions::STOP
383
+ ]
384
+ )
385
+ end
386
+
387
+ context "and when a block is given" do
388
+ it "must yield each parsed instruction" do
389
+ expect {|b|
390
+ subject.parse(io,&b)
391
+ }.to yield_successive_args(
392
+ Python::Pickle::Instructions::Global.new('copy_reg','_reconstructor'),
393
+ Python::Pickle::Instructions::Put.new(0),
394
+ Python::Pickle::Instructions::MARK,
395
+ Python::Pickle::Instructions::Global.new('__main__','MyClass'),
396
+ Python::Pickle::Instructions::Put.new(1),
397
+ Python::Pickle::Instructions::Global.new('__builtin__','object'),
398
+ Python::Pickle::Instructions::Put.new(2),
399
+ Python::Pickle::Instructions::NONE,
400
+ Python::Pickle::Instructions::TUPLE,
401
+ Python::Pickle::Instructions::Put.new(3),
402
+ Python::Pickle::Instructions::REDUCE,
403
+ Python::Pickle::Instructions::Put.new(4),
404
+ Python::Pickle::Instructions::MARK,
405
+ Python::Pickle::Instructions::DICT,
406
+ Python::Pickle::Instructions::Put.new(5),
407
+ Python::Pickle::Instructions::String.new('y'),
408
+ Python::Pickle::Instructions::Put.new(6),
409
+ Python::Pickle::Instructions::Int.new(66),
410
+ Python::Pickle::Instructions::SETITEM,
411
+ Python::Pickle::Instructions::String.new('x'),
412
+ Python::Pickle::Instructions::Put.new(7),
413
+ Python::Pickle::Instructions::Int.new(65),
414
+ Python::Pickle::Instructions::SETITEM,
415
+ Python::Pickle::Instructions::BUILD,
416
+ Python::Pickle::Instructions::STOP
417
+ )
418
+ end
419
+ end
420
+ end
421
+
422
+ context "and it contains a bytearray type" do
423
+ let(:file) { File.join(fixtures_dir,'bytearray_v0.pkl') }
424
+
425
+ it "must return an Array of parsed instructions" do
426
+ expect(subject.parse(io)).to eq(
427
+ [
428
+ Python::Pickle::Instructions::Global.new('__builtin__','bytearray'),
429
+ Python::Pickle::Instructions::Put.new(0),
430
+ Python::Pickle::Instructions::MARK,
431
+ Python::Pickle::Instructions::String.new('ABC'),
432
+ Python::Pickle::Instructions::Put.new(1),
433
+ Python::Pickle::Instructions::String.new('latin-1'),
434
+ Python::Pickle::Instructions::Put.new(2),
435
+ Python::Pickle::Instructions::TUPLE,
436
+ Python::Pickle::Instructions::Put.new(3),
437
+ Python::Pickle::Instructions::REDUCE,
438
+ Python::Pickle::Instructions::Put.new(4),
439
+ Python::Pickle::Instructions::STOP
440
+ ]
441
+ )
442
+ end
443
+
444
+ context "and when a block is given" do
445
+ it "must yield each parsed instruction" do
446
+ expect {|b|
447
+ subject.parse(io,&b)
448
+ }.to yield_successive_args(
449
+ Python::Pickle::Instructions::Global.new('__builtin__','bytearray'),
450
+ Python::Pickle::Instructions::Put.new(0),
451
+ Python::Pickle::Instructions::MARK,
452
+ Python::Pickle::Instructions::String.new('ABC'),
453
+ Python::Pickle::Instructions::Put.new(1),
454
+ Python::Pickle::Instructions::String.new('latin-1'),
455
+ Python::Pickle::Instructions::Put.new(2),
456
+ Python::Pickle::Instructions::TUPLE,
457
+ Python::Pickle::Instructions::Put.new(3),
458
+ Python::Pickle::Instructions::REDUCE,
459
+ Python::Pickle::Instructions::Put.new(4),
460
+ Python::Pickle::Instructions::STOP
461
+ )
462
+ end
463
+ end
464
+ end
465
+ end
466
+ end
467
+ end