python-pickle 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog.md +12 -0
- data/README.md +2 -1
- data/lib/python/pickle/deserializer.rb +142 -80
- data/lib/python/pickle/instructions/bin_persid.rb +31 -0
- data/lib/python/pickle/instructions/global.rb +11 -41
- data/lib/python/pickle/instructions/has_namespace_and_name.rb +61 -0
- data/lib/python/pickle/instructions/inst.rb +34 -0
- data/lib/python/pickle/instructions/next_buffer.rb +5 -1
- data/lib/python/pickle/instructions/obj.rb +30 -0
- data/lib/python/pickle/instructions/persid.rb +31 -0
- data/lib/python/pickle/instructions/readonly_buffer.rb +4 -0
- data/lib/python/pickle/instructions.rb +64 -0
- data/lib/python/pickle/protocol0.rb +313 -68
- data/lib/python/pickle/protocol1.rb +225 -93
- data/lib/python/pickle/protocol2.rb +205 -124
- data/lib/python/pickle/protocol3.rb +92 -123
- data/lib/python/pickle/protocol4.rb +188 -165
- data/lib/python/pickle/protocol5.rb +98 -166
- data/lib/python/pickle/version.rb +1 -1
- data/lib/python/pickle.rb +38 -32
- data/spec/deserializer_spec.rb +308 -0
- data/spec/fixtures/set_v0.pkl +11 -0
- data/spec/fixtures/set_v1.pkl +0 -0
- data/spec/fixtures/set_v2.pkl +0 -0
- data/spec/fixtures/set_v3.pkl +0 -0
- data/spec/fixtures/set_v4.pkl +0 -0
- data/spec/fixtures/set_v5.pkl +0 -0
- data/spec/generate_pickles2.py +1 -0
- data/spec/generate_pickles3.py +1 -0
- data/spec/integration/load/protocol0_spec.rb +10 -0
- data/spec/integration/load/protocol1_spec.rb +10 -0
- data/spec/integration/load/protocol2_spec.rb +10 -0
- data/spec/integration/load/protocol3_spec.rb +10 -0
- data/spec/integration/load/protocol4_spec.rb +10 -0
- data/spec/integration/load/protocol5_spec.rb +10 -0
- data/spec/protocol0_read_instruction_examples.rb +44 -0
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8fe6820a4b047c2e2eb027c3dbe88b5b8d7e51d201864e9e7b726cb566d687d
|
4
|
+
data.tar.gz: b1b66aa3811a277b63f643eb4c2968bab268ab7c22aa061713c1555f8d66162b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b44f4bddc1cfcbdfc4d7fda78a30b9982c268701109bbb92da050c1c226a006859f3a9dacd872c9362bb8c237723b7d8401dcb28626ad9a2e49b83af3c8c32d1
|
7
|
+
data.tar.gz: 8301c1d66a60a6cb7468f32a6f801d3b0ed699d771af7625eba034aafef762815201cb12b9484976248abe84cc32278647991e1cbb76745ebea84994e5ff2f2a
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
### 0.2.0 / 2023-02-19
|
2
|
+
|
3
|
+
* Added missing support for deserializing Python `set` objects.
|
4
|
+
* Added missing support for out-of-band buffers.
|
5
|
+
* Added partial support for parsing the `PERSID` and `BINPERSID` instructions.
|
6
|
+
* Added missing support for deserializing the `INST` and `OBJ` instructions.
|
7
|
+
* Added missing support for deserializing the `EMPTY_SET`, `FROZENSET`, and
|
8
|
+
`ADDITEMS` Pickle instructions.
|
9
|
+
* Added missing support for deserializing the `NEXT_BUFFER` and
|
10
|
+
`READONLY_BUFFER` Pickle instructions.
|
11
|
+
* Map `__builtin__.set` and `builtins.set` to Ruby's `Set` class.
|
12
|
+
|
1
13
|
### 0.1.0 / 2023-02-18
|
2
14
|
|
3
15
|
* Changed {Python::Pickle.dump} to raise a `NotImplementedError` exception.
|
data/README.md
CHANGED
@@ -21,10 +21,11 @@ format.
|
|
21
21
|
and protocol 5.
|
22
22
|
* Can parse both Python 2 and Python 3 Pickled data.
|
23
23
|
* Supports deserializing Python `None`, `True`, `False`, `int`, `str`, `tuple`,
|
24
|
-
`list`, `bytearray`, and other objects.
|
24
|
+
`set`, `list`, `bytearray`, and other objects.
|
25
25
|
* Supports mapping Python extension codes to Ruby classes.
|
26
26
|
* Supports mapping Python functions to Ruby methods.
|
27
27
|
* Supports mapping Python classes to Ruby classes.
|
28
|
+
* Supports out-of-band buffers.
|
28
29
|
|
29
30
|
## TODO
|
30
31
|
|
@@ -2,63 +2,10 @@ require 'python/pickle/py_class'
|
|
2
2
|
require 'python/pickle/py_object'
|
3
3
|
require 'python/pickle/tuple'
|
4
4
|
require 'python/pickle/byte_array'
|
5
|
+
require 'python/pickle/instructions'
|
5
6
|
require 'python/pickle/exceptions'
|
6
7
|
|
7
|
-
require '
|
8
|
-
require 'python/pickle/instructions/frame'
|
9
|
-
require 'python/pickle/instructions/get'
|
10
|
-
require 'python/pickle/instructions/bin_get'
|
11
|
-
require 'python/pickle/instructions/long_bin_get'
|
12
|
-
require 'python/pickle/instructions/mark'
|
13
|
-
require 'python/pickle/instructions/pop_mark'
|
14
|
-
require 'python/pickle/instructions/dup'
|
15
|
-
require 'python/pickle/instructions/put'
|
16
|
-
require 'python/pickle/instructions/bin_put'
|
17
|
-
require 'python/pickle/instructions/pop'
|
18
|
-
require 'python/pickle/instructions/memoize'
|
19
|
-
require 'python/pickle/instructions/ext1'
|
20
|
-
require 'python/pickle/instructions/ext2'
|
21
|
-
require 'python/pickle/instructions/ext4'
|
22
|
-
require 'python/pickle/instructions/none'
|
23
|
-
require 'python/pickle/instructions/new_true'
|
24
|
-
require 'python/pickle/instructions/new_false'
|
25
|
-
require 'python/pickle/instructions/float'
|
26
|
-
require 'python/pickle/instructions/bin_float'
|
27
|
-
require 'python/pickle/instructions/int'
|
28
|
-
require 'python/pickle/instructions/bin_int1'
|
29
|
-
require 'python/pickle/instructions/long'
|
30
|
-
require 'python/pickle/instructions/long1'
|
31
|
-
require 'python/pickle/instructions/long4'
|
32
|
-
require 'python/pickle/instructions/bin_bytes'
|
33
|
-
require 'python/pickle/instructions/short_bin_bytes'
|
34
|
-
require 'python/pickle/instructions/bin_bytes8'
|
35
|
-
require 'python/pickle/instructions/string'
|
36
|
-
require 'python/pickle/instructions/bin_string'
|
37
|
-
require 'python/pickle/instructions/short_bin_string'
|
38
|
-
require 'python/pickle/instructions/bin_unicode'
|
39
|
-
require 'python/pickle/instructions/short_bin_unicode'
|
40
|
-
require 'python/pickle/instructions/bin_unicode8'
|
41
|
-
require 'python/pickle/instructions/byte_array8'
|
42
|
-
require 'python/pickle/instructions/empty_list'
|
43
|
-
require 'python/pickle/instructions/empty_tuple'
|
44
|
-
require 'python/pickle/instructions/tuple'
|
45
|
-
require 'python/pickle/instructions/empty_dict'
|
46
|
-
require 'python/pickle/instructions/append'
|
47
|
-
require 'python/pickle/instructions/appends'
|
48
|
-
require 'python/pickle/instructions/list'
|
49
|
-
require 'python/pickle/instructions/tuple1'
|
50
|
-
require 'python/pickle/instructions/tuple2'
|
51
|
-
require 'python/pickle/instructions/tuple3'
|
52
|
-
require 'python/pickle/instructions/dict'
|
53
|
-
require 'python/pickle/instructions/global'
|
54
|
-
require 'python/pickle/instructions/stack_global'
|
55
|
-
require 'python/pickle/instructions/new_obj'
|
56
|
-
require 'python/pickle/instructions/new_obj_ex'
|
57
|
-
require 'python/pickle/instructions/reduce'
|
58
|
-
require 'python/pickle/instructions/build'
|
59
|
-
require 'python/pickle/instructions/set_item'
|
60
|
-
require 'python/pickle/instructions/set_items'
|
61
|
-
require 'python/pickle/instructions/stop'
|
8
|
+
require 'set'
|
62
9
|
|
63
10
|
module Python
|
64
11
|
module Pickle
|
@@ -94,6 +41,11 @@ module Python
|
|
94
41
|
# @return [Hash{Integer => Object}]
|
95
42
|
attr_reader :extensions
|
96
43
|
|
44
|
+
# An enumerable list of out-of-band buffers.
|
45
|
+
#
|
46
|
+
# @return [Enumerator, nil]
|
47
|
+
attr_reader :buffers
|
48
|
+
|
97
49
|
# The Python `object` class.
|
98
50
|
OBJECT_CLASS = PyClass.new('__builtins__','object')
|
99
51
|
|
@@ -107,7 +59,10 @@ module Python
|
|
107
59
|
# An optional mapping of custom Python constant names to Ruby classes
|
108
60
|
# or methods.
|
109
61
|
#
|
110
|
-
|
62
|
+
# @param [Enumerable, nil] buffers
|
63
|
+
# An enumerable list of out-of-band buffers.
|
64
|
+
#
|
65
|
+
def initialize(constants: nil, extensions: nil, buffers: nil)
|
111
66
|
@meta_stack = []
|
112
67
|
@stack = []
|
113
68
|
@memo = []
|
@@ -120,12 +75,14 @@ module Python
|
|
120
75
|
|
121
76
|
'__builtin__' => {
|
122
77
|
'object' => OBJECT_CLASS,
|
78
|
+
'set' => Set,
|
123
79
|
'bytearray' => ByteArray
|
124
80
|
},
|
125
81
|
|
126
82
|
# Python 3.x
|
127
83
|
'builtins' => {
|
128
84
|
'object' => OBJECT_CLASS,
|
85
|
+
'set' => Set,
|
129
86
|
'bytearray' => ByteArray
|
130
87
|
}
|
131
88
|
}
|
@@ -133,6 +90,8 @@ module Python
|
|
133
90
|
|
134
91
|
@extensions = {}
|
135
92
|
@extensions.merge!(extensions) if extensions
|
93
|
+
|
94
|
+
@buffers = buffers.each if buffers
|
136
95
|
end
|
137
96
|
|
138
97
|
#
|
@@ -199,26 +158,33 @@ module Python
|
|
199
158
|
Instructions::ShortBinUnicode,
|
200
159
|
Instructions::BinUnicode8
|
201
160
|
@stack.push(instruction.value)
|
202
|
-
when Instructions::ByteArray8
|
203
|
-
when Instructions::EMPTY_LIST
|
204
|
-
when Instructions::EMPTY_TUPLE
|
205
|
-
when Instructions::TUPLE
|
206
|
-
when Instructions::EMPTY_DICT
|
207
|
-
when Instructions::
|
208
|
-
when Instructions::
|
209
|
-
when Instructions::
|
210
|
-
when Instructions::
|
211
|
-
when Instructions::
|
212
|
-
when Instructions::
|
213
|
-
when Instructions::
|
214
|
-
when Instructions::
|
215
|
-
when Instructions::
|
216
|
-
when Instructions::
|
217
|
-
when Instructions::
|
218
|
-
when Instructions::
|
219
|
-
when Instructions::
|
220
|
-
when Instructions::
|
221
|
-
when Instructions::
|
161
|
+
when Instructions::ByteArray8 then execute_byte_array8(instruction)
|
162
|
+
when Instructions::EMPTY_LIST then execute_empty_list
|
163
|
+
when Instructions::EMPTY_TUPLE then execute_empty_tuple
|
164
|
+
when Instructions::TUPLE then execute_tuple
|
165
|
+
when Instructions::EMPTY_DICT then execute_empty_dict
|
166
|
+
when Instructions::EMPTY_SET then execute_empty_set
|
167
|
+
when Instructions::FROZENSET then execute_frozenset
|
168
|
+
when Instructions::APPEND then execute_append
|
169
|
+
when Instructions::APPENDS then execute_appends
|
170
|
+
when Instructions::ADDITEMS then execute_additems
|
171
|
+
when Instructions::LIST then execute_list
|
172
|
+
when Instructions::TUPLE1 then execute_tuple1
|
173
|
+
when Instructions::TUPLE2 then execute_tuple2
|
174
|
+
when Instructions::TUPLE3 then execute_tuple3
|
175
|
+
when Instructions::DICT then execute_dict
|
176
|
+
when Instructions::Global then execute_global(instruction)
|
177
|
+
when Instructions::STACK_GLOBAL then execute_stack_global
|
178
|
+
when Instructions::Inst then execute_inst(instruction)
|
179
|
+
when Instructions::OBJ then execute_obj
|
180
|
+
when Instructions::NEWOBJ then execute_newobj
|
181
|
+
when Instructions::NEWOBJ_EX then execute_newobj_ex
|
182
|
+
when Instructions::REDUCE then execute_reduce
|
183
|
+
when Instructions::BUILD then execute_build
|
184
|
+
when Instructions::SETITEM then execute_setitem
|
185
|
+
when Instructions::SETITEMS then execute_setitems
|
186
|
+
when Instructions::NEXT_BUFFER then execute_next_buffer
|
187
|
+
when Instructions::READONLY_BUFFER then execute_readonly_buffer
|
222
188
|
when Instructions::STOP
|
223
189
|
return :halt, @stack.pop
|
224
190
|
else
|
@@ -361,6 +327,29 @@ module Python
|
|
361
327
|
@stack.push({})
|
362
328
|
end
|
363
329
|
|
330
|
+
#
|
331
|
+
# Executes an `EMPTY_SET` instruction.
|
332
|
+
#
|
333
|
+
# @since 0.2.0
|
334
|
+
#
|
335
|
+
def execute_empty_set
|
336
|
+
@stack.push(Set.new)
|
337
|
+
end
|
338
|
+
|
339
|
+
#
|
340
|
+
# Executes a `FROZENSET` instruction.
|
341
|
+
#
|
342
|
+
# @since 0.2.0
|
343
|
+
#
|
344
|
+
def execute_frozenset
|
345
|
+
items = pop_meta_stack
|
346
|
+
|
347
|
+
set = Set.new(items)
|
348
|
+
set.freeze
|
349
|
+
|
350
|
+
@stack.push(set)
|
351
|
+
end
|
352
|
+
|
364
353
|
#
|
365
354
|
# Executes an `APPEND` instruction.
|
366
355
|
#
|
@@ -368,11 +357,11 @@ module Python
|
|
368
357
|
item = @stack.pop
|
369
358
|
list = @stack.last
|
370
359
|
|
371
|
-
unless list.kind_of?(Array)
|
360
|
+
unless (list.kind_of?(Array) || list.kind_of?(Set))
|
372
361
|
raise(DeserializationError,"cannot append element #{item.inspect} onto a non-Array: #{list.inspect}")
|
373
362
|
end
|
374
363
|
|
375
|
-
list
|
364
|
+
list << item
|
376
365
|
end
|
377
366
|
|
378
367
|
#
|
@@ -382,11 +371,34 @@ module Python
|
|
382
371
|
items = pop_meta_stack
|
383
372
|
list = @stack.last
|
384
373
|
|
385
|
-
|
374
|
+
case list
|
375
|
+
when Array
|
376
|
+
list.concat(items)
|
377
|
+
when Set
|
378
|
+
items.each do |item|
|
379
|
+
list << item
|
380
|
+
end
|
381
|
+
else
|
386
382
|
raise(DeserializationError,"cannot append elements #{items.inspect} onto a non-Array: #{list.inspect}")
|
387
383
|
end
|
384
|
+
end
|
385
|
+
|
386
|
+
#
|
387
|
+
# Executes a `ADDITEMS` instruction.
|
388
|
+
#
|
389
|
+
# @since 0.2.0
|
390
|
+
#
|
391
|
+
def execute_additems
|
392
|
+
items = pop_meta_stack
|
393
|
+
set = @stack.last
|
394
|
+
|
395
|
+
unless set.kind_of?(Set)
|
396
|
+
raise(DeserializationError,"cannot add items #{items.inspect} to a non-Set object: #{set.inspect}")
|
397
|
+
end
|
388
398
|
|
389
|
-
|
399
|
+
items.each do |item|
|
400
|
+
set << item
|
401
|
+
end
|
390
402
|
end
|
391
403
|
|
392
404
|
#
|
@@ -500,6 +512,33 @@ module Python
|
|
500
512
|
@stack.push(constant)
|
501
513
|
end
|
502
514
|
|
515
|
+
#
|
516
|
+
# Executes an `INST` instruction.
|
517
|
+
#
|
518
|
+
# @since 0.2.0
|
519
|
+
#
|
520
|
+
def execute_inst(instruction)
|
521
|
+
namespace = instruction.namespace
|
522
|
+
name = instruction.name
|
523
|
+
py_class = resolve_constant(namespace,name)
|
524
|
+
args = pop_meta_stack
|
525
|
+
py_object = py_class.new(*args)
|
526
|
+
|
527
|
+
@stack.push(py_object)
|
528
|
+
end
|
529
|
+
|
530
|
+
#
|
531
|
+
# Executes an `OBJ` instruction.
|
532
|
+
#
|
533
|
+
# @since 0.2.0
|
534
|
+
#
|
535
|
+
def execute_obj
|
536
|
+
py_class, *args = pop_meta_stack
|
537
|
+
py_object = py_class.new(*args)
|
538
|
+
|
539
|
+
@stack.push(py_object)
|
540
|
+
end
|
541
|
+
|
503
542
|
#
|
504
543
|
# Executes a `NEWOBJ` instruction.
|
505
544
|
#
|
@@ -590,6 +629,29 @@ module Python
|
|
590
629
|
end
|
591
630
|
end
|
592
631
|
|
632
|
+
#
|
633
|
+
# Executes a `NEXT_BUFFER` instruction.
|
634
|
+
#
|
635
|
+
# @since 0.2.0
|
636
|
+
#
|
637
|
+
def execute_next_buffer
|
638
|
+
unless @buffers
|
639
|
+
raise(DeserializationError,"pickle stream includes a NEXT_BUFFER instruction, but no buffers were provided")
|
640
|
+
end
|
641
|
+
|
642
|
+
@stack.push(@buffers.next)
|
643
|
+
end
|
644
|
+
|
645
|
+
#
|
646
|
+
# Executes a `READONLY_BUFFER` instruction.
|
647
|
+
#
|
648
|
+
# @since 0.2.0
|
649
|
+
#
|
650
|
+
def execute_readonly_buffer
|
651
|
+
buffer = @stack.last
|
652
|
+
buffer.freeze
|
653
|
+
end
|
654
|
+
|
593
655
|
end
|
594
656
|
end
|
595
657
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'python/pickle/instruction'
|
2
|
+
require 'python/pickle/instructions/has_value'
|
3
|
+
|
4
|
+
module Python
|
5
|
+
module Pickle
|
6
|
+
module Instructions
|
7
|
+
#
|
8
|
+
# Represents the `BINPERSID` instruction.
|
9
|
+
#
|
10
|
+
# @note introduced in protocol 0.
|
11
|
+
#
|
12
|
+
# @since 0.2.0
|
13
|
+
#
|
14
|
+
class BinPersID < Instruction
|
15
|
+
|
16
|
+
#
|
17
|
+
# Initializes the `BINPERSID` instruction.
|
18
|
+
#
|
19
|
+
def initialize
|
20
|
+
super(:BINPERSID)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
# Represents the `BINPERSID` instruction.
|
26
|
+
#
|
27
|
+
# @since 0.2.0
|
28
|
+
BINPERSID = BinPersID.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,59 +1,29 @@
|
|
1
1
|
require 'python/pickle/instruction'
|
2
|
-
require 'python/pickle/instructions/
|
2
|
+
require 'python/pickle/instructions/has_namespace_and_name'
|
3
3
|
|
4
4
|
module Python
|
5
5
|
module Pickle
|
6
6
|
module Instructions
|
7
|
+
#
|
8
|
+
# Represents the `GLOBAL` instruction.
|
9
|
+
#
|
10
|
+
# @note introduced in protocol 0.
|
11
|
+
#
|
7
12
|
class Global < Instruction
|
8
13
|
|
9
|
-
|
10
|
-
#
|
11
|
-
# @return [String]
|
12
|
-
attr_reader :namespace
|
13
|
-
|
14
|
-
# The global object name.
|
15
|
-
#
|
16
|
-
# @return [String]
|
17
|
-
attr_reader :name
|
14
|
+
include HasNamespaceAndName
|
18
15
|
|
19
16
|
#
|
20
|
-
# Initializes
|
17
|
+
# Initializes a `GLOBAL` instruction.
|
21
18
|
#
|
22
19
|
# @param [String] namespace
|
23
|
-
# The namespace name for the
|
20
|
+
# The namespace name for the constant.
|
24
21
|
#
|
25
22
|
# @param [String] name
|
26
|
-
# The name of the
|
23
|
+
# The name of the constant.
|
27
24
|
#
|
28
25
|
def initialize(namespace,name)
|
29
|
-
super(:GLOBAL)
|
30
|
-
|
31
|
-
@namespace = namespace
|
32
|
-
@name = name
|
33
|
-
end
|
34
|
-
|
35
|
-
#
|
36
|
-
# Compares the `GLOBAL` instruction to another instruction.
|
37
|
-
#
|
38
|
-
# @param [Instruction] other
|
39
|
-
# The other instruction to compare against.
|
40
|
-
#
|
41
|
-
# @return [Boolean]
|
42
|
-
# Indicates whether the other instruction matches this one.
|
43
|
-
#
|
44
|
-
def ==(other)
|
45
|
-
super(other) && \
|
46
|
-
(@namespace == other.namespace) && \
|
47
|
-
(@name == other.name)
|
48
|
-
end
|
49
|
-
|
50
|
-
#
|
51
|
-
# Converts the `GLOBAL` instructions to a String.
|
52
|
-
#
|
53
|
-
# @return [String]
|
54
|
-
#
|
55
|
-
def to_s
|
56
|
-
"#{super} #{@namespace}.#{@name}"
|
26
|
+
super(:GLOBAL,namespace,name)
|
57
27
|
end
|
58
28
|
|
59
29
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Python
|
2
|
+
module Pickle
|
3
|
+
module Instructions
|
4
|
+
module HasNamespaceAndName
|
5
|
+
# The constant's namespace.
|
6
|
+
#
|
7
|
+
# @return [String]
|
8
|
+
attr_reader :namespace
|
9
|
+
|
10
|
+
# The constant name.
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
attr_reader :name
|
14
|
+
|
15
|
+
#
|
16
|
+
# Initializes the instruction.
|
17
|
+
#
|
18
|
+
# @param [Symbol] opcode
|
19
|
+
# The instruction's opcode.
|
20
|
+
#
|
21
|
+
# @param [String] namespace
|
22
|
+
# The namespace name for the constant.
|
23
|
+
#
|
24
|
+
# @param [String] name
|
25
|
+
# The name of the constant.
|
26
|
+
#
|
27
|
+
def initialize(opcode,namespace,name)
|
28
|
+
super(opcode)
|
29
|
+
|
30
|
+
@namespace = namespace
|
31
|
+
@name = name
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Compares the instruction to another instruction.
|
36
|
+
#
|
37
|
+
# @param [Instruction] other
|
38
|
+
# The other instruction to compare against.
|
39
|
+
#
|
40
|
+
# @return [Boolean]
|
41
|
+
# Indicates whether the other instruction matches this one.
|
42
|
+
#
|
43
|
+
def ==(other)
|
44
|
+
super(other) && \
|
45
|
+
(@namespace == other.namespace) && \
|
46
|
+
(@name == other.name)
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Converts the instructions to a String.
|
51
|
+
#
|
52
|
+
# @return [String]
|
53
|
+
#
|
54
|
+
def to_s
|
55
|
+
"#{super} #{@namespace}.#{@name}"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'python/pickle/instruction'
|
2
|
+
require 'python/pickle/instructions/has_namespace_and_name'
|
3
|
+
|
4
|
+
module Python
|
5
|
+
module Pickle
|
6
|
+
module Instructions
|
7
|
+
#
|
8
|
+
# Represents the `INST` instruction.
|
9
|
+
#
|
10
|
+
# @note introduced in protocol 0.
|
11
|
+
#
|
12
|
+
# @since 0.2.0
|
13
|
+
#
|
14
|
+
class Inst < Instruction
|
15
|
+
|
16
|
+
include HasNamespaceAndName
|
17
|
+
|
18
|
+
#
|
19
|
+
# Initializes a `INST` instruction.
|
20
|
+
#
|
21
|
+
# @param [String] namespace
|
22
|
+
# The namespace name for the constant.
|
23
|
+
#
|
24
|
+
# @param [String] name
|
25
|
+
# The name of the constant.
|
26
|
+
#
|
27
|
+
def initialize(namespace,name)
|
28
|
+
super(:INST,namespace,name)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -6,7 +6,9 @@ module Python
|
|
6
6
|
#
|
7
7
|
# Represents a pickle `NEXT_BUFFER` instruction.
|
8
8
|
#
|
9
|
-
# @note introduced in protocol
|
9
|
+
# @note introduced in protocol 5.
|
10
|
+
#
|
11
|
+
# @since 0.2.0
|
10
12
|
#
|
11
13
|
class NextBuffer < Instruction
|
12
14
|
|
@@ -20,6 +22,8 @@ module Python
|
|
20
22
|
end
|
21
23
|
|
22
24
|
# The `NEXT_BUFFER` instruction.
|
25
|
+
#
|
26
|
+
# @since 0.2.0
|
23
27
|
NEXT_BUFFER = NextBuffer.new
|
24
28
|
end
|
25
29
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'python/pickle/instruction'
|
2
|
+
|
3
|
+
module Python
|
4
|
+
module Pickle
|
5
|
+
module Instructions
|
6
|
+
#
|
7
|
+
# Represents a pickle `OBJ` instruction.
|
8
|
+
#
|
9
|
+
# @note introduced in protocol 0.
|
10
|
+
#
|
11
|
+
# @since 0.2.0
|
12
|
+
#
|
13
|
+
class Obj < Instruction
|
14
|
+
|
15
|
+
#
|
16
|
+
# Initializes the `OBJ` instruction.
|
17
|
+
#
|
18
|
+
def initialize
|
19
|
+
super(:OBJ)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
# The `OBJ` instruction.
|
25
|
+
#
|
26
|
+
# @since 0.2.0
|
27
|
+
OBJ = Obj.new
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'python/pickle/instruction'
|
2
|
+
require 'python/pickle/instructions/has_value'
|
3
|
+
|
4
|
+
module Python
|
5
|
+
module Pickle
|
6
|
+
module Instructions
|
7
|
+
#
|
8
|
+
# Represents the `PERSID` instruction.
|
9
|
+
#
|
10
|
+
# @note introduced in protocol 0.
|
11
|
+
#
|
12
|
+
# @since 0.2.0
|
13
|
+
#
|
14
|
+
class PersID < Instruction
|
15
|
+
|
16
|
+
include HasValue
|
17
|
+
|
18
|
+
#
|
19
|
+
# Initializes the `PERSID` instruction.
|
20
|
+
#
|
21
|
+
# @param [String] value
|
22
|
+
# The `PERSID` instruction's value.
|
23
|
+
#
|
24
|
+
def initialize(value)
|
25
|
+
super(:PERSID,value)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -8,6 +8,8 @@ module Python
|
|
8
8
|
#
|
9
9
|
# @note introduced in protocol 5.
|
10
10
|
#
|
11
|
+
# @since 0.2.0
|
12
|
+
#
|
11
13
|
class ReadonlyBuffer < Instruction
|
12
14
|
|
13
15
|
#
|
@@ -20,6 +22,8 @@ module Python
|
|
20
22
|
end
|
21
23
|
|
22
24
|
# The `READONLY_BUFFER` instruction.
|
25
|
+
#
|
26
|
+
# @since 0.2.0
|
23
27
|
READONLY_BUFFER = ReadonlyBuffer.new
|
24
28
|
end
|
25
29
|
end
|