rubypython 0.3.1 → 0.3.2
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/.rspec +2 -0
- data/History.markdown +5 -0
- data/License.txt +2 -2
- data/Manifest.txt +13 -8
- data/README.markdown +5 -3
- data/Rakefile +7 -5
- data/lib/rubypython/conversion.rb +18 -1
- data/lib/rubypython/legacy.rb +25 -0
- data/lib/rubypython/operators.rb +7 -0
- data/lib/rubypython/options.rb +69 -0
- data/lib/rubypython/pymainclass.rb +13 -2
- data/lib/rubypython/pyobject.rb +17 -5
- data/lib/rubypython/python.rb +176 -153
- data/lib/rubypython/rubypyproxy.rb +60 -14
- data/lib/rubypython/version.rb +1 -1
- data/lib/rubypython.rb +51 -5
- data/spec/callback_spec.rb +63 -0
- data/spec/conversion_spec.rb +17 -9
- data/spec/legacy_spec.rb +41 -2
- data/spec/pymainclass_spec.rb +12 -5
- data/spec/pyobject_spec.rb +44 -37
- data/spec/python_helpers/objects.py +3 -0
- data/spec/python_helpers/objects.pyc +0 -0
- data/spec/pythonerror_spec.rb +13 -6
- data/spec/refcnt_spec.rb +4 -4
- data/spec/rubypyclass_spec.rb +9 -2
- data/spec/rubypyproxy_spec.rb +55 -34
- data/spec/rubypython_spec.rb +41 -8
- data/spec/spec_helper.rb +11 -13
- data.tar.gz.sig +0 -0
- metadata +30 -12
- metadata.gz.sig +0 -0
- data/spec/spec.opts +0 -2
data/.rspec
ADDED
data/History.markdown
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
## 0.3.2 2011-02-02
|
2
|
+
* Major Enhancements
|
3
|
+
* Allow procs and methods to be passed to Ruby.
|
4
|
+
* Allow configuration of the loaded Python library.
|
5
|
+
|
1
6
|
## 0.3.1 2011-01-19
|
2
7
|
* Compatability Updates
|
3
8
|
* Cleanup of code which finds Python library thanks to Austin Ziegler.
|
data/License.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2008 Zach Raines
|
1
|
+
Copyright (c) 2008-2011 Zach Raines
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
CHANGED
@@ -4,29 +4,34 @@ Manifest.txt
|
|
4
4
|
PostInstall.txt
|
5
5
|
README.markdown
|
6
6
|
Rakefile
|
7
|
+
.rspec
|
8
|
+
lib/rubypython
|
7
9
|
lib/rubypython.rb
|
8
10
|
lib/rubypython/blankobject.rb
|
11
|
+
lib/rubypython/conversion.rb
|
12
|
+
lib/rubypython/core_ext
|
9
13
|
lib/rubypython/core_ext/string.rb
|
10
|
-
lib/rubypython/
|
14
|
+
lib/rubypython/legacy.rb
|
11
15
|
lib/rubypython/macros.rb
|
12
|
-
lib/rubypython/conversion.rb
|
13
16
|
lib/rubypython/operators.rb
|
14
|
-
lib/rubypython/
|
17
|
+
lib/rubypython/options.rb
|
15
18
|
lib/rubypython/pymainclass.rb
|
19
|
+
lib/rubypython/pyobject.rb
|
16
20
|
lib/rubypython/python.rb
|
21
|
+
lib/rubypython/pythonerror.rb
|
17
22
|
lib/rubypython/rubypyproxy.rb
|
18
23
|
lib/rubypython/version.rb
|
19
|
-
|
24
|
+
spec/callback_spec.rb
|
25
|
+
spec/conversion_spec.rb
|
26
|
+
spec/legacy_spec.rb
|
20
27
|
spec/pymainclass_spec.rb
|
21
28
|
spec/pyobject_spec.rb
|
22
29
|
spec/python_helpers
|
23
30
|
spec/python_helpers/objects.py
|
31
|
+
spec/python_helpers/objects.pyc
|
24
32
|
spec/pythonerror_spec.rb
|
33
|
+
spec/refcnt_spec.rb
|
25
34
|
spec/rubypyclass_spec.rb
|
26
35
|
spec/rubypyproxy_spec.rb
|
27
36
|
spec/rubypython_spec.rb
|
28
|
-
spec/refcnt_spec.rb
|
29
|
-
spec/conversion_spec.rb
|
30
|
-
spec/legacy_spec.rb
|
31
|
-
spec/spec.opts
|
32
37
|
spec/spec_helper.rb
|
data/README.markdown
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# RubyPython
|
2
2
|
|
3
|
-
* [RubyPython](http://
|
3
|
+
* [RubyPython](http://bitbucket.org/raineszm/rubypython/)
|
4
4
|
|
5
5
|
## DESCRIPTION:
|
6
6
|
|
@@ -17,6 +17,8 @@ provides a means for wrapping and converting Python objects.
|
|
17
17
|
* Can execute arbitrary methods on imported modules and return the result
|
18
18
|
* Python objects can be treated as Ruby objects!
|
19
19
|
* Python's standard library available to you from within Ruby.
|
20
|
+
* Pass Ruby methods and procs as callbacks and call them from within Python code.
|
21
|
+
* Specify the python executable to be loaded.
|
20
22
|
|
21
23
|
### Known Problems
|
22
24
|
|
@@ -75,13 +77,13 @@ The documentation should provide a reasonable description of how to use RubyPyth
|
|
75
77
|
Starting with version 0.3.x there are two modes of operation: normal and
|
76
78
|
legacy. These are described in the docs.
|
77
79
|
|
78
|
-
The most useful to check out [docs](http://
|
80
|
+
The most useful to check out [docs](http://rubydoc.info/gems/rubypython/) will be those for RubyPython and RubyPython::RubyPyProxy.
|
79
81
|
|
80
82
|
## LICENSE:
|
81
83
|
|
82
84
|
(The MIT License)
|
83
85
|
|
84
|
-
Copyright (c) 2008 Zach Raines
|
86
|
+
Copyright (c) 2008-2011 Zach Raines
|
85
87
|
|
86
88
|
Permission is hereby granted, free of charge, to any person obtaining
|
87
89
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
require '
|
1
|
+
require 'rspec/core/rake_task'
|
2
2
|
require 'yard'
|
3
3
|
|
4
4
|
desc "Run all examples"
|
5
|
-
|
6
|
-
t.
|
5
|
+
RSpec::Core::RakeTask.new('spec') do |t|
|
6
|
+
t.pattern = 'spec/**/*_spec.rb'
|
7
|
+
t.rspec_opts = '-t ~@slow' unless ENV['filter'] == 'none'
|
7
8
|
end
|
8
9
|
|
9
10
|
desc "Run all examples with RCov"
|
10
|
-
|
11
|
-
t.
|
11
|
+
RSpec::Core::RakeTask.new('spec:rcov') do |t|
|
12
|
+
t.pattern = 'spec/**/*.rb'
|
13
|
+
t.rspec_opts = '--tag ~slow:true' unless ENV['filter'] == 'none'
|
12
14
|
t.rcov = true
|
13
15
|
t.rcov_opts = ['--exclude', 'spec']
|
14
16
|
end
|
@@ -65,12 +65,26 @@ module RubyPython
|
|
65
65
|
Python.PyString_FromString rSymbol.to_s
|
66
66
|
end
|
67
67
|
|
68
|
+
def self.rtopProc(rObj)
|
69
|
+
pyMethodDef = Python::PyMethodDef.new
|
70
|
+
callback = Proc.new do |py_self, py_args|
|
71
|
+
ret = rObj.call(*RubyPyProxy.new(py_args).to_a)
|
72
|
+
PyObject.convert(ret)[0].pointer
|
73
|
+
end
|
74
|
+
pyMethodDef[:ml_name] = FFI::MemoryPointer.from_string "Proc::#{rObj.object_id}"
|
75
|
+
pyMethodDef[:ml_meth] = callback
|
76
|
+
pyMethodDef[:ml_flags] = Python::METH_VARARGS
|
77
|
+
pyMethodDef[:ml_doc] = nil
|
78
|
+
|
79
|
+
Python::PyCFunction_New pyMethodDef, nil
|
80
|
+
end
|
81
|
+
|
68
82
|
#If possible converts a ruby type to an equivalent
|
69
83
|
#python native type.
|
70
84
|
#@param rObj a native ruby type
|
71
85
|
#@param [Boolean] is_key whether this object will be used as a key in a
|
72
86
|
# python dict.
|
73
|
-
#@return [FFI::Pointer] a to a C PyObject\*
|
87
|
+
#@return [FFI::Pointer] a pointer to a C PyObject\*
|
74
88
|
#@raise [UnsupportedConversion]
|
75
89
|
def self.rtopObject(rObj, is_key=false)
|
76
90
|
case rObj
|
@@ -101,6 +115,9 @@ module RubyPython
|
|
101
115
|
rtopSymbol rObj
|
102
116
|
when nil
|
103
117
|
rtopNone
|
118
|
+
when Proc, Method
|
119
|
+
raise UnsupportedConversion.new("Python to Ruby callbacks not suppported in legacy mode") if RubyPython.legacy_mode
|
120
|
+
rtopProc rObj
|
104
121
|
else
|
105
122
|
raise UnsupportedConversion.new("Unsupported type for RTOP conversion." )
|
106
123
|
end
|
data/lib/rubypython/legacy.rb
CHANGED
@@ -1,5 +1,30 @@
|
|
1
1
|
require 'rubypython'
|
2
2
|
|
3
|
+
#A quick way to activate legacy mode for your project. Requiring
|
4
|
+
#'rubypython/legacy' automatically activates legacy_mode as described
|
5
|
+
#in the documentation for {RubyPython}. If you wish to run your
|
6
|
+
#project in legacy mode you can require 'rubypython/legacy' instead of
|
7
|
+
#'rubypython'
|
8
|
+
#
|
9
|
+
#@example Default Behavior
|
10
|
+
# irb(main):001:0> require 'rubypython'
|
11
|
+
# => true
|
12
|
+
# irb(main):002:0> RubyPython.start
|
13
|
+
# => true
|
14
|
+
# irb(main):003:0> RubyPython::PyMain.float(42).is_a? RubyPython::RubyPyProxy
|
15
|
+
# => true
|
16
|
+
# irb(main):004:0> RubyPython.stop
|
17
|
+
# => true
|
18
|
+
#
|
19
|
+
#@example Legacy Mode
|
20
|
+
# irb(main):001:0> require 'rubypython/legacy'
|
21
|
+
# => true
|
22
|
+
# irb(main):002:0> RubyPython.start
|
23
|
+
# => true
|
24
|
+
# irb(main):003:0> RubyPython::PyMain.float(42).is_a? Float
|
25
|
+
# => true
|
26
|
+
# irb(main):004:0> RubyPython.stop
|
27
|
+
# => true
|
3
28
|
module RubyPython::LegacyMode
|
4
29
|
class << self
|
5
30
|
def setup_legacy
|
data/lib/rubypython/operators.rb
CHANGED
@@ -107,5 +107,12 @@ module RubyPython
|
|
107
107
|
PyMain.cmp(self, other)
|
108
108
|
end
|
109
109
|
|
110
|
+
#For internal use only. Called by {RubyPython} when the
|
111
|
+
#interpreter is started or stopped so that the neccesary
|
112
|
+
#preperation or cleanup can be done.
|
113
|
+
def self.update(status)
|
114
|
+
@@operator = nil if status.equal? :stop
|
115
|
+
end
|
116
|
+
|
110
117
|
end
|
111
118
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module RubyPython
|
2
|
+
#A hash for storing RubyPython execution options.
|
3
|
+
@options = {}
|
4
|
+
|
5
|
+
#A list of options which require the Python library to be reloaded.
|
6
|
+
NEED_RELOAD = [
|
7
|
+
:python_exe,
|
8
|
+
:python_lib
|
9
|
+
]
|
10
|
+
|
11
|
+
class << self
|
12
|
+
#Allows one to set options for RubyPython's execution. Parameters
|
13
|
+
#may be set either by supplying a hash argument or by supplying
|
14
|
+
#a block and calling setters on the provided OpenStruct.
|
15
|
+
#@param [Hash] opts a hash of options to set
|
16
|
+
#@option opts [String] :python_exe The python executable for
|
17
|
+
# the python version you wish to use. Can be anything in your
|
18
|
+
# execution path as well as a local or relative path.
|
19
|
+
#@option opts [String] :python_lib The full path to the python
|
20
|
+
# library you wish to load.
|
21
|
+
#@return [Hash] a copy of the new options hash
|
22
|
+
#
|
23
|
+
#@example
|
24
|
+
# irb(main):001:0> RubyPython.run do
|
25
|
+
# irb(main):002:1* RubyPython.import('sys').version.rubify.to_f
|
26
|
+
# irb(main):003:1> end
|
27
|
+
# => 2.7
|
28
|
+
# irb(main):004:0> RubyPython.configure :python_exe => 'python2.6'
|
29
|
+
# => {:python_exe=>"python2.6"}
|
30
|
+
# irb(main):005:0> RubyPython.run do
|
31
|
+
# irb(main):006:1* RubyPython.import('sys').version.rubify.to_f
|
32
|
+
# irb(main):007:1> end
|
33
|
+
# => 2.6
|
34
|
+
#
|
35
|
+
def configure(opts={})
|
36
|
+
old_values = @options.select { |k,v| NEED_RELOAD.include? k }
|
37
|
+
|
38
|
+
if block_given?
|
39
|
+
ostruct = OpenStruct.new @options
|
40
|
+
yield ostruct
|
41
|
+
@options = Hash[*ostruct.instance_eval do
|
42
|
+
@table.map do |k, v|
|
43
|
+
[k.to_sym, v]
|
44
|
+
end.flatten
|
45
|
+
end]
|
46
|
+
end
|
47
|
+
@options.merge!(opts)
|
48
|
+
|
49
|
+
@reload = true if NEED_RELOAD.any? { |k| @options[k] != old_values[k] }
|
50
|
+
options
|
51
|
+
end
|
52
|
+
|
53
|
+
#Returns a copy of the hash currently being used to determine run
|
54
|
+
#options. This allows the user to determine what options have been
|
55
|
+
#set. Modification of options should be done via the configure
|
56
|
+
#method.
|
57
|
+
#@return [Hash] a copy of the current options hash
|
58
|
+
def options
|
59
|
+
@options.dup
|
60
|
+
end
|
61
|
+
|
62
|
+
#Reset the options hash.
|
63
|
+
#@return [void]
|
64
|
+
def clear_options
|
65
|
+
@options.clear
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -17,13 +17,13 @@ module RubyPython
|
|
17
17
|
attr_writer :main, :builtin
|
18
18
|
|
19
19
|
#@return [RubyPyModule] a proxy object wrapping the Python \__main\__
|
20
|
-
#namespace.
|
20
|
+
# namespace.
|
21
21
|
def main
|
22
22
|
@main||=RubyPython.import "__main__"
|
23
23
|
end
|
24
24
|
|
25
25
|
#@return [RubyPyModule] a proxy object wrapping the Python \__builtin\__
|
26
|
-
#namespace.
|
26
|
+
# namespace.
|
27
27
|
def builtin
|
28
28
|
@builtin||=RubyPython.import "__builtin__"
|
29
29
|
end
|
@@ -45,6 +45,17 @@ module RubyPython
|
|
45
45
|
end
|
46
46
|
block ? block.call(result) : result
|
47
47
|
end
|
48
|
+
|
49
|
+
#For internal use only. Called by {RubyPython} when the
|
50
|
+
#interpreter is started or stopped so that the neccesary
|
51
|
+
#preperation or cleanup can be done.
|
52
|
+
def update(status)
|
53
|
+
if status.equal? :stop
|
54
|
+
@main = nil
|
55
|
+
@builtin = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
48
59
|
end
|
49
60
|
|
50
61
|
PyMain = PyMainClass.instance
|
data/lib/rubypython/pyobject.rb
CHANGED
@@ -10,8 +10,6 @@ module RubyPython
|
|
10
10
|
#subclasses.
|
11
11
|
class PyObject
|
12
12
|
|
13
|
-
#@private
|
14
|
-
#
|
15
13
|
#This class wraps C PyObject\*s so that the Python reference count is
|
16
14
|
#automatically decreased when the Ruby object referencing them
|
17
15
|
#goes out of scope.
|
@@ -33,6 +31,14 @@ module RubyPython
|
|
33
31
|
Python.Py_DecRef pointer
|
34
32
|
end
|
35
33
|
end
|
34
|
+
|
35
|
+
|
36
|
+
#For internal use only. Called by {RubyPython} when the
|
37
|
+
#interpreter is started or stopped so that the neccesary
|
38
|
+
#preperation or cleanup can be done.
|
39
|
+
def update(status)
|
40
|
+
current_pointers.clear if status.equal? :stop
|
41
|
+
end
|
36
42
|
end
|
37
43
|
|
38
44
|
self.current_pointers = {}
|
@@ -123,9 +129,15 @@ module RubyPython
|
|
123
129
|
#Tests whether the wrapped object is a function or a method. This is not the
|
124
130
|
#same as {#callable?} as many other Python objects are callable.
|
125
131
|
def function_or_method?
|
126
|
-
|
127
|
-
|
128
|
-
|
132
|
+
[
|
133
|
+
Python.PyFunction_Type,
|
134
|
+
Python.PyMethod_Type,
|
135
|
+
Python.PyCFunction_Type
|
136
|
+
].each do |type|
|
137
|
+
return true if Macros.PyObject_TypeCheck(@pointer, type.to_ptr) != 0
|
138
|
+
end
|
139
|
+
|
140
|
+
false
|
129
141
|
end
|
130
142
|
|
131
143
|
#Is the wrapped object callable?
|