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.
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
+