rubypython 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -1
- data/Manifest.txt +16 -1
- data/PostInstall.txt +1 -1
- data/README.txt +7 -2
- data/config/hoe.rb +12 -12
- data/ext/rubypython_bridge/cbridge.c +92 -90
- data/ext/rubypython_bridge/cbridge.h +6 -16
- data/ext/rubypython_bridge/ptor.c +110 -56
- data/ext/rubypython_bridge/ptor.h +9 -25
- data/ext/rubypython_bridge/rp_blankobject.c +42 -0
- data/ext/rubypython_bridge/rp_blankobject.h +10 -0
- data/ext/rubypython_bridge/rp_class.c +56 -0
- data/ext/rubypython_bridge/rp_class.h +6 -0
- data/ext/rubypython_bridge/rp_error.c +14 -4
- data/ext/rubypython_bridge/rp_error.h +3 -1
- data/ext/rubypython_bridge/rp_function.c +31 -0
- data/ext/rubypython_bridge/rp_function.h +6 -0
- data/ext/rubypython_bridge/rp_instance.c +165 -0
- data/ext/rubypython_bridge/rp_instance.h +6 -0
- data/ext/rubypython_bridge/rp_module.c +159 -0
- data/ext/rubypython_bridge/rp_module.h +7 -0
- data/ext/rubypython_bridge/rp_object.c +93 -427
- data/ext/rubypython_bridge/rp_object.h +8 -54
- data/ext/rubypython_bridge/rp_util.c +61 -0
- data/ext/rubypython_bridge/rp_util.h +11 -0
- data/ext/rubypython_bridge/rtop.c +103 -54
- data/ext/rubypython_bridge/rtop.h +11 -16
- data/ext/rubypython_bridge/rubypython_bridge.c +48 -20
- data/ext/rubypython_bridge/rubypython_bridge.h +5 -6
- data/lib/rubypython.rb +2 -2
- data/lib/rubypython/session.rb +4 -0
- data/lib/rubypython/version.rb +1 -1
- data/test/python_helpers/objects.py +12 -0
- data/test/python_helpers/objects.pyc +0 -0
- data/test/test_rubypython.rb +123 -19
- data/test/test_rubypython_bridge_extn.rb +52 -19
- data/test/test_session.rb +1 -1
- data/website/index.html +25 -9
- data/website/index.txt +26 -3
- metadata +20 -5
- data/.autotest +0 -9
@@ -1,6 +1,18 @@
|
|
1
1
|
#include "rubypython_bridge.h"
|
2
2
|
|
3
|
+
#include "ptor.h" //PyObject* to VALUE conversion
|
4
|
+
#include "rtop.h" //VALUE to PyObject* conversion
|
5
|
+
#include "cbridge.h" //General interface functions
|
6
|
+
#include "rp_error.h" //Error propogation from Python to Ruby
|
7
|
+
#include "rp_object.h"
|
8
|
+
#include "rp_blankobject.h"
|
9
|
+
#include "rp_util.h"
|
10
|
+
#include "rp_module.h"
|
11
|
+
#include "rp_class.h"
|
12
|
+
#include "rp_function.h"
|
13
|
+
|
3
14
|
VALUE mRubyPythonBridge;
|
15
|
+
|
4
16
|
RUBY_EXTERN VALUE cRubyPyObject;
|
5
17
|
RUBY_EXTERN VALUE cRubyPyModule;
|
6
18
|
RUBY_EXTERN VALUE cRubyPyClass;
|
@@ -8,7 +20,8 @@ RUBY_EXTERN VALUE cBlankObject;
|
|
8
20
|
|
9
21
|
|
10
22
|
/*
|
11
|
-
call-seq: func(modname,funcname
|
23
|
+
call - seq: func(modname, funcname, *args)
|
24
|
+
|
12
25
|
Given a python module name _modname_ and a function name _funcname_ calls the given function
|
13
26
|
with the supplied arguments.
|
14
27
|
|
@@ -17,28 +30,43 @@ Use builtins as the module for a built in function.
|
|
17
30
|
*/
|
18
31
|
static VALUE func_with_module(VALUE self, VALUE args)
|
19
32
|
{
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
33
|
+
// Before doing anything we attempt to start the interpreter
|
34
|
+
// Started here will be 1 if the interpreter is started by this
|
35
|
+
// function and zero otherwise
|
36
|
+
int started_here = rpSafeStart();
|
37
|
+
|
38
|
+
VALUE module, func, return_val;
|
39
|
+
|
40
|
+
// If we hav less than two arguments we cannot proceed.
|
41
|
+
// Perhaps it would make more sense to throw an error here.
|
42
|
+
if(RARRAY_LEN(args) < 2) return Qfalse;
|
43
|
+
|
44
|
+
module = rb_ary_shift(args);
|
45
|
+
func = rb_ary_shift(args);
|
46
|
+
|
47
|
+
// rpCallWithModule is defined in cbridge.c
|
48
|
+
return_val = rpCallWithModule(module, func, args);
|
49
|
+
|
50
|
+
// If we started the interpreter, we now halt it.
|
51
|
+
rpSafeStop(started_here);
|
52
|
+
|
27
53
|
return return_val;
|
28
54
|
}
|
29
55
|
|
56
|
+
|
30
57
|
/*
|
31
|
-
* call-seq: import(modname)
|
58
|
+
* call - seq: import(modname)
|
32
59
|
*
|
33
60
|
* Imports the python module _modname_ using the interpreter and returns a ruby wrapper
|
34
61
|
*/
|
35
|
-
static VALUE rp_import(VALUE self,VALUE mname)
|
62
|
+
static VALUE rp_import(VALUE self, VALUE mname)
|
36
63
|
{
|
37
|
-
return rb_class_new_instance(1,&mname,cRubyPyModule);
|
64
|
+
return rb_class_new_instance(1,&mname, cRubyPyModule);
|
38
65
|
}
|
39
66
|
|
67
|
+
|
40
68
|
/*
|
41
|
-
* call-seq: start()
|
69
|
+
* call - seq: start()
|
42
70
|
*
|
43
71
|
* Starts the python interpreter
|
44
72
|
*/
|
@@ -51,11 +79,12 @@ VALUE rp_start(VALUE self)
|
|
51
79
|
return Qfalse;
|
52
80
|
}
|
53
81
|
Py_Initialize();
|
82
|
+
|
54
83
|
return Qtrue;
|
55
84
|
}
|
56
85
|
|
57
86
|
/*
|
58
|
-
* call-seq: stop()
|
87
|
+
* call - seq: stop()
|
59
88
|
*
|
60
89
|
* Stop the python interpreter
|
61
90
|
*/
|
@@ -77,14 +106,13 @@ VALUE rp_stop(VALUE self)
|
|
77
106
|
*
|
78
107
|
* Use RubyPython instead.
|
79
108
|
*/
|
80
|
-
|
81
109
|
void Init_rubypython_bridge()
|
82
110
|
{
|
83
|
-
mRubyPythonBridge=rb_define_module("RubyPythonBridge");
|
84
|
-
rb_define_module_function(mRubyPythonBridge,"func",func_with_module,-2);
|
85
|
-
rb_define_module_function(mRubyPythonBridge,"start",rp_start,0);
|
86
|
-
rb_define_module_function(mRubyPythonBridge,"stop",rp_stop,0);
|
87
|
-
rb_define_module_function(mRubyPythonBridge,"import",rp_import,1);
|
111
|
+
mRubyPythonBridge = rb_define_module("RubyPythonBridge");
|
112
|
+
rb_define_module_function(mRubyPythonBridge,"func", func_with_module,- 2);
|
113
|
+
rb_define_module_function(mRubyPythonBridge,"start", rp_start, 0);
|
114
|
+
rb_define_module_function(mRubyPythonBridge,"stop", rp_stop, 0);
|
115
|
+
rb_define_module_function(mRubyPythonBridge,"import", rp_import, 1);
|
88
116
|
Init_BlankObject();
|
89
117
|
Init_RubyPyObject();
|
90
118
|
Init_RubyPyModule();
|
@@ -93,4 +121,4 @@ void Init_rubypython_bridge()
|
|
93
121
|
Init_RubyPyError();
|
94
122
|
Init_RubyPyInstance();
|
95
123
|
|
96
|
-
}
|
124
|
+
}
|
@@ -1,11 +1,10 @@
|
|
1
|
+
#include "config.h"
|
2
|
+
|
1
3
|
#ifndef RUBY_19
|
4
|
+
|
5
|
+
#ifndef RARRAY_LEN
|
2
6
|
#define RARRAY_LEN(arr) (RARRAY(arr)->len)
|
3
7
|
#define RARRAY_PTR(arr) (RARRAY(arr)->ptr)
|
4
8
|
#endif
|
5
|
-
#include "config.h"
|
6
9
|
|
7
|
-
#
|
8
|
-
#include "rtop.h" //VALUE to PyObject conversion
|
9
|
-
#include "cbridge.h" //General interface functions
|
10
|
-
#include "rp_error.h"
|
11
|
-
#include "rp_object.h"
|
10
|
+
#endif
|
data/lib/rubypython.rb
CHANGED
@@ -80,7 +80,7 @@ module RubyPython
|
|
80
80
|
# RubyPython.stop
|
81
81
|
#
|
82
82
|
# Also see, _stop_
|
83
|
-
def self.start()
|
83
|
+
def self.start() #=> true||false
|
84
84
|
RubyPythonBridge.start
|
85
85
|
end
|
86
86
|
|
@@ -117,7 +117,7 @@ module RubyPython
|
|
117
117
|
# Simply starts the interpreter, runs the supplied block, and stops the interpreter.
|
118
118
|
def self.session(&block)
|
119
119
|
start
|
120
|
-
retval=block.call
|
120
|
+
retval = block.call
|
121
121
|
stop
|
122
122
|
return retval
|
123
123
|
end
|
data/lib/rubypython/version.rb
CHANGED
Binary file
|
data/test/test_rubypython.rb
CHANGED
@@ -16,86 +16,136 @@ class TestRubypython < Test::Unit::TestCase
|
|
16
16
|
def test_delegation
|
17
17
|
RubyPython.start
|
18
18
|
cPickle=RubyPython.import("cPickle")
|
19
|
-
|
20
|
-
|
19
|
+
|
20
|
+
assert_instance_of(RubyPythonBridge::RubyPyModule,
|
21
|
+
cPickle,
|
22
|
+
"Module object not returned by import.")
|
23
|
+
|
24
|
+
assert_equal({"a"=>"n", [1, "2"]=>4},
|
25
|
+
cPickle.loads("(dp1\nS'a'\nS'n'\ns(I1\nS'2'\ntp2\nI4\ns."),
|
26
|
+
"Python pickle load test returned incorrect objects.")
|
27
|
+
|
21
28
|
dumped_array=cPickle.dumps([1,2,3,4])
|
22
|
-
|
23
|
-
|
29
|
+
|
30
|
+
assert_equal([1,2,3,4],
|
31
|
+
cPickle.loads(dumped_array),
|
32
|
+
"Pickled information was not retrieved correctly.")
|
33
|
+
|
34
|
+
assert_raise(NoMethodError, "Rubypython failed to raise NoMethodError on call to nonexistent method") do
|
24
35
|
cPickle.splack
|
25
36
|
end
|
26
|
-
|
37
|
+
|
38
|
+
assert_instance_of(RubyPythonBridge::RubyPyClass,
|
39
|
+
cPickle.PicklingError,
|
40
|
+
"Wrapped Python class was not of type RubyPyClass.")
|
41
|
+
|
27
42
|
cPickle.free_pobj
|
43
|
+
|
28
44
|
ObjectSpace.each_object(RubyPythonBridge::RubyPyObject) do |o|
|
29
45
|
o.free_pobj
|
30
46
|
end
|
31
|
-
|
47
|
+
|
48
|
+
assert(RubyPython.stop,"Interpreter did not halt correctly.")
|
32
49
|
end
|
33
50
|
|
34
51
|
def test_two_imports
|
35
52
|
RubyPython.start
|
36
|
-
|
37
|
-
|
53
|
+
assert_nothing_raised("Error raised on imports") do
|
54
|
+
RubyPython.import "cPickle"
|
55
|
+
RubyPython.import "urllib"
|
56
|
+
end
|
38
57
|
RubyPython.stop
|
39
58
|
end
|
40
59
|
|
41
60
|
def test_propogate_python_error
|
42
61
|
RubyPython.start
|
43
|
-
|
62
|
+
|
63
|
+
assert_raise(PythonError,"rubypython failed to propogate python error.") do
|
44
64
|
RubyPython.import "slasdfj"
|
45
65
|
end
|
66
|
+
|
46
67
|
RubyPython.stop
|
47
68
|
end
|
48
69
|
|
49
70
|
def test_run_method
|
50
71
|
unpickled=nil
|
72
|
+
|
51
73
|
RubyPython.run do
|
52
74
|
cPickle=import "cPickle"
|
53
75
|
cPickle.inspect
|
54
76
|
unpickled=cPickle.loads("(dp1\nS'a'\nS'n'\ns(I1\nS'2'\ntp2\nI4\ns.")
|
55
77
|
end
|
56
|
-
|
57
|
-
|
78
|
+
|
79
|
+
assert_equal({"a"=>"n", [1, "2"]=>4},
|
80
|
+
unpickled,
|
81
|
+
"Incorrect object returned from cPickle.")
|
82
|
+
|
83
|
+
assert(!RubyPython.stop, "RubyPython did not seem to halt at the correct time.")
|
58
84
|
end
|
59
85
|
|
60
86
|
def test_instance_method_delegation
|
61
87
|
RubyPython.start
|
88
|
+
|
62
89
|
wave=RubyPython.import "wave"
|
63
90
|
w=wave.open("test/test.wav","rb")
|
64
|
-
assert_equal(9600,
|
91
|
+
assert_equal(9600,
|
92
|
+
w.getframerate,
|
93
|
+
"Wrapped wave library incorrectly passing framerate.")
|
65
94
|
w.close
|
95
|
+
|
66
96
|
RubyPython.stop
|
67
97
|
end
|
68
98
|
|
69
99
|
def test_pymain_delegation
|
70
100
|
RubyPython.start
|
71
|
-
|
101
|
+
|
102
|
+
assert_equal(42.to_f,
|
103
|
+
PyMain.float(42),
|
104
|
+
"Integer conversion problems in Python.")
|
105
|
+
|
72
106
|
RubyPython.stop
|
73
107
|
end
|
74
108
|
|
75
109
|
def test_block_syntax
|
76
110
|
returned=""
|
111
|
+
|
77
112
|
RubyPython.start
|
78
|
-
|
113
|
+
|
114
|
+
returned = PyMain.float(22) do |f|
|
79
115
|
f*2
|
80
116
|
end
|
81
|
-
|
117
|
+
|
118
|
+
assert_equal(44.0,
|
119
|
+
returned,
|
120
|
+
"Wrapped Python object failed to correctly utilize block syntax.")
|
121
|
+
|
82
122
|
RubyPython.stop
|
83
123
|
end
|
84
124
|
|
85
125
|
def test_session_function
|
86
126
|
RubyPython.session do
|
127
|
+
|
87
128
|
cPickle=RubyPython.import "cPickle"
|
129
|
+
|
88
130
|
cPickle.inspect
|
89
|
-
|
131
|
+
|
132
|
+
assert_equal({"a"=>"n", [1, "2"]=>4},
|
133
|
+
cPickle.loads("(dp1\nS'a'\nS'n'\ns(I1\nS'2'\ntp2\nI4\ns."),
|
134
|
+
"cPickle misbehaved in session block.")
|
90
135
|
end
|
91
136
|
end
|
92
137
|
|
93
138
|
|
94
139
|
def test_setter_ary
|
95
140
|
RubyPython.session do
|
141
|
+
|
96
142
|
sys=RubyPython.import 'sys'
|
97
|
-
|
98
|
-
|
143
|
+
|
144
|
+
sys.path=[".",".."]
|
145
|
+
|
146
|
+
assert_equal([".",".."],
|
147
|
+
sys.path,
|
148
|
+
"Ruby failed to modify Python object as expected.")
|
99
149
|
end
|
100
150
|
end
|
101
151
|
|
@@ -104,8 +154,62 @@ class TestRubypython < Test::Unit::TestCase
|
|
104
154
|
urllib2=RubyPython.import "urllib2"
|
105
155
|
req=urllib2.Request("google.com")
|
106
156
|
req.headers={:a=>"2","k"=>4}
|
107
|
-
assert_equal({"a"=>"2","k"=>4},
|
157
|
+
assert_equal({"a"=>"2","k"=>4},
|
158
|
+
req.headers,
|
159
|
+
"Python dictionary not set as expected.")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_set_twice
|
164
|
+
RubyPython.session do
|
165
|
+
sys = RubyPython.import 'sys'
|
166
|
+
|
167
|
+
sys.path = ['.']
|
168
|
+
|
169
|
+
sys.path = ['..']
|
170
|
+
|
171
|
+
assert_equal(['..'],
|
172
|
+
sys.path,
|
173
|
+
"Ruby failed to modify Python object as expected.")
|
174
|
+
|
108
175
|
end
|
109
176
|
end
|
110
177
|
|
111
178
|
end
|
179
|
+
|
180
|
+
class TestWithCustomObject < Test::Unit::TestCase
|
181
|
+
def setup
|
182
|
+
RubyPython.start
|
183
|
+
sys = RubyPython.import 'sys'
|
184
|
+
sys.path = ['./test/python_helpers']
|
185
|
+
@objects = RubyPython.import 'objects'
|
186
|
+
end
|
187
|
+
|
188
|
+
def teardown
|
189
|
+
RubyPython.stop
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_string_access
|
193
|
+
assert_equal("STRING",
|
194
|
+
@objects.RubyPythonMockObject.STRING,
|
195
|
+
"String class members not being converted correctly.")
|
196
|
+
rbString = @objects.RubyPythonMockObject.STRING
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_string_ary_access
|
200
|
+
assert_equal(["STRING1", "STRING2"],
|
201
|
+
@objects.RubyPythonMockObject.STRING_LIST,
|
202
|
+
"List of strings class member not being converted correctly.")
|
203
|
+
rbStringList = @objects.RubyPythonMockObject.STRING_LIST
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_string_ary_modify
|
207
|
+
rbStringList = @objects.RubyPythonMockObject.STRING_LIST
|
208
|
+
rbStringList.push"NEW_STRING"
|
209
|
+
@objects.RubyPythonMockObject.STRING_LIST = rbStringList
|
210
|
+
assert_equal("NEW_STRING",
|
211
|
+
@objects.RubyPythonMockObject.STRING_LIST[2],
|
212
|
+
"Failed to add object to list.")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
@@ -6,30 +6,51 @@ require "rubypython_bridge.so"
|
|
6
6
|
class TestRubyPythonBridgeExtn < Test::Unit::TestCase
|
7
7
|
|
8
8
|
def test_func_with_module
|
9
|
-
pickle_return=RubyPythonBridge.func("cPickle",
|
9
|
+
pickle_return = RubyPythonBridge.func("cPickle",
|
10
|
+
"loads", "(dp1\nS'a'\nS'n'\ns(I1\nS'2'\ntp2\nI4\ns.")
|
11
|
+
|
10
12
|
assert_equal({"a"=>"n", [1, "2"]=>4},pickle_return)
|
11
13
|
end
|
12
14
|
|
13
15
|
def test_start_stop
|
14
|
-
assert(RubyPythonBridge.start)
|
15
|
-
|
16
|
-
assert(RubyPythonBridge.
|
17
|
-
|
16
|
+
assert(RubyPythonBridge.start, "Embedded python interpreter failed to start correctly.")
|
17
|
+
|
18
|
+
assert(!RubyPythonBridge.start, "Interpreter attempted to start while running.")
|
19
|
+
|
20
|
+
assert(RubyPythonBridge.stop, "Interpreter failed to halt.")
|
21
|
+
|
22
|
+
assert(!RubyPythonBridge.stop, "Interpreter ran into trouble while halting.")
|
18
23
|
end
|
19
24
|
|
20
25
|
def test_new_instance
|
21
26
|
RubyPythonBridge.start
|
22
|
-
|
23
|
-
|
24
|
-
|
27
|
+
|
28
|
+
urllib2 = RubyPythonBridge.import "urllib2"
|
29
|
+
|
30
|
+
assert_instance_of(RubyPythonBridge::RubyPyClass,
|
31
|
+
urllib2.Request,
|
32
|
+
"Wrapped Python class not of correct type.")
|
33
|
+
|
34
|
+
assert_instance_of(RubyPythonBridge::RubyPyInstance,
|
35
|
+
urllib2.Request("google.com"),
|
36
|
+
"Wrapped python instance not of correct type.")
|
37
|
+
|
25
38
|
RubyPythonBridge.stop
|
26
39
|
end
|
27
40
|
|
28
41
|
def test_new_instance_with_new_method
|
29
42
|
RubyPythonBridge.start
|
43
|
+
|
30
44
|
urllib2=RubyPythonBridge.import "urllib2"
|
31
|
-
|
32
|
-
assert_instance_of(RubyPythonBridge::
|
45
|
+
|
46
|
+
assert_instance_of(RubyPythonBridge::RubyPyClass,
|
47
|
+
urllib2.Request,
|
48
|
+
"Wrapped Python class not of correct type.")
|
49
|
+
|
50
|
+
assert_instance_of(RubyPythonBridge::RubyPyInstance,
|
51
|
+
urllib2.Request.new("google.com"),
|
52
|
+
"New call misbehaving of wrapped class.")
|
53
|
+
|
33
54
|
RubyPythonBridge.stop
|
34
55
|
end
|
35
56
|
|
@@ -49,27 +70,39 @@ class TestRubyPythonBridgeWithCPickle < Test::Unit::TestCase
|
|
49
70
|
end
|
50
71
|
|
51
72
|
def test_mod_respond_to
|
52
|
-
assert(@cPickle.respond_to?
|
73
|
+
assert(@cPickle.respond_to?(:loads),
|
74
|
+
"Ruby respond to method not working on wrapped module.")
|
53
75
|
end
|
54
76
|
|
55
77
|
def test_data_passing
|
56
|
-
assert_equal({"a"=>"n", [1, "2"]=>4}
|
57
|
-
|
58
|
-
|
78
|
+
assert_equal({"a"=>"n", [1, "2"]=>4},
|
79
|
+
@cPickle.loads( "(dp1\nS'a'\nS'n'\ns(I1\nS'2'\ntp2\nI4\ns."),
|
80
|
+
"Data returned from wrapped cPickle is incorrect." )
|
81
|
+
|
82
|
+
orig_array = [1,2,3,4]
|
83
|
+
dumped_array = @cPickle.dumps(orig_array)
|
84
|
+
|
85
|
+
assert_equal(orig_array,
|
86
|
+
@cPickle.loads(dumped_array),
|
87
|
+
"Array returned from cPickle is not equivalent to input array.")
|
59
88
|
end
|
60
89
|
|
61
|
-
def
|
62
|
-
assert_raise NoMethodError do
|
90
|
+
def test_unknown_method
|
91
|
+
assert_raise(NoMethodError, "Missing method failed to raise NoMethodError") do
|
63
92
|
@cPickle.splack
|
64
93
|
end
|
65
94
|
end
|
66
95
|
|
67
96
|
def test_class_wrapping
|
68
|
-
assert_instance_of(RubyPythonBridge::RubyPyClass
|
97
|
+
assert_instance_of(RubyPythonBridge::RubyPyClass,
|
98
|
+
@cPickle.PicklingError,
|
99
|
+
"Wrapped class is not an instance of RubyPyClass.")
|
69
100
|
end
|
70
101
|
|
71
|
-
def
|
72
|
-
assert_instance_of(RubyPythonBridge::RubyPyModule
|
102
|
+
def test_module_wrapping
|
103
|
+
assert_instance_of(RubyPythonBridge::RubyPyModule,
|
104
|
+
@cPickle,
|
105
|
+
"Wrapped module is not of class RubyPyModule.")
|
73
106
|
end
|
74
107
|
|
75
108
|
end
|