python-pickle 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea86f43e4b83bacac94635b88e2c9deeb6eb4aaa553f1770e4943554389422fc
4
- data.tar.gz: 973327ecbd8f2c1df7d0ac10f37d76628745e00da9317ab655a9f12644fef441
3
+ metadata.gz: c18d8d36ae1a85dd7dbdbe13bf136de10bd2d30ddaab523bace2042f1ab3c784
4
+ data.tar.gz: ad04252dfd4cbcb7e8d80b61e92a1d7439ce256ccfda97b9b3a202e8b3225415
5
5
  SHA512:
6
- metadata.gz: 8b95a73ff2ebfba7c9ca97648df7c7b3b6be14df61e0e6f4943e3e263a5f300696e79d8cf57aacc7bd9d572bcf3c00a5ec88162e1dd8cc627617afe01414499d
7
- data.tar.gz: 73a9a106cfa346d3d74835cf9369732f041fdb2faafdb8a030f1e9ec6b58831e8b7c8aee3a05bec687d11d2d4ea9d48a00d4fcf164f0c686eb84c1248b15f056
6
+ metadata.gz: 4f64f303012885b2acb6b3ee56527a10a109cac5a9b5f938fea2817552b43bbefad6b5d460f299bb5909388b4eeff722d69b2cba9342e1e8a1c460e3c070a08b
7
+ data.tar.gz: cc598296cf863810512869805f53b17d2a16bffc9bc09afcb8e35e21fcf1d50b53026151bbd28b687820523618e5dc66a52b42e416281d79ab95a0d6fd636d2a
data/ChangeLog.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ### 0.1.0 / 2023-02-18
2
2
 
3
+ * Changed {Python::Pickle.dump} to raise a `NotImplementedError` exception.
4
+ * Fixed a typo in the method signature of {Python::Pickle.dump}.
5
+
6
+ ### 0.1.0 / 2023-02-18
7
+
3
8
  * Initial release:
4
9
  * Supports deserializing Python Pickle data into Ruby objects.
5
10
  * Supports serializing Ruby objects into Python Pickle data.
data/README.md CHANGED
@@ -20,7 +20,9 @@ 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 `tuple` and `bytearray` objects.
23
+ * Supports deserializing Python `None`, `True`, `False`, `int`, `str`, `tuple`,
24
+ `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.
26
28
 
@@ -1,6 +1,6 @@
1
1
  module Python
2
2
  module Pickle
3
3
  # python-pickle version
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
6
6
  end
data/lib/python/pickle.rb CHANGED
@@ -28,7 +28,7 @@ module Python
28
28
  # The default protocol version to use.
29
29
  #
30
30
  # @api public
31
- DEFAULT_PROTCOL = 4
31
+ DEFAULT_PROTOCOL = 4
32
32
 
33
33
  # The highest protocol version supported.
34
34
  #
@@ -88,12 +88,22 @@ module Python
88
88
  # The explicit protocol version to use. If `nil` the protocol version will
89
89
  # be inferred by inspecting the first two bytes of the stream.
90
90
  #
91
+ # @param [Hash{Symbol => Object}] kwargs
92
+ # Additional keyword arguments.
93
+ #
94
+ # @option kwargs [Hash{Integer => Object}] :extensions
95
+ # A Hash of registered extension IDs and their Objects.
96
+ #
97
+ # @option kwargs [Hash{String => Hash{String => Class,Method}}] :constants
98
+ # An optional mapping of custom Python constant names to Ruby classes
99
+ # or methods.
100
+ #
91
101
  # @api public
92
102
  #
93
- def self.load(data,**kwargs)
103
+ def self.load(data, protocol: nil, **kwargs)
94
104
  deserializer = Deserializer.new(**kwargs)
95
105
 
96
- parse(data) do |instruction|
106
+ parse(data, protocol: protocol) do |instruction|
97
107
  status, object = deserializer.execute(instruction)
98
108
 
99
109
  if status == :halt
@@ -110,11 +120,27 @@ module Python
110
120
  # @param [String] path
111
121
  # The path of the file.
112
122
  #
123
+ # @param [Hash{Symbol => Object}] kwargs
124
+ # Additional keyword arguments.
125
+ #
126
+ # @option kwargs [Hash{Integer => Object}] :extensions
127
+ # A Hash of registered extension IDs and their Objects.
128
+ #
129
+ # @option kwargs [Hash{String => Hash{String => Class,Method}}] :constants
130
+ # An optional mapping of custom Python constant names to Ruby classes
131
+ # or methods.
132
+ #
113
133
  # @return [Object]
114
134
  # The deserialized object.
115
135
  #
116
136
  def self.load_file(path,**kwargs)
117
- load(File.open(path,'rb'),**kwargs)
137
+ result = nil
138
+
139
+ File.open(path,'rb') do |file|
140
+ result = load(file,**kwargs)
141
+ end
142
+
143
+ return result
118
144
  end
119
145
 
120
146
  #
@@ -129,12 +155,12 @@ module Python
129
155
  # @param [Integer] protocol
130
156
  # The desired Python Pickle protocol to use.
131
157
  #
158
+ # @note serializing is currently not supported.
159
+ #
132
160
  # @api public
133
161
  #
134
162
  def self.dump(object,output=nil, protocol: DEFAULT_PROTOCOL)
135
- if (protocol < 0) || (protocol > HIGHEST_PROTOCOL)
136
- raise(ArgumentError,"protocol must be between 0 or #{HIGHEST_PROTOCOL}, but was #{protocol.inspect}")
137
- end
163
+ raise(NotImplementedError,"pickle serializing is currently not supported")
138
164
  end
139
165
 
140
166
  #
@@ -2,6 +2,11 @@ require 'spec_helper'
2
2
  require 'python/pickle/deserializer'
3
3
 
4
4
  describe Python::Pickle::Deserializer do
5
+ module TestDeserializer
6
+ class MyClass
7
+ end
8
+ end
9
+
5
10
  describe "#initialize" do
6
11
  it "must initialize #meta_stack to an empty Array" do
7
12
  expect(subject.meta_stack).to eq([])
@@ -44,9 +49,55 @@ describe Python::Pickle::Deserializer do
44
49
  end
45
50
 
46
51
  context "when initialized with the `extensions:` keyword argument" do
52
+ let(:extensions) do
53
+ {
54
+ 0x41 => Object.new,
55
+ 0x42 => Object.new,
56
+ 0x43 => Object.new
57
+ }
58
+ end
59
+
60
+ subject { described_class.new(extensions: extensions) }
61
+
62
+ it "must add the extensions: values to #extensions" do
63
+ expect(subject.extensions).to eq(extensions)
64
+ end
47
65
  end
48
66
 
49
67
  context "when initialized with the `constants:` keyword argument" do
68
+ let(:constants) do
69
+ {
70
+ '__main__' => {
71
+ 'MyClass' => TestDeserializer::MyClass
72
+ }
73
+ }
74
+ end
75
+
76
+ subject { described_class.new(constants: constants) }
77
+
78
+ it "must merge the constants: keyword argument with the default constants" do
79
+ expect(subject.constants).to eq(
80
+ {
81
+ 'copy_reg' => {
82
+ '_reconstructor' => subject.method(:copyreg_reconstructor)
83
+ },
84
+
85
+ '__builtin__' => {
86
+ 'object' => described_class::OBJECT_CLASS,
87
+ 'bytearray' => Python::Pickle::ByteArray
88
+ },
89
+
90
+ 'builtins' => {
91
+ 'object' => described_class::OBJECT_CLASS,
92
+ 'bytearray' => Python::Pickle::ByteArray
93
+ },
94
+
95
+ '__main__' => {
96
+ 'MyClass' => TestDeserializer::MyClass
97
+ }
98
+ }
99
+ )
100
+ end
50
101
  end
51
102
  end
52
103
 
data/spec/pickle_spec.rb CHANGED
@@ -52,6 +52,33 @@ describe Python::Pickle do
52
52
  it "must deserialize the Python Pickle data in the given file" do
53
53
  expect(subject.load(data)).to eq({"foo" => "bar"})
54
54
  end
55
+
56
+ context "when the constants: keyword argument is given" do
57
+ let(:path) { File.join(fixtures_dir,'object_v4.pkl') }
58
+
59
+ module TestLoad
60
+ class MyClass
61
+ attr_reader :x, :y
62
+
63
+ def __setstate__(attributes)
64
+ @x = attributes['x']
65
+ @y = attributes['y']
66
+ end
67
+ end
68
+ end
69
+
70
+ let(:constants) do
71
+ {
72
+ '__main__' => {
73
+ 'MyClass' => TestLoad::MyClass
74
+ }
75
+ }
76
+ end
77
+
78
+ it "must map the Python classes to the Ruby classes" do
79
+ expect(subject.load(data, constants: constants)).to be_kind_of(TestLoad::MyClass)
80
+ end
81
+ end
55
82
  end
56
83
 
57
84
  describe ".load_file" do
@@ -60,9 +87,43 @@ describe Python::Pickle do
60
87
  it "must deserialize the Python Pickle data in the given file" do
61
88
  expect(subject.load_file(path)).to eq({"foo" => "bar"})
62
89
  end
90
+
91
+ context "when the constants: keyword argument is given" do
92
+ let(:path) { File.join(fixtures_dir,'object_v4.pkl') }
93
+
94
+ module TestLoad
95
+ class MyClass
96
+ attr_reader :x, :y
97
+
98
+ def __setstate__(attributes)
99
+ @x = attributes['x']
100
+ @y = attributes['y']
101
+ end
102
+ end
103
+ end
104
+
105
+ let(:constants) do
106
+ {
107
+ '__main__' => {
108
+ 'MyClass' => TestLoad::MyClass
109
+ }
110
+ }
111
+ end
112
+
113
+ it "must map the Python classes to the Ruby classes" do
114
+ expect(subject.load_file(path, constants: constants)).to be_kind_of(TestLoad::MyClass)
115
+ end
116
+ end
63
117
  end
64
118
 
65
119
  describe ".dump" do
120
+ let(:object) { Object.new }
121
+
122
+ it do
123
+ expect {
124
+ subject.dump(object)
125
+ }.to raise_error(NotImplementedError,"pickle serializing is currently not supported")
126
+ end
66
127
  end
67
128
 
68
129
  describe ".infer_protocol_version" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: python-pickle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern