rubypython-raspi 0.1.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/.autotest +3 -0
- data/.gitignore +18 -0
- data/.hgignore +20 -0
- data/.hgtags +10 -0
- data/.rspec +2 -0
- data/Contributors.rdoc +10 -0
- data/History.rdoc +192 -0
- data/License.rdoc +26 -0
- data/Manifest.txt +43 -0
- data/PostInstall.txt +16 -0
- data/README.rdoc +272 -0
- data/Rakefile +108 -0
- data/autotest/discover.rb +1 -0
- data/lib/rubypython.rb +284 -0
- data/lib/rubypython/blankobject.rb +23 -0
- data/lib/rubypython/conversion.rb +286 -0
- data/lib/rubypython/legacy.rb +18 -0
- data/lib/rubypython/macros.rb +56 -0
- data/lib/rubypython/operators.rb +124 -0
- data/lib/rubypython/pygenerator.rb +61 -0
- data/lib/rubypython/pymainclass.rb +80 -0
- data/lib/rubypython/pyobject.rb +232 -0
- data/lib/rubypython/python.rb +195 -0
- data/lib/rubypython/pythonerror.rb +80 -0
- data/lib/rubypython/rubypyproxy.rb +336 -0
- data/lib/rubypython/type.rb +20 -0
- data/spec/basic_spec.rb +50 -0
- data/spec/callback_spec.rb +53 -0
- data/spec/conversion_spec.rb +68 -0
- data/spec/legacy_spec.rb +46 -0
- data/spec/pymainclass_spec.rb +24 -0
- data/spec/pyobject_spec.rb +246 -0
- data/spec/python_helpers/basics.py +23 -0
- data/spec/python_helpers/errors.py +2 -0
- data/spec/python_helpers/objects.py +48 -0
- data/spec/pythonerror_spec.rb +52 -0
- data/spec/refcnt_spec.rb +62 -0
- data/spec/rubypyclass_spec.rb +10 -0
- data/spec/rubypyproxy_spec.rb +261 -0
- data/spec/rubypython_spec.rb +59 -0
- data/spec/spec_helper.rb +67 -0
- metadata +200 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
|
3
|
+
def iterate_list():
|
4
|
+
for item in [ 1, 2, 3 ]:
|
5
|
+
yield item
|
6
|
+
|
7
|
+
def identity(object):
|
8
|
+
return object
|
9
|
+
|
10
|
+
def simple_callback(callback, value):
|
11
|
+
return callback(value)
|
12
|
+
|
13
|
+
def simple_generator(callback):
|
14
|
+
output = []
|
15
|
+
for i in callback():
|
16
|
+
output.append(i)
|
17
|
+
return output
|
18
|
+
|
19
|
+
def named_args(arg1, arg2):
|
20
|
+
return [arg1, arg2]
|
21
|
+
|
22
|
+
def expects_tuple(tvalue):
|
23
|
+
return isinstance(tvalue, tuple)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
|
3
|
+
def identity(object):
|
4
|
+
return object
|
5
|
+
|
6
|
+
def apply_callback(callback, args):
|
7
|
+
return callback(*args)
|
8
|
+
|
9
|
+
def named_args(arg1, arg2):
|
10
|
+
return [arg2*2, arg1*2]
|
11
|
+
|
12
|
+
class RubyPythonMockObject:
|
13
|
+
STRING = "STRING"
|
14
|
+
STRING_LIST = ["STRING1", "STRING2"]
|
15
|
+
INT = 1
|
16
|
+
INT_LIST = [1,1]
|
17
|
+
FLOAT = 1.0
|
18
|
+
FLOAT_LIST = [1.0,1.0]
|
19
|
+
|
20
|
+
def square_elements(self, aList):
|
21
|
+
return [x**2 for x in aList]
|
22
|
+
|
23
|
+
def sum_elements(self, aList):
|
24
|
+
return sum(aList)
|
25
|
+
|
26
|
+
def __eq__(self, other):
|
27
|
+
if type(self) == type(other):
|
28
|
+
return True
|
29
|
+
else:
|
30
|
+
return False
|
31
|
+
|
32
|
+
class NewStyleClass(object):
|
33
|
+
def a_method(self):
|
34
|
+
pass
|
35
|
+
|
36
|
+
an_int = 1
|
37
|
+
a_char = 'a'
|
38
|
+
a_float = 1.0
|
39
|
+
a_symbol = 'sym'
|
40
|
+
a_string = "STRING"
|
41
|
+
a_string_with_nulls = "STRING\0WITH\0NULLS"
|
42
|
+
an_array = a_list = [an_int, a_char, a_float, a_string]
|
43
|
+
a_hash = a_dict = { an_int: an_int, a_char: a_char, a_symbol: a_float,
|
44
|
+
a_string: a_string }
|
45
|
+
true = python_True = True
|
46
|
+
false = python_False = False
|
47
|
+
nil = python_None = None
|
48
|
+
a_tuple = tuple(a_list)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe RubyPython::PythonError do
|
4
|
+
def cause_error
|
5
|
+
RubyPython::Python.PyImport_ImportModule("wat")
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#error?" do
|
9
|
+
it "should return false when no error has occured" do
|
10
|
+
described_class.error?.should be_false
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return true when an error has occured" do
|
14
|
+
cause_error
|
15
|
+
described_class.error?.should be_true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#clear" do
|
20
|
+
it "should reset the Python error flag" do
|
21
|
+
cause_error
|
22
|
+
described_class.clear
|
23
|
+
described_class.error?.should be_false
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not barf when there is no error" do
|
27
|
+
lambda {described_class.clear}.should_not raise_exception
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#fetch" do
|
32
|
+
it "should make availible Python error type" do
|
33
|
+
cause_error
|
34
|
+
rbType, rbValue, rbTraceback = described_class.fetch
|
35
|
+
rbType.getAttr("__name__").rubify.should == "ImportError"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe ".last_traceback" do
|
40
|
+
it "should make availble the Python traceback of the last error" do
|
41
|
+
traceback = RubyPython.import 'traceback'
|
42
|
+
errors = RubyPython.import 'errors'
|
43
|
+
begin
|
44
|
+
errors.nested_error
|
45
|
+
rescue RubyPython::PythonError => exc
|
46
|
+
tb = exc.traceback
|
47
|
+
list = traceback.format_tb(tb)
|
48
|
+
list.rubify[0].should =~ /1 \/ 0/
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/refcnt_spec.rb
ADDED
@@ -0,0 +1,62 @@
|
|
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
|
+
before :all do
|
19
|
+
RubyPython.start
|
20
|
+
@sys = RubyPython.import 'sys'
|
21
|
+
@sys.path.append './spec/python_helpers'
|
22
|
+
@objects = RubyPython.import 'objects'
|
23
|
+
end
|
24
|
+
|
25
|
+
after :all do
|
26
|
+
RubyPython.stop
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be one given a new object" do
|
30
|
+
pyObj = @objects.RubyPythonMockObject.new
|
31
|
+
get_refcnt(pyObj).should == 1
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should increase when a new reference is passed into Ruby" do
|
35
|
+
pyObj = @objects.RubyPythonMockObject
|
36
|
+
refcnt = get_refcnt(pyObj)
|
37
|
+
pyObj2 = @objects.RubyPythonMockObject
|
38
|
+
get_refcnt(pyObj).should == (refcnt + 1)
|
39
|
+
end
|
40
|
+
|
41
|
+
describe RubyPython::PyObject do
|
42
|
+
describe "#xIncref" do
|
43
|
+
it "should increase the reference count" do
|
44
|
+
pyObj = @objects.RubyPythonMockObject.new
|
45
|
+
refcnt = get_refcnt(pyObj)
|
46
|
+
pyObj.pObject.xIncref
|
47
|
+
get_refcnt(pyObj).should == refcnt + 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#xDecref" do
|
52
|
+
it "should decrease the reference count" do
|
53
|
+
pyObj = @objects.RubyPythonMockObject.new
|
54
|
+
pyObj.pObject.xIncref
|
55
|
+
refcnt = get_refcnt(pyObj)
|
56
|
+
pointer = pyObj.pObject.pointer
|
57
|
+
pyObj.pObject.xDecref
|
58
|
+
get_refcnt(pointer).should == refcnt - 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe RubyPython::RubyPyClass do
|
4
|
+
describe "#new" do
|
5
|
+
it "should return a RubyPyInstance" do
|
6
|
+
urllib2 = RubyPython.import 'urllib2'
|
7
|
+
urllib2.Request.new('google.com').should be_a(RubyPython::RubyPyInstance)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
include TestConstants
|
4
|
+
describe RubyPython::RubyPyProxy do
|
5
|
+
before do
|
6
|
+
@a = RubyPython::PyObject.new "a"
|
7
|
+
@b = RubyPython::PyObject.new "b"
|
8
|
+
@builtin = RubyPython.import("__builtin__").pObject
|
9
|
+
@string = RubyPython.import("string").pObject
|
10
|
+
|
11
|
+
@two = described_class.new 2
|
12
|
+
@six = described_class.new 6
|
13
|
+
|
14
|
+
@sys = RubyPython.import 'sys'
|
15
|
+
@sys.path.append './spec/python_helpers'
|
16
|
+
@objects = RubyPython.import 'objects'
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#new" do
|
20
|
+
it "should accept a PyObject instance" do
|
21
|
+
rbPyObject = RubyPython::PyObject.new AString
|
22
|
+
lambda {described_class.new rbPyObject}.should_not raise_exception
|
23
|
+
end
|
24
|
+
|
25
|
+
[
|
26
|
+
["a string", AString],
|
27
|
+
["an int", AnInt],
|
28
|
+
["a float", AFloat],
|
29
|
+
["an array", AnArray],
|
30
|
+
["a symbol", ASym, ASym.to_s],
|
31
|
+
["a hash", AHash, AConvertedHash]
|
32
|
+
].each do |arr|
|
33
|
+
type, input, output = arr
|
34
|
+
output ||= input
|
35
|
+
|
36
|
+
it "should convert #{type} to wrapped pObject" do
|
37
|
+
described_class.new(input).pObject.rubify.should == output
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#rubify" do
|
43
|
+
[
|
44
|
+
["a string", AString],
|
45
|
+
["an int", AnInt],
|
46
|
+
["a float", AFloat],
|
47
|
+
["an array", AnArray],
|
48
|
+
["a symbol", ASym],
|
49
|
+
["a hash", AHash]
|
50
|
+
].each do |title, obj|
|
51
|
+
it "should faithfully unwrap #{title}" do
|
52
|
+
pyObject = RubyPython::PyObject.new obj
|
53
|
+
proxy = described_class.new pyObject
|
54
|
+
proxy.rubify.should == pyObject.rubify
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#inspect" do
|
60
|
+
it "should return 'repr' of wrapped object" do
|
61
|
+
@six.inspect.should == '6'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should gracefully handle lack of defined __repr__" do
|
65
|
+
lambda { @objects.RubyPythonMockObject.inspect }.should_not raise_exception
|
66
|
+
end
|
67
|
+
|
68
|
+
it "always tries the 'repr' function if __repr__ produces an error" do
|
69
|
+
RubyPython::PyMain.list.inspect.should == run_python_command('print repr(list)').chomp
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#to_s" do
|
74
|
+
it "should return 'str' of wrapped object" do
|
75
|
+
@six.to_s.should == '6'
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should gracefully handle lack of defined __str__" do
|
79
|
+
lambda { @objects.RubyPythonMockObject.to_s }.should_not raise_exception
|
80
|
+
end
|
81
|
+
|
82
|
+
it "always tries the 'str' function if __repr__ produces an error" do
|
83
|
+
RubyPython::PyMain.list.to_s.should == run_python_command('print str(list)').chomp
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#to_a" do
|
88
|
+
it "should convert a list to an array of its entries" do
|
89
|
+
list = @objects.a_list
|
90
|
+
list.to_a.should == AnArray.map { |x| described_class.new(x) }
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should convert a tuple to an array of its entries" do
|
94
|
+
tuple = @objects.a_tuple
|
95
|
+
tuple.to_a.should == AnArray.map { |x| described_class.new(x) }
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should convert a dict to an array of keys" do
|
99
|
+
dict = @objects.a_dict
|
100
|
+
dict.to_a.sort.should == AConvertedHash.keys.map {|x| described_class.new(x)}.sort
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#respond_to?" do
|
105
|
+
it "should return true given getters" do
|
106
|
+
@objects.should respond_to(:RubyPythonMockObject)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return false given undefined methods" do
|
110
|
+
@objects.should_not respond_to(:undefined_attr)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should return true given any setter" do
|
114
|
+
@objects.should respond_to(:any_variable=)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return true given methods on RubyPyProxy instance" do
|
118
|
+
@objects.should respond_to(:inspect)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "method delegation" do
|
123
|
+
it "should refer method calls to wrapped object" do
|
124
|
+
aProxy = described_class.new(@a)
|
125
|
+
bProxy = described_class.new(@b)
|
126
|
+
aProxy.__add__(bProxy).rubify.should == (@a.rubify + @b.rubify)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should raise NoMethodError when method is undefined" do
|
130
|
+
aProxy = described_class.new @a
|
131
|
+
lambda {aProxy.wat}.should raise_exception(NoMethodError)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "raises NoMethodError when boolean method is undefined" do
|
135
|
+
aProxy = described_class.new @a
|
136
|
+
lambda { aProxy.wat? }.should raise_exception(NoMethodError)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should allow methods to be called with no arguments" do
|
140
|
+
builtinProxy = described_class.new @builtin
|
141
|
+
rbStrClass = builtinProxy.str
|
142
|
+
rbStrClass.new.rubify.should == String.new
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should fetch attributes when method name is an attribute" do
|
146
|
+
pyLetters = @string.getAttr "ascii_letters"
|
147
|
+
stringProxy = described_class.new @string
|
148
|
+
stringProxy.ascii_letters.rubify.should == pyLetters.rubify
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should set attribute if method call is a setter" do
|
152
|
+
stringProxy = described_class.new @string
|
153
|
+
stringProxy.letters = AString
|
154
|
+
stringProxy.letters.rubify.should == AString
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should create nonexistent attirubte if method call is a setter" do
|
158
|
+
stringProxy = described_class.new @string
|
159
|
+
stringProxy.nonExistent = 1
|
160
|
+
stringProxy.nonExistent.rubify.should == 1
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should return a class as a RubyPyClass" do
|
164
|
+
urllib2 = RubyPython.import('urllib2')
|
165
|
+
urllib2.Request.should be_a(RubyPython::RubyPyClass)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should pass named args via bang method" do
|
169
|
+
@objects.named_args!(:arg2 => 2, :arg1 => 1).rubify.should == [4,2]
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should pass through keyword arguments via bang method" do
|
173
|
+
builtinProxy = described_class.new @builtin
|
174
|
+
builtinProxy.dict!({'dict'=>'val'}, :keyword=>true).rubify.should == {
|
175
|
+
'dict' => 'val',
|
176
|
+
'keyword' => true
|
177
|
+
}
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "when used with an operator" do
|
182
|
+
[
|
183
|
+
'+', '-', '/', '*', '&', '^', '%', '**',
|
184
|
+
'>>', '<<', '<=>', '|'
|
185
|
+
].each do |op|
|
186
|
+
it "should delegate #{op}" do
|
187
|
+
@six.__send__(op, @two).rubify.should == 6.__send__(op, 2)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
[
|
192
|
+
'~', '-@', '+@'
|
193
|
+
].each do |op|
|
194
|
+
it "should delegate #{op}" do
|
195
|
+
@six.__send__(op).rubify.should == 6.__send__(op)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
['==', '<', '>', '<=', '>='].each do |op|
|
200
|
+
it "should delegate #{op}" do
|
201
|
+
@six.__send__(op, @two).should == 6.__send__(op, 2)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "#equal?" do
|
206
|
+
it "be true given proxies representing the same object" do
|
207
|
+
obj1 = @objects.RubyPythonMockObject
|
208
|
+
obj2 = @objects.RubyPythonMockObject
|
209
|
+
obj1.should equal(obj2)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should be false given objects which are different" do
|
213
|
+
@two.should_not equal(@six)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should allow list indexing" do
|
218
|
+
array = described_class.new(AnArray)
|
219
|
+
array[1].rubify.should == AnArray[1]
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should allow dict access" do
|
223
|
+
dict = described_class.new(AHash)
|
224
|
+
key = AConvertedHash.keys[0]
|
225
|
+
dict[key].rubify.should == AConvertedHash[key]
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should allow list index assignment" do
|
229
|
+
array = described_class.new(AnArray)
|
230
|
+
val = AString*2
|
231
|
+
array[1] = val
|
232
|
+
array[1].rubify.should == val
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should allow dict value modification" do
|
236
|
+
dict = described_class.new(AHash)
|
237
|
+
key = AConvertedHash.keys[0]
|
238
|
+
val = AString*2
|
239
|
+
dict[key] = val
|
240
|
+
dict[key].rubify.should == val
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should allow creation of new dict key-val pair" do
|
244
|
+
dict = described_class.new(AHash)
|
245
|
+
key = AString*2
|
246
|
+
dict[key] = AString
|
247
|
+
dict[key].rubify.should == AString
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should allow membership tests with include?" do
|
251
|
+
list = described_class.new(AnArray)
|
252
|
+
list.include?(AnArray[0]).should be_true
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should delegate object equality" do
|
257
|
+
urllib_a = RubyPython.import('urllib')
|
258
|
+
urllib_b = RubyPython.import('urllib')
|
259
|
+
urllib_a.should == urllib_b
|
260
|
+
end
|
261
|
+
end
|