rubypython 0.2.11 → 0.3.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.
- data.tar.gz.sig +0 -0
- data/{History.txt → History.markdown} +34 -28
- data/Manifest.txt +26 -40
- data/PostInstall.txt +2 -1
- data/README.markdown +103 -0
- data/Rakefile +19 -3
- data/lib/rubypython.rb +118 -114
- data/lib/rubypython/blankobject.rb +21 -0
- data/lib/rubypython/conversion.rb +198 -0
- data/lib/rubypython/core_ext/string.rb +7 -0
- data/lib/rubypython/legacy.rb +15 -0
- data/lib/rubypython/macros.rb +47 -0
- data/lib/rubypython/operators.rb +111 -0
- data/lib/rubypython/pymainclass.rb +51 -0
- data/lib/rubypython/pyobject.rb +203 -0
- data/lib/rubypython/python.rb +111 -0
- data/lib/rubypython/pythonerror.rb +78 -0
- data/lib/rubypython/rubypyproxy.rb +214 -0
- data/lib/rubypython/version.rb +4 -3
- data/spec/conversion_spec.rb +66 -0
- data/spec/legacy_spec.rb +22 -0
- data/spec/pymainclass_spec.rb +26 -0
- data/spec/pyobject_spec.rb +264 -0
- data/spec/python_helpers/objects.py +41 -0
- data/spec/pythonerror_spec.rb +43 -0
- data/spec/refcnt_spec.rb +68 -0
- data/spec/rubypyclass_spec.rb +13 -0
- data/spec/rubypyproxy_spec.rb +249 -0
- data/spec/rubypython_spec.rb +62 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +51 -0
- metadata +79 -73
- metadata.gz.sig +0 -0
- data/README.txt +0 -60
- data/ext/rubypython_bridge/cbridge.c +0 -150
- data/ext/rubypython_bridge/cbridge.h +0 -15
- data/ext/rubypython_bridge/config.h +0 -14
- data/ext/rubypython_bridge/extconf.rb +0 -43
- data/ext/rubypython_bridge/ptor.c +0 -242
- data/ext/rubypython_bridge/ptor.h +0 -15
- data/ext/rubypython_bridge/rp_blankobject.c +0 -42
- data/ext/rubypython_bridge/rp_blankobject.h +0 -11
- data/ext/rubypython_bridge/rp_class.c +0 -56
- data/ext/rubypython_bridge/rp_class.h +0 -7
- data/ext/rubypython_bridge/rp_error.c +0 -34
- data/ext/rubypython_bridge/rp_error.h +0 -11
- data/ext/rubypython_bridge/rp_function.c +0 -31
- data/ext/rubypython_bridge/rp_function.h +0 -7
- data/ext/rubypython_bridge/rp_instance.c +0 -164
- data/ext/rubypython_bridge/rp_instance.h +0 -7
- data/ext/rubypython_bridge/rp_module.c +0 -160
- data/ext/rubypython_bridge/rp_module.h +0 -8
- data/ext/rubypython_bridge/rp_object.c +0 -194
- data/ext/rubypython_bridge/rp_object.h +0 -23
- data/ext/rubypython_bridge/rp_util.c +0 -63
- data/ext/rubypython_bridge/rp_util.h +0 -11
- data/ext/rubypython_bridge/rtop.c +0 -212
- data/ext/rubypython_bridge/rtop.h +0 -17
- data/ext/rubypython_bridge/rubypython_bridge.c +0 -125
- data/ext/rubypython_bridge/rubypython_bridge.h +0 -10
- data/lib/rubypython/session.rb +0 -4
- data/lib/rubypython/wrapper_extensions.rb +0 -83
- data/setup.rb +0 -1585
- data/tasks/environment.rake +0 -7
- data/tasks/extconf.rake +0 -13
- data/tasks/extconf/rubypython_bridge.rake +0 -49
- data/test/python_helpers/objects.py +0 -12
- data/test/test.wav +0 -0
- data/test/test_helper.rb +0 -2
- data/test/test_rubypython.rb +0 -215
- data/test/test_rubypython_bridge_extn.rb +0 -133
- data/test/test_session.rb +0 -6
data/spec/refcnt_spec.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
def get_refcnt(pobject)
|
4
|
+
raise 'Cannot work with a nil object' if pobject.nil?
|
5
|
+
|
6
|
+
if pobject.kind_of? RubyPython::RubyPyProxy
|
7
|
+
pobject = pobject.pObject.pointer
|
8
|
+
elsif pobject.kind_of? RubyPython::PyObject
|
9
|
+
pobject = pobject.pointer
|
10
|
+
end
|
11
|
+
struct = RubyPython::Python::PyObjectStruct.new pobject
|
12
|
+
struct[:ob_refcnt]
|
13
|
+
end
|
14
|
+
|
15
|
+
include TestConstants
|
16
|
+
|
17
|
+
describe 'Reference Counting' do
|
18
|
+
|
19
|
+
before :all do
|
20
|
+
RubyPython.start
|
21
|
+
@sys = RubyPython.import 'sys'
|
22
|
+
@sys.path.append './spec/python_helpers'
|
23
|
+
@objects = RubyPython.import 'objects'
|
24
|
+
end
|
25
|
+
|
26
|
+
after :all do
|
27
|
+
RubyPython.stop
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should be one for a new object" do
|
31
|
+
pyObj = @objects.RubyPythonMockObject.new
|
32
|
+
get_refcnt(pyObj).should == 1
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should increase when a new reference is passed into Ruby" do
|
36
|
+
pyObj = @objects.RubyPythonMockObject
|
37
|
+
refcnt = get_refcnt(pyObj)
|
38
|
+
pyObj2 = @objects.RubyPythonMockObject
|
39
|
+
get_refcnt(pyObj).should == (refcnt + 1)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe RubyPython::PyObject do
|
43
|
+
|
44
|
+
describe "#xIncref" do
|
45
|
+
it "should increase the reference count" do
|
46
|
+
pyObj = @objects.RubyPythonMockObject.new
|
47
|
+
refcnt = get_refcnt(pyObj)
|
48
|
+
pyObj.pObject.xIncref
|
49
|
+
get_refcnt(pyObj).should == refcnt + 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#xDecref" do
|
54
|
+
it "should decrease the reference count" do
|
55
|
+
pyObj = @objects.RubyPythonMockObject.new
|
56
|
+
pyObj.pObject.xIncref
|
57
|
+
refcnt = get_refcnt(pyObj)
|
58
|
+
pointer = pyObj.pObject.pointer
|
59
|
+
pyObj.pObject.xDecref
|
60
|
+
get_refcnt(pointer).should == refcnt - 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe RubyPython::RubyPyClass do
|
4
|
+
include RubyPythonStartStop
|
5
|
+
|
6
|
+
describe "#new" do
|
7
|
+
it "should return a RubyPyInstance" do
|
8
|
+
urllib2 = RubyPython.import 'urllib2'
|
9
|
+
urllib2.Request.new('google.com').should be_a(RubyPython::RubyPyInstance)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
|
4
|
+
include TestConstants
|
5
|
+
describe RubyPython::RubyPyProxy do
|
6
|
+
include RubyPythonStartStop
|
7
|
+
|
8
|
+
before do
|
9
|
+
@a = RubyPython::PyObject.new "a"
|
10
|
+
@b = RubyPython::PyObject.new "b"
|
11
|
+
@builtin = RubyPython.import("__builtin__").pObject
|
12
|
+
@string = RubyPython.import("string").pObject
|
13
|
+
|
14
|
+
@two = described_class.new 2
|
15
|
+
@six = described_class.new 6
|
16
|
+
|
17
|
+
@sys = RubyPython.import 'sys'
|
18
|
+
@sys.path.append './spec/python_helpers'
|
19
|
+
@objects = RubyPython.import 'objects'
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#new" do
|
23
|
+
it "should accept a PyObject instance" do
|
24
|
+
rbPyObject = RubyPython::PyObject.new AString
|
25
|
+
lambda {described_class.new rbPyObject}.should_not raise_exception
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
[
|
30
|
+
["a string", AString],
|
31
|
+
["an int", AnInt],
|
32
|
+
["a float", AFloat],
|
33
|
+
["an array", AnArray],
|
34
|
+
["a symbol", ASym, ASym.to_s],
|
35
|
+
["a hash", AHash, AConvertedHash]
|
36
|
+
].each do |arr|
|
37
|
+
type, input, output = arr
|
38
|
+
output ||= input
|
39
|
+
|
40
|
+
it "should convert #{type} to wrapped pObject" do
|
41
|
+
described_class.new(input).pObject.rubify.should == output
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#rubify" do
|
48
|
+
[
|
49
|
+
["a string", AString],
|
50
|
+
["an int", AnInt],
|
51
|
+
["a float", AFloat],
|
52
|
+
["an array", AnArray],
|
53
|
+
["a symbol", ASym],
|
54
|
+
["a hash", AHash]
|
55
|
+
].each do |title, obj|
|
56
|
+
it "should faithfully unwrap #{title}" do
|
57
|
+
pyObject = RubyPython::PyObject.new obj
|
58
|
+
proxy = described_class.new pyObject
|
59
|
+
proxy.rubify.should == pyObject.rubify
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#inspect" do
|
65
|
+
|
66
|
+
it "should return 'repr' of wrapped object" do
|
67
|
+
@six.inspect.should == '6'
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should gracefully handle lack of defined __repr__" do
|
71
|
+
lambda { @objects.RubyPythonMockObject.inspect }.should_not raise_exception
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#to_s" do
|
77
|
+
it "should return 'str' of wrapped object" do
|
78
|
+
@six.to_s.should == '6'
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should gracefully handle lack of defined __str__" do
|
82
|
+
lambda { @objects.RubyPythonMockObject.to_s }.should_not raise_exception
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#to_a" do
|
87
|
+
it "should convert a list to an array of its entries" do
|
88
|
+
list = @objects.a_list
|
89
|
+
list.to_a.should == AnArray.map { |x| described_class.new(x) }
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should convert a tuple to an array of its entries" do
|
93
|
+
tuple = @objects.a_tuple
|
94
|
+
tuple.to_a.should == AnArray.map { |x| described_class.new(x) }
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should convert a dict to an array of keys" do
|
98
|
+
dict = @objects.a_dict
|
99
|
+
dict.to_a.sort.should == AConvertedHash.keys.map {|x| described_class.new(x)}.sort
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#respond_to?" do
|
104
|
+
it "should return true for getters" do
|
105
|
+
@objects.should respond_to(:RubyPythonMockObject)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should return false for undefined methods" do
|
109
|
+
@objects.should_not respond_to(:undefined_attr)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should return true for any setter" do
|
113
|
+
@objects.should respond_to(:any_variable=)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should return true for methods on RubyPyProxy instance" do
|
117
|
+
@objects.should respond_to(:inspect)
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "method delegation" do
|
123
|
+
|
124
|
+
it "should refer method calls to wrapped object" do
|
125
|
+
aProxy = described_class.new(@a)
|
126
|
+
bProxy = described_class.new(@b)
|
127
|
+
aProxy.__add__(bProxy).rubify.should == (@a.rubify + @b.rubify)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should raise NoMethodError when method is undefined" do
|
131
|
+
aProxy = described_class.new @a
|
132
|
+
lambda {aProxy.wat}.should raise_exception(NoMethodError)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should allow methods to be called with no arguments" do
|
136
|
+
builtinProxy = described_class.new @builtin
|
137
|
+
rbStrClass = builtinProxy.str
|
138
|
+
rbStrClass.new.rubify.should == String.new
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should fetch attributes when method name is an attribute" do
|
142
|
+
pyLetters = @string.getAttr "ascii_letters"
|
143
|
+
stringProxy = described_class.new @string
|
144
|
+
stringProxy.ascii_letters.rubify.should == pyLetters.rubify
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should set attribute if method call is a setter" do
|
148
|
+
stringProxy = described_class.new @string
|
149
|
+
stringProxy.letters = AString
|
150
|
+
stringProxy.letters.rubify.should == AString
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should create nonexistent attirubte if method call is a setter" do
|
154
|
+
stringProxy = described_class.new @string
|
155
|
+
stringProxy.nonExistent = 1
|
156
|
+
stringProxy.nonExistent.rubify.should == 1
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should return a class as a RubyPyClass" do
|
160
|
+
urllib2 = RubyPython.import('urllib2')
|
161
|
+
urllib2.Request.should be_a(RubyPython::RubyPyClass)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "when used with an operator" do
|
166
|
+
|
167
|
+
[
|
168
|
+
'+', '-', '/', '*', '&', '^', '%', '**',
|
169
|
+
'>>', '<<', '<=>', '|'
|
170
|
+
].each do |op|
|
171
|
+
it "should delegate #{op}" do
|
172
|
+
@six.__send__(op, @two).rubify.should == 6.__send__(op, 2)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
[
|
177
|
+
'~', '-@', '+@'
|
178
|
+
].each do |op|
|
179
|
+
it "should delegate #{op}" do
|
180
|
+
@six.__send__(op).rubify.should == 6.__send__(op)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
['==', '<', '>', '<=', '>='].each do |op|
|
185
|
+
it "should delegate #{op}" do
|
186
|
+
@six.__send__(op, @two).should == 6.__send__(op, 2)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "#equal?" do
|
191
|
+
it "be true for proxies representing the same object" do
|
192
|
+
obj1 = @objects.RubyPythonMockObject
|
193
|
+
obj2 = @objects.RubyPythonMockObject
|
194
|
+
obj1.should equal(obj2)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should be false for objects which are different" do
|
198
|
+
@two.should_not equal(@six)
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should allow list indexing" do
|
204
|
+
array = described_class.new(AnArray)
|
205
|
+
array[1].rubify.should == AnArray[1]
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should allow dict access" do
|
209
|
+
dict = described_class.new(AHash)
|
210
|
+
key = AConvertedHash.keys[0]
|
211
|
+
dict[key].rubify.should == AConvertedHash[key]
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should allow list index assignment" do
|
215
|
+
array = described_class.new(AnArray)
|
216
|
+
val = AString*2
|
217
|
+
array[1] = val
|
218
|
+
array[1].rubify.should == val
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should allow dict value modification" do
|
222
|
+
dict = described_class.new(AHash)
|
223
|
+
key = AConvertedHash.keys[0]
|
224
|
+
val = AString*2
|
225
|
+
dict[key] = val
|
226
|
+
dict[key].rubify.should == val
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should allow creation of new dict key-val pair" do
|
230
|
+
dict = described_class.new(AHash)
|
231
|
+
key = AString*2
|
232
|
+
dict[key] = AString
|
233
|
+
dict[key].rubify.should == AString
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should allow membership tests with include?" do
|
237
|
+
list = described_class.new(AnArray)
|
238
|
+
list.include?(AnArray[0]).should be_true
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
it "should delegate object equality" do
|
244
|
+
urllib_a = RubyPython.import('urllib')
|
245
|
+
urllib_b = RubyPython.import('urllib')
|
246
|
+
urllib_a.should == urllib_b
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe RubyPython do
|
4
|
+
include RubyPythonStartStop
|
5
|
+
|
6
|
+
describe "#import" do
|
7
|
+
it "should handle multiple imports" do
|
8
|
+
lambda do
|
9
|
+
RubyPython.import 'cPickle'
|
10
|
+
RubyPython.import 'urllib'
|
11
|
+
end.should_not raise_exception
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should propagate Python errors" do
|
15
|
+
lambda do
|
16
|
+
RubyPython.import 'nonExistentModule'
|
17
|
+
end.should raise_exception(RubyPython::PythonError)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return a RubyPyModule" do
|
21
|
+
RubyPython.import('urllib2').should be_a(RubyPython::RubyPyModule)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe RubyPython, "#session" do
|
28
|
+
|
29
|
+
it "should start interpreter" do
|
30
|
+
RubyPython.session do
|
31
|
+
cPickle = RubyPython.import "cPickle"
|
32
|
+
cPickle.loads("(dp1\nS'a'\nS'n'\ns(I1\nS'2'\ntp2\nI4\ns.").rubify.should == {"a"=>"n", [1, "2"]=>4}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should stop the interpreter" do
|
37
|
+
RubyPython.session do
|
38
|
+
cPickle = RubyPython.import "cPickle"
|
39
|
+
end
|
40
|
+
|
41
|
+
RubyPython.stop.should be_false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe RubyPython, "#run" do
|
46
|
+
|
47
|
+
it "should start interpreter" do
|
48
|
+
RubyPython.run do
|
49
|
+
cPickle = import "cPickle"
|
50
|
+
cPickle.loads("(dp1\nS'a'\nS'n'\ns(I1\nS'2'\ntp2\nI4\ns.").rubify.should == {"a"=>"n", [1, "2"]=>4}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should stop the interpreter" do
|
55
|
+
RubyPython.run do
|
56
|
+
cPickle = import "cPickle"
|
57
|
+
end
|
58
|
+
|
59
|
+
RubyPython.stop.should be_false
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
require 'ffi'
|
4
|
+
rescue LoadError
|
5
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
6
|
+
gem 'rspec'
|
7
|
+
require 'spec'
|
8
|
+
require 'ffi'
|
9
|
+
end
|
10
|
+
|
11
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
12
|
+
require 'rubypython'
|
13
|
+
|
14
|
+
module TestConstants
|
15
|
+
#REDEFINE THESE SO THEY ARE VISIBILE
|
16
|
+
AString = "STRING"
|
17
|
+
AnInt = 1
|
18
|
+
AChar = 'a'
|
19
|
+
AFloat = 1.0
|
20
|
+
AnArray = [AnInt, AChar, AFloat, AString]
|
21
|
+
ASym = :sym
|
22
|
+
AHash = {
|
23
|
+
AnInt => AnInt,
|
24
|
+
AChar.to_sym => AChar,
|
25
|
+
ASym => AFloat,
|
26
|
+
AString => AString
|
27
|
+
}
|
28
|
+
AConvertedHash = Hash[*AHash.map do |k, v|
|
29
|
+
key = k.is_a?(Symbol)? k.to_s : k
|
30
|
+
[key,v]
|
31
|
+
end.flatten]
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_python_command(cmd)
|
35
|
+
IO.popen("python -c '#{cmd}'") { |f| f.gets.chomp}
|
36
|
+
end
|
37
|
+
|
38
|
+
class RubyPython::RubyPyProxy
|
39
|
+
[:should, :should_not, :class].each { |m| reveal(m) }
|
40
|
+
end
|
41
|
+
|
42
|
+
share_as :RubyPythonStartStop do
|
43
|
+
before do
|
44
|
+
RubyPython.start
|
45
|
+
end
|
46
|
+
|
47
|
+
after do
|
48
|
+
RubyPython.stop
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|