rubypython 0.2.11 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data.tar.gz.sig +0 -0
  2. data/{History.txt → History.markdown} +34 -28
  3. data/Manifest.txt +26 -40
  4. data/PostInstall.txt +2 -1
  5. data/README.markdown +103 -0
  6. data/Rakefile +19 -3
  7. data/lib/rubypython.rb +118 -114
  8. data/lib/rubypython/blankobject.rb +21 -0
  9. data/lib/rubypython/conversion.rb +198 -0
  10. data/lib/rubypython/core_ext/string.rb +7 -0
  11. data/lib/rubypython/legacy.rb +15 -0
  12. data/lib/rubypython/macros.rb +47 -0
  13. data/lib/rubypython/operators.rb +111 -0
  14. data/lib/rubypython/pymainclass.rb +51 -0
  15. data/lib/rubypython/pyobject.rb +203 -0
  16. data/lib/rubypython/python.rb +111 -0
  17. data/lib/rubypython/pythonerror.rb +78 -0
  18. data/lib/rubypython/rubypyproxy.rb +214 -0
  19. data/lib/rubypython/version.rb +4 -3
  20. data/spec/conversion_spec.rb +66 -0
  21. data/spec/legacy_spec.rb +22 -0
  22. data/spec/pymainclass_spec.rb +26 -0
  23. data/spec/pyobject_spec.rb +264 -0
  24. data/spec/python_helpers/objects.py +41 -0
  25. data/spec/pythonerror_spec.rb +43 -0
  26. data/spec/refcnt_spec.rb +68 -0
  27. data/spec/rubypyclass_spec.rb +13 -0
  28. data/spec/rubypyproxy_spec.rb +249 -0
  29. data/spec/rubypython_spec.rb +62 -0
  30. data/spec/spec.opts +2 -0
  31. data/spec/spec_helper.rb +51 -0
  32. metadata +79 -73
  33. metadata.gz.sig +0 -0
  34. data/README.txt +0 -60
  35. data/ext/rubypython_bridge/cbridge.c +0 -150
  36. data/ext/rubypython_bridge/cbridge.h +0 -15
  37. data/ext/rubypython_bridge/config.h +0 -14
  38. data/ext/rubypython_bridge/extconf.rb +0 -43
  39. data/ext/rubypython_bridge/ptor.c +0 -242
  40. data/ext/rubypython_bridge/ptor.h +0 -15
  41. data/ext/rubypython_bridge/rp_blankobject.c +0 -42
  42. data/ext/rubypython_bridge/rp_blankobject.h +0 -11
  43. data/ext/rubypython_bridge/rp_class.c +0 -56
  44. data/ext/rubypython_bridge/rp_class.h +0 -7
  45. data/ext/rubypython_bridge/rp_error.c +0 -34
  46. data/ext/rubypython_bridge/rp_error.h +0 -11
  47. data/ext/rubypython_bridge/rp_function.c +0 -31
  48. data/ext/rubypython_bridge/rp_function.h +0 -7
  49. data/ext/rubypython_bridge/rp_instance.c +0 -164
  50. data/ext/rubypython_bridge/rp_instance.h +0 -7
  51. data/ext/rubypython_bridge/rp_module.c +0 -160
  52. data/ext/rubypython_bridge/rp_module.h +0 -8
  53. data/ext/rubypython_bridge/rp_object.c +0 -194
  54. data/ext/rubypython_bridge/rp_object.h +0 -23
  55. data/ext/rubypython_bridge/rp_util.c +0 -63
  56. data/ext/rubypython_bridge/rp_util.h +0 -11
  57. data/ext/rubypython_bridge/rtop.c +0 -212
  58. data/ext/rubypython_bridge/rtop.h +0 -17
  59. data/ext/rubypython_bridge/rubypython_bridge.c +0 -125
  60. data/ext/rubypython_bridge/rubypython_bridge.h +0 -10
  61. data/lib/rubypython/session.rb +0 -4
  62. data/lib/rubypython/wrapper_extensions.rb +0 -83
  63. data/setup.rb +0 -1585
  64. data/tasks/environment.rake +0 -7
  65. data/tasks/extconf.rake +0 -13
  66. data/tasks/extconf/rubypython_bridge.rake +0 -49
  67. data/test/python_helpers/objects.py +0 -12
  68. data/test/test.wav +0 -0
  69. data/test/test_helper.rb +0 -2
  70. data/test/test_rubypython.rb +0 -215
  71. data/test/test_rubypython_bridge_extn.rb +0 -133
  72. data/test/test_session.rb +0 -6
@@ -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
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format specdoc
@@ -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
+