rubypython 0.3.1 → 0.3.2
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.
- data/.rspec +2 -0
- data/History.markdown +5 -0
- data/License.txt +2 -2
- data/Manifest.txt +13 -8
- data/README.markdown +5 -3
- data/Rakefile +7 -5
- data/lib/rubypython/conversion.rb +18 -1
- data/lib/rubypython/legacy.rb +25 -0
- data/lib/rubypython/operators.rb +7 -0
- data/lib/rubypython/options.rb +69 -0
- data/lib/rubypython/pymainclass.rb +13 -2
- data/lib/rubypython/pyobject.rb +17 -5
- data/lib/rubypython/python.rb +176 -153
- data/lib/rubypython/rubypyproxy.rb +60 -14
- data/lib/rubypython/version.rb +1 -1
- data/lib/rubypython.rb +51 -5
- data/spec/callback_spec.rb +63 -0
- data/spec/conversion_spec.rb +17 -9
- data/spec/legacy_spec.rb +41 -2
- data/spec/pymainclass_spec.rb +12 -5
- data/spec/pyobject_spec.rb +44 -37
- data/spec/python_helpers/objects.py +3 -0
- data/spec/python_helpers/objects.pyc +0 -0
- data/spec/pythonerror_spec.rb +13 -6
- data/spec/refcnt_spec.rb +4 -4
- data/spec/rubypyclass_spec.rb +9 -2
- data/spec/rubypyproxy_spec.rb +55 -34
- data/spec/rubypython_spec.rb +41 -8
- data/spec/spec_helper.rb +11 -13
- data.tar.gz.sig +0 -0
- metadata +30 -12
- metadata.gz.sig +0 -0
- data/spec/spec.opts +0 -2
data/spec/conversion_spec.rb
CHANGED
@@ -2,16 +2,20 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
|
|
2
2
|
|
3
3
|
include TestConstants
|
4
4
|
describe RubyPython::Conversion do
|
5
|
-
include RubyPythonStartStop
|
6
5
|
|
7
6
|
subject { RubyPython::Conversion }
|
8
7
|
|
9
8
|
before do
|
9
|
+
RubyPython.start
|
10
10
|
sys = RubyPython.import 'sys'
|
11
11
|
sys.path.append './spec/python_helpers'
|
12
12
|
@objects = RubyPython.import 'objects'
|
13
13
|
end
|
14
14
|
|
15
|
+
after do
|
16
|
+
RubyPython.stop
|
17
|
+
end
|
18
|
+
|
15
19
|
context "when converting from Python to Ruby" do
|
16
20
|
[
|
17
21
|
["an int", "an int", AnInt],
|
@@ -24,13 +28,13 @@ describe RubyPython::Conversion do
|
|
24
28
|
["python False", "false", false],
|
25
29
|
["python None", "nil", nil]
|
26
30
|
].each do |py_type, rb_type, output|
|
27
|
-
it "
|
31
|
+
it "converts #{py_type} to #{rb_type}" do
|
28
32
|
py_object_ptr = @objects.__send__(py_type.sub(' ', '_')).pObject.pointer
|
29
33
|
subject.ptorObject(py_object_ptr).should == output
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
33
|
-
it "
|
37
|
+
it "returns an FFI::Pointer when it cannot convert" do
|
34
38
|
unconvertable = @objects.RubyPythonMockObject.pObject.pointer
|
35
39
|
subject.ptorObject(unconvertable).should be_a_kind_of(FFI::Pointer)
|
36
40
|
end
|
@@ -47,20 +51,24 @@ describe RubyPython::Conversion do
|
|
47
51
|
["a dict", "a hash", AConvertedHash],
|
48
52
|
["python True", "true", true],
|
49
53
|
["python False", "false", false],
|
50
|
-
["python None", "nil", nil]
|
51
|
-
|
54
|
+
["python None", "nil", nil],
|
55
|
+
["a function", "a proc", AProc, true]
|
56
|
+
].each do |py_type, rb_type, input, no_compare|
|
52
57
|
|
53
|
-
it "
|
58
|
+
it "converts #{rb_type} to #{py_type}" do
|
54
59
|
py_object_ptr = subject.rtopObject(input)
|
55
|
-
|
56
|
-
|
60
|
+
unless no_compare
|
61
|
+
output = @objects.__send__(rb_type.sub(' ', '_')).pObject.pointer
|
62
|
+
RubyPython::Python.PyObject_Compare(py_object_ptr, output).should == 0
|
63
|
+
end
|
57
64
|
end
|
58
65
|
end
|
59
66
|
|
60
|
-
it "
|
67
|
+
it "raises an exception when it cannot convert" do
|
61
68
|
lambda { subject.rtopObject(Class) }.should raise_exception(subject::UnsupportedConversion)
|
62
69
|
end
|
63
70
|
|
64
71
|
end
|
65
72
|
|
73
|
+
|
66
74
|
end
|
data/spec/legacy_spec.rb
CHANGED
@@ -3,7 +3,19 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
|
|
3
3
|
include TestConstants
|
4
4
|
|
5
5
|
describe 'RubyPython Legacy Mode Module' do
|
6
|
-
|
6
|
+
|
7
|
+
before do
|
8
|
+
RubyPython.start
|
9
|
+
sys = RubyPython.import 'sys'
|
10
|
+
path = sys.path
|
11
|
+
path.push './spec/python_helpers'
|
12
|
+
sys.path = path
|
13
|
+
@objects = RubyPython.import 'objects'
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
RubyPython.stop
|
18
|
+
end
|
7
19
|
|
8
20
|
before :all do
|
9
21
|
require 'rubypython/legacy'
|
@@ -14,9 +26,36 @@ describe 'RubyPython Legacy Mode Module' do
|
|
14
26
|
end
|
15
27
|
|
16
28
|
describe "when required" do
|
17
|
-
it "
|
29
|
+
it "enables legacy mode" do
|
18
30
|
RubyPython.legacy_mode.should == true
|
19
31
|
end
|
32
|
+
|
33
|
+
[
|
34
|
+
["an int", "an int", AnInt],
|
35
|
+
["a float", "a float", AFloat],
|
36
|
+
["a string", "a string", AString],
|
37
|
+
["a list", "an array", AnArray],
|
38
|
+
["a tuple", "an array", AnArray],
|
39
|
+
["a dict", "a hash", AConvertedHash],
|
40
|
+
["python True", "true", true],
|
41
|
+
["python False", "false", false],
|
42
|
+
["python None", "nil", nil]
|
43
|
+
].each do |py_type, rb_type, output|
|
44
|
+
it "implicitly converts #{py_type} to #{rb_type}" do
|
45
|
+
@objects.__send__(py_type.sub(' ', '_')).should == output
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
[
|
50
|
+
["proc", AProc],
|
51
|
+
["method", AMethod]
|
52
|
+
].each do |rb_type, rb_obj|
|
53
|
+
it "raises an exception if a #{rb_type} callback is supplied" do
|
54
|
+
lambda do
|
55
|
+
@objects.apply_callback(rb_obj, [1, 1])
|
56
|
+
end.should raise_exception(RubyPython::Conversion::UnsupportedConversion)
|
57
|
+
end
|
58
|
+
end
|
20
59
|
end
|
21
60
|
|
22
61
|
end
|
data/spec/pymainclass_spec.rb
CHANGED
@@ -2,23 +2,30 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
|
|
2
2
|
|
3
3
|
describe RubyPython::PyMainClass do
|
4
4
|
include TestConstants
|
5
|
-
|
5
|
+
|
6
|
+
before do
|
7
|
+
RubyPython.start
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
RubyPython.stop
|
12
|
+
end
|
6
13
|
|
7
14
|
subject { RubyPython::PyMain }
|
8
15
|
|
9
|
-
it "
|
16
|
+
it "delegates to builtins" do
|
10
17
|
subject.float(AnInt).rubify.should == AnInt.to_f
|
11
18
|
end
|
12
19
|
|
13
|
-
it "
|
20
|
+
it "handles block syntax" do
|
14
21
|
subject.float(AnInt) {|f| f.rubify*2}.should == (AnInt.to_f * 2)
|
15
22
|
end
|
16
23
|
|
17
|
-
it "
|
24
|
+
it "allows attribute access" do
|
18
25
|
subject.main.__name__.rubify.should == '__main__'
|
19
26
|
end
|
20
27
|
|
21
|
-
it "
|
28
|
+
it "allows global variable modification" do
|
22
29
|
subject.x = 2
|
23
30
|
subject.x.rubify.should == 2
|
24
31
|
end
|
data/spec/pyobject_spec.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
2
|
|
3
3
|
describe RubyPython::PyObject do
|
4
|
-
include RubyPythonStartStop
|
5
4
|
include TestConstants
|
6
5
|
|
6
|
+
before do
|
7
|
+
RubyPython.start
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
RubyPython.start
|
12
|
+
end
|
13
|
+
|
7
14
|
before do
|
8
15
|
@string = RubyPython.import('string').pObject
|
9
16
|
@urllib2 = RubyPython.import('urllib2').pObject
|
@@ -23,7 +30,7 @@ describe RubyPython::PyObject do
|
|
23
30
|
["a hash", AHash]
|
24
31
|
].each do |title, obj|
|
25
32
|
|
26
|
-
it "
|
33
|
+
it "wraps #{title}" do
|
27
34
|
lambda { described_class.new(obj) }.should_not raise_exception
|
28
35
|
end
|
29
36
|
end
|
@@ -34,10 +41,10 @@ describe RubyPython::PyObject do
|
|
34
41
|
"a list",
|
35
42
|
"a dict",
|
36
43
|
"a tuple"
|
37
|
-
].each do |
|
38
|
-
it "
|
44
|
+
].each do |type|
|
45
|
+
it "accepts a Python pointer to a #{type}" do
|
39
46
|
lambda do
|
40
|
-
py_obj = @objects.__send__(
|
47
|
+
py_obj = @objects.__send__(type.gsub(' ','_')).pObject.pointer
|
41
48
|
described_class.new(py_obj)
|
42
49
|
end.should_not raise_exception
|
43
50
|
end
|
@@ -59,7 +66,7 @@ describe RubyPython::PyObject do
|
|
59
66
|
type, input, output = arr
|
60
67
|
output ||= input
|
61
68
|
|
62
|
-
it "
|
69
|
+
it "faithfully unwraps #{type}" do
|
63
70
|
described_class.new(input).rubify.should == output
|
64
71
|
end
|
65
72
|
|
@@ -68,35 +75,35 @@ describe RubyPython::PyObject do
|
|
68
75
|
end #rubify
|
69
76
|
|
70
77
|
describe "#hasAttr" do
|
71
|
-
it "
|
78
|
+
it "is true when wrapped object has the requested attribute" do
|
72
79
|
@string.hasAttr("ascii_letters").should be_true
|
73
80
|
end
|
74
81
|
|
75
|
-
it "
|
82
|
+
it "is false when wrapped object does not have the requested attribute" do
|
76
83
|
@string.hasAttr("nonExistentThing").should be_false
|
77
84
|
end
|
78
85
|
end
|
79
86
|
|
80
87
|
describe "#getAttr" do
|
81
|
-
it "
|
88
|
+
it "fetchs a pointer to the requested object attribute" do
|
82
89
|
ascii_letters = @string.getAttr "ascii_letters"
|
83
90
|
ascii_letters.rubify.should == "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
84
91
|
end
|
85
92
|
|
86
|
-
it "
|
93
|
+
it "returns a PyObject instance" do
|
87
94
|
ascii_letters = @string.getAttr "ascii_letters"
|
88
95
|
ascii_letters.should be_kind_of(described_class)
|
89
96
|
end
|
90
97
|
end
|
91
98
|
|
92
99
|
describe "#setAttr" do
|
93
|
-
it "
|
100
|
+
it "modifies the specified attribute of the object" do
|
94
101
|
pyNewLetters = described_class.new "RbPy"
|
95
102
|
@string.setAttr "ascii_letters", pyNewLetters
|
96
103
|
@string.getAttr("ascii_letters").rubify.should == pyNewLetters.rubify
|
97
104
|
end
|
98
105
|
|
99
|
-
it "
|
106
|
+
it "creates the requested attribute if it doesn't exist" do
|
100
107
|
pyNewString = described_class.new "python"
|
101
108
|
@string.setAttr "ruby", pyNewString
|
102
109
|
@string.getAttr("ruby").rubify.should == pyNewString.rubify
|
@@ -111,36 +118,36 @@ describe RubyPython::PyObject do
|
|
111
118
|
@less_dup = described_class.new 5
|
112
119
|
end
|
113
120
|
|
114
|
-
it "
|
121
|
+
it "returns 0 when objects are equal" do
|
115
122
|
@less.cmp(@less_dup).should == 0
|
116
123
|
end
|
117
124
|
|
118
|
-
it "
|
125
|
+
it "changes sign under interchange of arguments" do
|
119
126
|
@less.cmp(@greater).should == -@greater.cmp(@less)
|
120
127
|
end
|
121
128
|
|
122
|
-
it "
|
129
|
+
it "returns -1 when first object is less than the second" do
|
123
130
|
@less.cmp(@greater).should == -1
|
124
131
|
end
|
125
132
|
|
126
|
-
it "
|
133
|
+
it "returns 1 when first object is greater than the second" do
|
127
134
|
@greater.cmp(@less).should == 1
|
128
135
|
end
|
129
136
|
end
|
130
137
|
|
131
138
|
describe "#makeTuple" do
|
132
|
-
it "
|
139
|
+
it "wraps single arguments in a tuple" do
|
133
140
|
arg = described_class.new AString
|
134
141
|
described_class.makeTuple(arg).rubify.should == [AString]
|
135
142
|
end
|
136
143
|
|
137
|
-
it "
|
144
|
+
it "turns a Python list into a tuple" do
|
138
145
|
arg = @objects.a_list.pObject
|
139
146
|
converted = described_class.makeTuple(arg)
|
140
147
|
converted.rubify.should == AnArray
|
141
148
|
end
|
142
149
|
|
143
|
-
it "
|
150
|
+
it "returns the given argument if it is a tuple" do
|
144
151
|
arg = @objects.a_tuple.pObject
|
145
152
|
converted = described_class.makeTuple(arg)
|
146
153
|
converted.pointer.address.should == arg.pointer.address
|
@@ -150,7 +157,7 @@ describe RubyPython::PyObject do
|
|
150
157
|
|
151
158
|
describe "#callObject" do
|
152
159
|
#Expand coverage types
|
153
|
-
it "
|
160
|
+
it "executes wrapped object with supplied arguments" do
|
154
161
|
arg = described_class.new AnInt
|
155
162
|
argt = described_class.buildArgTuple arg
|
156
163
|
|
@@ -161,7 +168,7 @@ describe RubyPython::PyObject do
|
|
161
168
|
end
|
162
169
|
|
163
170
|
describe "#newList" do
|
164
|
-
it "
|
171
|
+
it "wraps supplied args in a Python list" do
|
165
172
|
args = AnArray.map do |obj|
|
166
173
|
described_class.new obj
|
167
174
|
end
|
@@ -171,21 +178,21 @@ describe RubyPython::PyObject do
|
|
171
178
|
|
172
179
|
describe "#function_or_method?" do
|
173
180
|
|
174
|
-
it "
|
181
|
+
it "is true for a method" do
|
175
182
|
mockObjClass = @objects.RubyPythonMockObject.pObject
|
176
183
|
mockObjClass.getAttr('square_elements').should be_a_function_or_method
|
177
184
|
end
|
178
185
|
|
179
|
-
it "
|
186
|
+
it "is true for a function" do
|
180
187
|
@objects.pObject.getAttr('identity').should be_a_function_or_method
|
181
188
|
end
|
182
189
|
|
183
|
-
|
190
|
+
it "is true for a builtin function" do
|
184
191
|
any = @builtin.pObject.getAttr('any')
|
185
192
|
any.should be_a_function_or_method
|
186
193
|
end
|
187
194
|
|
188
|
-
it "
|
195
|
+
it "is false for a class" do
|
189
196
|
@objects.RubyPythonMockObject.pObject.should_not be_a_function_or_method
|
190
197
|
end
|
191
198
|
|
@@ -193,20 +200,20 @@ describe RubyPython::PyObject do
|
|
193
200
|
|
194
201
|
describe "#class?" do
|
195
202
|
|
196
|
-
it "
|
203
|
+
it "is true if wrapped object is an old style class" do
|
197
204
|
@objects.RubyPythonMockObject.pObject.should be_a_class
|
198
205
|
end
|
199
206
|
|
200
|
-
it "
|
207
|
+
it "is true if wrapped object is an new style class" do
|
201
208
|
@objects.NewStyleClass.pObject.should be_a_class
|
202
209
|
end
|
203
210
|
|
204
|
-
it "
|
211
|
+
it "is true if wrapped object is a builtin class" do
|
205
212
|
strClass = @builtin.pObject.getAttr('str')
|
206
213
|
strClass.should be_a_class
|
207
214
|
end
|
208
215
|
|
209
|
-
it "
|
216
|
+
it "is false for an object instance" do
|
210
217
|
@objects.RubyPythonMockObject.new.pObject.should_not be_a_class
|
211
218
|
end
|
212
219
|
|
@@ -214,25 +221,25 @@ describe RubyPython::PyObject do
|
|
214
221
|
|
215
222
|
describe "#callable?" do
|
216
223
|
|
217
|
-
it "
|
224
|
+
it "is true for a method" do
|
218
225
|
mockObjClass = @objects.RubyPythonMockObject.pObject
|
219
226
|
mockObjClass.getAttr('square_elements').should be_callable
|
220
227
|
end
|
221
228
|
|
222
|
-
it "
|
229
|
+
it "is true for a function" do
|
223
230
|
@objects.pObject.getAttr('identity').should be_callable
|
224
231
|
end
|
225
232
|
|
226
|
-
it "
|
233
|
+
it "is true for a builtin function" do
|
227
234
|
any = @builtin.pObject.getAttr('any')
|
228
235
|
any.should be_callable
|
229
236
|
end
|
230
237
|
|
231
|
-
it "
|
238
|
+
it "is true for a class" do
|
232
239
|
@objects.RubyPythonMockObject.pObject.should be_callable
|
233
240
|
end
|
234
241
|
|
235
|
-
it "
|
242
|
+
it "is false for a non-callable instance" do
|
236
243
|
@objects.RubyPythonMockObject.new.pObject.should_not be_callable
|
237
244
|
end
|
238
245
|
|
@@ -242,17 +249,17 @@ describe RubyPython::PyObject do
|
|
242
249
|
|
243
250
|
describe ".convert" do
|
244
251
|
|
245
|
-
it "
|
252
|
+
it "does not modify PyObjects passed to it" do
|
246
253
|
args = AnArray.map { |x| described_class.new(x) }
|
247
254
|
described_class.convert(*args).should == args
|
248
255
|
end
|
249
256
|
|
250
|
-
it "
|
257
|
+
it "pulls PyObjects out of RubyPyProxy instances" do
|
251
258
|
args = @objects.an_array.to_a
|
252
259
|
described_class.convert(*args).should == args.map {|x| x.pObject}
|
253
260
|
end
|
254
261
|
|
255
|
-
it "
|
262
|
+
it "creates new PyObject instances of simple Ruby types" do
|
256
263
|
described_class.convert(*AnArray).each do |x|
|
257
264
|
x.should be_a_kind_of described_class
|
258
265
|
end
|
Binary file
|
data/spec/pythonerror_spec.rb
CHANGED
@@ -1,38 +1,45 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
2
|
|
3
3
|
describe RubyPython::PythonError do
|
4
|
-
|
4
|
+
|
5
|
+
before do
|
6
|
+
RubyPython.start
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
RubyPython.start
|
11
|
+
end
|
5
12
|
|
6
13
|
def cause_error
|
7
14
|
RubyPython::Python.PyImport_ImportModule("wat")
|
8
15
|
end
|
9
16
|
|
10
17
|
describe "#error?" do
|
11
|
-
it "
|
18
|
+
it "is false when no error has occured" do
|
12
19
|
described_class.error?.should be_false
|
13
20
|
end
|
14
21
|
|
15
|
-
it "
|
22
|
+
it "is true when an error has occured" do
|
16
23
|
cause_error
|
17
24
|
described_class.error?.should be_true
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|
21
28
|
describe "#clear" do
|
22
|
-
it "
|
29
|
+
it "resets the Python error flag" do
|
23
30
|
cause_error
|
24
31
|
described_class.clear
|
25
32
|
described_class.error?.should be_false
|
26
33
|
end
|
27
34
|
|
28
|
-
it "
|
35
|
+
it "doesn't barf when there is no error" do
|
29
36
|
lambda {described_class.clear}.should_not raise_exception
|
30
37
|
end
|
31
38
|
end
|
32
39
|
|
33
40
|
|
34
41
|
describe "#fetch" do
|
35
|
-
it "
|
42
|
+
it "makes availible Python error type" do
|
36
43
|
cause_error
|
37
44
|
rbType, rbValue, rbTraceback = described_class.fetch
|
38
45
|
rbType.getAttr("__name__").rubify.should == "ImportError"
|
data/spec/refcnt_spec.rb
CHANGED
@@ -27,12 +27,12 @@ describe 'Reference Counting' do
|
|
27
27
|
RubyPython.stop
|
28
28
|
end
|
29
29
|
|
30
|
-
it "
|
30
|
+
it "is one for a new object" do
|
31
31
|
pyObj = @objects.RubyPythonMockObject.new
|
32
32
|
get_refcnt(pyObj).should == 1
|
33
33
|
end
|
34
34
|
|
35
|
-
it "
|
35
|
+
it "increases when a new reference is passed into Ruby" do
|
36
36
|
pyObj = @objects.RubyPythonMockObject
|
37
37
|
refcnt = get_refcnt(pyObj)
|
38
38
|
pyObj2 = @objects.RubyPythonMockObject
|
@@ -42,7 +42,7 @@ describe 'Reference Counting' do
|
|
42
42
|
describe RubyPython::PyObject do
|
43
43
|
|
44
44
|
describe "#xIncref" do
|
45
|
-
it "
|
45
|
+
it "increases the reference count" do
|
46
46
|
pyObj = @objects.RubyPythonMockObject.new
|
47
47
|
refcnt = get_refcnt(pyObj)
|
48
48
|
pyObj.pObject.xIncref
|
@@ -51,7 +51,7 @@ describe 'Reference Counting' do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
describe "#xDecref" do
|
54
|
-
it "
|
54
|
+
it "decreases the reference count" do
|
55
55
|
pyObj = @objects.RubyPythonMockObject.new
|
56
56
|
pyObj.pObject.xIncref
|
57
57
|
refcnt = get_refcnt(pyObj)
|
data/spec/rubypyclass_spec.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
2
|
|
3
3
|
describe RubyPython::RubyPyClass do
|
4
|
-
|
4
|
+
|
5
|
+
before do
|
6
|
+
RubyPython.start
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
RubyPython.start
|
11
|
+
end
|
5
12
|
|
6
13
|
describe "#new" do
|
7
|
-
it "
|
14
|
+
it "returns a RubyPyInstance" do
|
8
15
|
urllib2 = RubyPython.import 'urllib2'
|
9
16
|
urllib2.Request.new('google.com').should be_a(RubyPython::RubyPyInstance)
|
10
17
|
end
|