python-pickle 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/ChangeLog.md +17 -0
- data/README.md +4 -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 +71 -39
- data/spec/deserializer_spec.rb +359 -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/pickle_spec.rb +61 -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,20 @@
|
|
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
|
+
|
13
|
+
### 0.1.0 / 2023-02-18
|
14
|
+
|
15
|
+
* Changed {Python::Pickle.dump} to raise a `NotImplementedError` exception.
|
16
|
+
* Fixed a typo in the method signature of {Python::Pickle.dump}.
|
17
|
+
|
1
18
|
### 0.1.0 / 2023-02-18
|
2
19
|
|
3
20
|
* Initial release:
|
data/README.md
CHANGED
@@ -20,9 +20,12 @@ format.
|
|
20
20
|
* Supports Pickle protocol 0, protocol 1, protocol 2, protocol 3, protocol 4,
|
21
21
|
and protocol 5.
|
22
22
|
* Can parse both Python 2 and Python 3 Pickled data.
|
23
|
-
* Supports deserializing Python `
|
23
|
+
* Supports deserializing Python `None`, `True`, `False`, `int`, `str`, `tuple`,
|
24
|
+
`set`, `list`, `bytearray`, and other objects.
|
25
|
+
* Supports mapping Python extension codes to Ruby classes.
|
24
26
|
* Supports mapping Python functions to Ruby methods.
|
25
27
|
* Supports mapping Python classes to Ruby classes.
|
28
|
+
* Supports out-of-band buffers.
|
26
29
|
|
27
30
|
## TODO
|
28
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
|