lokeshh_rubypython 0.7
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.
- checksums.yaml +7 -0
- data/.autotest +3 -0
- data/.gitignore +18 -0
- data/.hgignore +20 -0
- data/.hgtags +12 -0
- data/.rspec +2 -0
- data/Contributors.rdoc +11 -0
- data/History.rdoc +214 -0
- data/License.rdoc +26 -0
- data/Manifest.txt +46 -0
- data/PostInstall.txt +16 -0
- data/README.rdoc +272 -0
- data/Rakefile +118 -0
- data/autotest/discover.rb +1 -0
- data/lib/rubypython/blankobject.rb +23 -0
- data/lib/rubypython/conversion.rb +332 -0
- data/lib/rubypython/interpreter.rb +262 -0
- data/lib/rubypython/macros.rb +56 -0
- data/lib/rubypython/operators.rb +120 -0
- data/lib/rubypython/pygenerator.rb +61 -0
- data/lib/rubypython/pymainclass.rb +80 -0
- data/lib/rubypython/pyobject.rb +189 -0
- data/lib/rubypython/python.rb +199 -0
- data/lib/rubypython/pythonerror.rb +80 -0
- data/lib/rubypython/rubypyproxy.rb +328 -0
- data/lib/rubypython/tuple.rb +10 -0
- data/lib/rubypython/type.rb +20 -0
- data/lib/rubypython.rb +229 -0
- data/spec/basic_spec.rb +50 -0
- data/spec/callback_spec.rb +53 -0
- data/spec/conversion_spec.rb +68 -0
- data/spec/pymainclass_spec.rb +24 -0
- data/spec/pyobject_spec.rb +202 -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 +98 -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 +71 -0
- data/website/index.rhtml +36 -0
- data/website/robots.txt +5 -0
- data/website/stylesheets/960.css +549 -0
- data/website/stylesheets/border-radius.htc +143 -0
- data/website/stylesheets/screen.css +132 -0
- metadata +297 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# -*- ruby encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'hoe'
|
|
5
|
+
|
|
6
|
+
Hoe.plugin :doofus
|
|
7
|
+
Hoe.plugin :gemspec2
|
|
8
|
+
Hoe.plugin :rubyforge unless ENV['CI'] or ENV['TRAVIS']
|
|
9
|
+
Hoe.plugin :git
|
|
10
|
+
Hoe.plugin :hg
|
|
11
|
+
Hoe.plugin :travis
|
|
12
|
+
|
|
13
|
+
Hoe.spec 'rubypython' do
|
|
14
|
+
self.rubyforge_name = self.name
|
|
15
|
+
|
|
16
|
+
developer('Steeve Morin', 'swiuzzz+rubypython@gmail.com')
|
|
17
|
+
developer('Austin Ziegler', 'austin@rubyforge.org')
|
|
18
|
+
developer('Zach Raines', 'raineszm+rubypython@gmail.com')
|
|
19
|
+
|
|
20
|
+
license 'MIT'
|
|
21
|
+
|
|
22
|
+
self.remote_rdoc_dir = 'rdoc'
|
|
23
|
+
self.rsync_args << ' --exclude=statsvn/'
|
|
24
|
+
|
|
25
|
+
self.history_file = 'History.rdoc'
|
|
26
|
+
self.readme_file = 'README.rdoc'
|
|
27
|
+
self.extra_rdoc_files = FileList["*.rdoc"].to_a
|
|
28
|
+
|
|
29
|
+
self.extra_deps << ['ffi', '~> 1.0.7']
|
|
30
|
+
self.extra_deps << ['blankslate', '>= 2.1.2.3']
|
|
31
|
+
|
|
32
|
+
self.extra_dev_deps << ['hoe-doofus', '~> 1.0']
|
|
33
|
+
self.extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
|
|
34
|
+
self.extra_dev_deps << ['hoe-git', '~> 1.5']
|
|
35
|
+
self.extra_dev_deps << ['hoe-hg', '~> 1.0']
|
|
36
|
+
self.extra_dev_deps << ['hoe-rubygems', '~> 1.0']
|
|
37
|
+
self.extra_dev_deps << ['hoe-travis', '~> 1.2']
|
|
38
|
+
|
|
39
|
+
self.extra_dev_deps << ['rspec', '~> 2.0']
|
|
40
|
+
self.extra_dev_deps << ['tilt', '~> 1.0']
|
|
41
|
+
|
|
42
|
+
self.spec_extras[:requirements] = [ "Python, ~> 2.4" ]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
namespace :website do
|
|
46
|
+
desc "Build the website files."
|
|
47
|
+
task :build => [ "website/index.html" ]
|
|
48
|
+
|
|
49
|
+
deps = FileList["website/**/*"].exclude { |f| File.directory? f }
|
|
50
|
+
deps.include(*%w(Rakefile))
|
|
51
|
+
deps.include(*FileList["*.rdoc"].to_a)
|
|
52
|
+
deps.exclude(*%w(website/index.html website/images/*))
|
|
53
|
+
|
|
54
|
+
file "website/index.html" => deps do |t|
|
|
55
|
+
require 'tilt'
|
|
56
|
+
require 'rubypython'
|
|
57
|
+
|
|
58
|
+
puts "Generating #{t.name}…"
|
|
59
|
+
|
|
60
|
+
# Let's modify the rdoc for presenation purposes.
|
|
61
|
+
body_rdoc = File.read("README.rdoc")
|
|
62
|
+
|
|
63
|
+
contrib = File.read("Contributors.rdoc")
|
|
64
|
+
body_rdoc.gsub!(/^:include: Contributors.rdoc/, contrib)
|
|
65
|
+
|
|
66
|
+
license = File.read("License.rdoc")
|
|
67
|
+
body_rdoc.sub!(/^:include: License.rdoc/, license)
|
|
68
|
+
toc_elements = body_rdoc.scan(/^(=+) (.*)$/)
|
|
69
|
+
toc_elements.map! { |e| [ e[0].count('='), e[1] ] }
|
|
70
|
+
body_rdoc.gsub!(/^(=.*)/) { "#{$1.downcase}" }
|
|
71
|
+
body = Tilt::RDocTemplate.new(nil) { body_rdoc }.render
|
|
72
|
+
|
|
73
|
+
title = nil
|
|
74
|
+
body.gsub!(%r{<h1>(.*)</h1>}) { title = $1; "" }
|
|
75
|
+
|
|
76
|
+
toc_elements = toc_elements.select { |e| e[0].between?(2, 3) }
|
|
77
|
+
|
|
78
|
+
last_level = 0
|
|
79
|
+
toc = ""
|
|
80
|
+
|
|
81
|
+
toc_elements.each do |element|
|
|
82
|
+
level, text = *element
|
|
83
|
+
ltext = text.downcase
|
|
84
|
+
id = text.downcase.gsub(/[^a-z]+/, '-')
|
|
85
|
+
|
|
86
|
+
body.gsub!(%r{<h#{level}>#{ltext}</h#{level}>}) {
|
|
87
|
+
%Q(<h#{level} id="#{id}">#{ltext}</h#{level}>)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if last_level != level
|
|
91
|
+
if level > last_level
|
|
92
|
+
toc << "<ol>"
|
|
93
|
+
else
|
|
94
|
+
toc << "</li></ol></li>"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
last_level = level
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
toc << %Q(<li><a href="##{id}">#{text}</a>)
|
|
101
|
+
end
|
|
102
|
+
toc << "</li></ol>"
|
|
103
|
+
|
|
104
|
+
template = Tilt.new("website/index.rhtml", :trim => "<>%")
|
|
105
|
+
context = {
|
|
106
|
+
:title => title,
|
|
107
|
+
:toc => toc,
|
|
108
|
+
:body => body,
|
|
109
|
+
:download => "http://rubyforge.org/frs/?group_id=6737",
|
|
110
|
+
:version => RubyPython::VERSION,
|
|
111
|
+
:modified => Time.now
|
|
112
|
+
}
|
|
113
|
+
File.open(t.name, "w") { |f| f.write template.render(self, context) } end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
task "docs" => "website:build"
|
|
117
|
+
|
|
118
|
+
# vim: syntax=ruby
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'blankslate'
|
|
2
|
+
|
|
3
|
+
# This document is the basis of the RubyPyProxy precisely because it hides
|
|
4
|
+
# the implementation of so many things that should be forwarded on to the
|
|
5
|
+
# Python object. This class is for internal use only.
|
|
6
|
+
#
|
|
7
|
+
# Note that in Ruby 1.9, BasicObject might be a better choice, but there are
|
|
8
|
+
# some decisions made in the rest of the library that make this harder. I
|
|
9
|
+
# don't see a clean way to integrate both Ruby 1.8 and 1.9 support for this.
|
|
10
|
+
class RubyPython::BlankObject < ::BlankSlate #:nodoc:
|
|
11
|
+
class << self
|
|
12
|
+
def hide(name)
|
|
13
|
+
if instance_methods.include?(name) and
|
|
14
|
+
name.to_s !~ /^(__|instance_eval|object_id)/
|
|
15
|
+
@hidden_methods ||= {}
|
|
16
|
+
@hidden_methods[name.to_sym] = instance_method(name)
|
|
17
|
+
undef_method name
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
instance_methods.each { |m| hide(m) }
|
|
23
|
+
end
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
require 'rubypython/python'
|
|
2
|
+
require 'rubypython/macros'
|
|
3
|
+
require 'numru'
|
|
4
|
+
|
|
5
|
+
# Acts as a namespace for methods to bidirectionally convert between native
|
|
6
|
+
# Ruby types and native \Python types. Unsupported conversions raise
|
|
7
|
+
# UnsupportedConversion.
|
|
8
|
+
#
|
|
9
|
+
# The methods in this module should be considered internal implementation to
|
|
10
|
+
# RubyPython as they all return FFI pointers to \Python objects.
|
|
11
|
+
module RubyPython::Conversion
|
|
12
|
+
# Raised when RubyPython does not know how to convert an object from
|
|
13
|
+
# \Python to Ruby or vice versa.
|
|
14
|
+
class UnsupportedConversion < Exception; end
|
|
15
|
+
class ConversionError < RuntimeError; end
|
|
16
|
+
|
|
17
|
+
# Convert a Ruby string to a \Python string. Returns an FFI::Pointer to
|
|
18
|
+
# a PyStringObject.
|
|
19
|
+
def self.rtopString(rString)
|
|
20
|
+
size = rString.respond_to?(:bytesize) ? rString.bytesize : rString.size
|
|
21
|
+
ptr = RubyPython::Python.PyString_FromStringAndSize(rString, size)
|
|
22
|
+
if ptr.null?
|
|
23
|
+
raise ConversionError.new "Python failed to create a string with contents #{rString}"
|
|
24
|
+
else
|
|
25
|
+
ptr
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Convert a Ruby Array to \Python List. Returns an FFI::Pointer to
|
|
30
|
+
# a PyListObject.
|
|
31
|
+
def self.rtopArrayToList(rArray)
|
|
32
|
+
size = rArray.length
|
|
33
|
+
pList = RubyPython::Python.PyList_New size
|
|
34
|
+
if pList.null?
|
|
35
|
+
raise ConversionError.new "Python failed to create list of size #{size}"
|
|
36
|
+
end
|
|
37
|
+
rArray.each_with_index do |el, i|
|
|
38
|
+
# PyList_SetItem steals a reference, but rtopObject creates a new reference
|
|
39
|
+
# So we wind up with giving a new reference to the Python interpreter for every
|
|
40
|
+
# object
|
|
41
|
+
ret = RubyPython::Python.PyList_SetItem pList, i, rtopObject(el)
|
|
42
|
+
raise ConversionError.new "Failed to set item #{el} in array conversion" if ret == -1
|
|
43
|
+
end
|
|
44
|
+
pList
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Convert a Ruby Array (including the subclass RubyPython::Tuple) to
|
|
48
|
+
# \Python \tuple. Returns an FFI::Pointer to a PyTupleObject.
|
|
49
|
+
def self.rtopArrayToTuple(rArray)
|
|
50
|
+
pList = rtopArrayToList(rArray)
|
|
51
|
+
pTuple = RubyPython::Python.PyList_AsTuple(pList)
|
|
52
|
+
RubyPython::Python.Py_DecRef(pList)
|
|
53
|
+
if pTuple.null?
|
|
54
|
+
raise Conversion.new "Python failed to convert an intermediate list of #{rArray} to a tuple"
|
|
55
|
+
end
|
|
56
|
+
pTuple
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Convert a Ruby Hash to a \Python Dict. Returns an FFI::Pointer to a
|
|
60
|
+
# PyDictObject.
|
|
61
|
+
def self.rtopHash(rHash)
|
|
62
|
+
pDict = RubyPython::Python.PyDict_New
|
|
63
|
+
if pDict.null?
|
|
64
|
+
raise ConversionError.new "Python failed to create new dict"
|
|
65
|
+
end
|
|
66
|
+
rHash.each do |k,v|
|
|
67
|
+
key = rtopObject(k, :key => true)
|
|
68
|
+
value = rtopObject(v)
|
|
69
|
+
|
|
70
|
+
# PyDict_SetItem INCREFS both the key and the value passed to it.
|
|
71
|
+
# Since rtopObject already gives us a new reference, this is not necessary.
|
|
72
|
+
# Thus, we decref the passed in objects to balancy things out
|
|
73
|
+
if RubyPython::Python.PyDict_SetItem(pDict, key, value) == -1
|
|
74
|
+
raise ConversionError.new "Python failed to set #{key}, #{value} in dict conversion"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
RubyPython::Python.Py_DecRef key
|
|
78
|
+
RubyPython::Python.Py_DecRef value
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
pDict
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Convert a Ruby Fixnum to a \Python Int. Returns an FFI::Pointer to a
|
|
85
|
+
# PyIntObject.
|
|
86
|
+
def self.rtopFixnum(rNum)
|
|
87
|
+
num = RubyPython::Python.PyInt_FromLong(rNum)
|
|
88
|
+
raise ConversionError.new "Failed to convert #{rNum}" if num.null?
|
|
89
|
+
num
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Convert a Ruby Bignum to a \Python Long. Returns an FFI::Pointer to a
|
|
93
|
+
# PyLongObject.
|
|
94
|
+
def self.rtopBigNum(rNum)
|
|
95
|
+
num = RubyPython::Python.PyLong_FromLongLong(rNum)
|
|
96
|
+
raise ConversionError.new "Failed to convert #{rNum}" if num.null?
|
|
97
|
+
num
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Convert a Ruby float to a \Python Float. Returns an FFI::Pointer to a
|
|
101
|
+
# PyFloatObject.
|
|
102
|
+
def self.rtopFloat(rNum)
|
|
103
|
+
num = RubyPython::Python.PyFloat_FromDouble(rNum)
|
|
104
|
+
raise ConversionError.new "Failed to convert #{rNum}" if num.null?
|
|
105
|
+
num
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Returns a \Python False value (equivalent to Ruby's +false+). Returns an
|
|
109
|
+
# FFI::Pointer to Py_ZeroStruct.
|
|
110
|
+
def self.rtopFalse
|
|
111
|
+
RubyPython::Macros.Py_RETURN_FALSE
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Returns a \Python True value (equivalent to Ruby's +true+). Returns an
|
|
115
|
+
# FFI::Pointer to Py_TrueStruct.
|
|
116
|
+
def self.rtopTrue
|
|
117
|
+
RubyPython::Macros.Py_RETURN_TRUE
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Returns a \Python None value (equivalent to Ruby's +nil+). Returns an
|
|
121
|
+
# FFI::Pointer to Py_NoneStruct.
|
|
122
|
+
def self.rtopNone
|
|
123
|
+
RubyPython::Macros.Py_RETURN_NONE
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Convert a Ruby Symbol to a \Python String. Returns an FFI::Pointer to a
|
|
127
|
+
# PyStringObject.
|
|
128
|
+
def self.rtopSymbol(rSymbol)
|
|
129
|
+
rtopString rSymbol.to_s
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Convert a Ruby Proc to a \Python Function. Returns an FFI::Pointer to a
|
|
133
|
+
# PyCFunction.
|
|
134
|
+
def self.rtopFunction(rObj)
|
|
135
|
+
proc = ::FFI::Function.new(:pointer, [:pointer, :pointer]) do |p_self, p_args|
|
|
136
|
+
retval = rObj.call(*ptorTuple(p_args))
|
|
137
|
+
pObject = retval.is_a?(RubyPython::RubyPyProxy) ? retval.pObject : RubyPython::PyObject.new(retval)
|
|
138
|
+
|
|
139
|
+
# make sure the refcount is >1 when pObject is destroyed
|
|
140
|
+
pObject.xIncref
|
|
141
|
+
pObject.pointer
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
defn = RubyPython::Python::PyMethodDef.new
|
|
145
|
+
defn[:ml_name] = ::FFI::MemoryPointer.from_string("RubyPython::Proc::%s" % rObj.object_id)
|
|
146
|
+
defn[:ml_meth] = proc
|
|
147
|
+
defn[:ml_flags] = RubyPython::Python::METH_VARARGS
|
|
148
|
+
defn[:ml_doc] = nil
|
|
149
|
+
|
|
150
|
+
return RubyPython::Python.PyCFunction_New(defn, nil)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# This will attempt to convert a Ruby object to an equivalent \Python
|
|
154
|
+
# native type. Returns an FFI::Pointer to a \Python object (the
|
|
155
|
+
# appropriate Py_Object C structure). If the conversion is unsuccessful,
|
|
156
|
+
# will raise UnsupportedConversion.
|
|
157
|
+
#
|
|
158
|
+
# [rObj] A native Ruby object.
|
|
159
|
+
# [is_key] Set to +true+ if the provided Ruby object will be used as a
|
|
160
|
+
# key in a \Python +dict+. (This primarily matters for Array
|
|
161
|
+
# conversion.)
|
|
162
|
+
def self.rtopObject(rObj, is_key = false)
|
|
163
|
+
case rObj
|
|
164
|
+
when String
|
|
165
|
+
rtopString rObj
|
|
166
|
+
when RubyPython::Tuple
|
|
167
|
+
rtopArrayToTuple rObj
|
|
168
|
+
when Array
|
|
169
|
+
# If this object is going to be used as a hash key we should make it a
|
|
170
|
+
# tuple instead of a list
|
|
171
|
+
if is_key
|
|
172
|
+
rtopArrayToTuple rObj
|
|
173
|
+
else
|
|
174
|
+
rtopArrayToList rObj
|
|
175
|
+
end
|
|
176
|
+
when Hash
|
|
177
|
+
rtopHash rObj
|
|
178
|
+
when Fixnum
|
|
179
|
+
rtopFixnum rObj
|
|
180
|
+
when Bignum
|
|
181
|
+
rtopBignum rObj
|
|
182
|
+
when Float
|
|
183
|
+
rtopFloat rObj
|
|
184
|
+
when true
|
|
185
|
+
rtopTrue
|
|
186
|
+
when false
|
|
187
|
+
rtopFalse
|
|
188
|
+
when Symbol
|
|
189
|
+
rtopSymbol rObj
|
|
190
|
+
when Proc, Method
|
|
191
|
+
rtopFunction rObj
|
|
192
|
+
when nil
|
|
193
|
+
rtopNone
|
|
194
|
+
when RubyPython::PyObject
|
|
195
|
+
rObj.xIncref
|
|
196
|
+
rObj.pointer
|
|
197
|
+
when RubyPython::RubyPyProxy
|
|
198
|
+
rtopObject(rObj.pObject, is_key)
|
|
199
|
+
when NumRu
|
|
200
|
+
rtopObject(rObj.np_obj)
|
|
201
|
+
else
|
|
202
|
+
raise UnsupportedConversion.new("Unsupported type #{rObj.class} for conversion.")
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Convert an FFI::Pointer to a \Python String (PyStringObject) to a Ruby
|
|
207
|
+
# String.
|
|
208
|
+
def self.ptorString(pString)
|
|
209
|
+
#strPtr is a pointer to a pointer to the internal character array.
|
|
210
|
+
#FFI will free strPtr when we are done but the internal array MUST
|
|
211
|
+
#not be modified
|
|
212
|
+
strPtr = ::FFI::MemoryPointer.new(:pointer)
|
|
213
|
+
sizePtr = ::FFI::MemoryPointer.new(:ssize_t)
|
|
214
|
+
|
|
215
|
+
RubyPython::Python.PyString_AsStringAndSize(pString, strPtr, sizePtr)
|
|
216
|
+
|
|
217
|
+
size = case ::FFI.find_type(:ssize_t)
|
|
218
|
+
when ::FFI.find_type(:long)
|
|
219
|
+
sizePtr.read_long
|
|
220
|
+
when ::FFI.find_type(:int)
|
|
221
|
+
sizePtr.read_int
|
|
222
|
+
when ::FFI.find_type(:long_long)
|
|
223
|
+
sizePtr.read_long_long
|
|
224
|
+
else
|
|
225
|
+
nil
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
strPtr.read_pointer.read_string(size)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Convert an FFI::Pointer to a \Python List (PyListObject) to a Ruby
|
|
232
|
+
# Array.
|
|
233
|
+
def self.ptorList(pList)
|
|
234
|
+
rb_array = []
|
|
235
|
+
list_size = RubyPython::Python.PyList_Size(pList)
|
|
236
|
+
|
|
237
|
+
list_size.times do |i|
|
|
238
|
+
element = RubyPython::Python.PyList_GetItem(pList, i)
|
|
239
|
+
rObject = ptorObject(element)
|
|
240
|
+
rb_array.push rObject
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
rb_array
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Convert an FFI::Pointer to a \Python Int (PyIntObject) to a Ruby Fixnum.
|
|
247
|
+
def self.ptorInt(pNum)
|
|
248
|
+
RubyPython::Python.PyInt_AsLong(pNum)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Convert an FFI::Pointer to a \Python Long (PyLongObject) to a Ruby
|
|
252
|
+
# Fixnum. This version does not do overflow checking, but probably should.
|
|
253
|
+
def self.ptorLong(pNum)
|
|
254
|
+
RubyPython::Python.PyLong_AsLong(pNum)
|
|
255
|
+
# TODO Overflow Checking
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Convert an FFI::Pointer to a \Python Float (PyFloatObject) to a Ruby
|
|
259
|
+
# Float.
|
|
260
|
+
def self.ptorFloat(pNum)
|
|
261
|
+
RubyPython::Python.PyFloat_AsDouble(pNum)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Convert an FFI::Pointer to a \Python Tuple (PyTupleObject) to an
|
|
265
|
+
# instance of RubyPython::Tuple, a subclass of the Ruby Array class.
|
|
266
|
+
def self.ptorTuple(pTuple)
|
|
267
|
+
#PySequence_List returns a new list. Since we are only using it as a temporary
|
|
268
|
+
#here, we will have to DecRef it once we are done.
|
|
269
|
+
pList = RubyPython::Python.PySequence_List pTuple
|
|
270
|
+
rArray = ptorList pList
|
|
271
|
+
RubyPython::Python.Py_DecRef pList
|
|
272
|
+
RubyPython::Tuple.tuple(rArray)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Convert an FFI::Pointer to a \Python Dictionary (PyDictObject) to a Ruby
|
|
276
|
+
# Hash.
|
|
277
|
+
def self.ptorDict(pDict)
|
|
278
|
+
rb_hash = {}
|
|
279
|
+
|
|
280
|
+
pos = ::FFI::MemoryPointer.new :ssize_t
|
|
281
|
+
pos.write_int 0
|
|
282
|
+
key = ::FFI::MemoryPointer.new :pointer
|
|
283
|
+
val = ::FFI::MemoryPointer.new :pointer
|
|
284
|
+
|
|
285
|
+
while RubyPython::Python.PyDict_Next(pDict, pos, key, val) != 0
|
|
286
|
+
#PyDict_Next sets key and val to borrowed references. We do not care
|
|
287
|
+
#if we are able to convert them to native ruby types, but if we wind up
|
|
288
|
+
#wrapping either in a proxy we better IncRef it to make sure it stays
|
|
289
|
+
#around.
|
|
290
|
+
pKey = key.read_pointer
|
|
291
|
+
pVal = val.read_pointer
|
|
292
|
+
rKey = ptorObject(pKey)
|
|
293
|
+
rVal = ptorObject(pVal)
|
|
294
|
+
RubyPython.Py_IncRef pKey if rKey.kind_of? ::FFI::Pointer
|
|
295
|
+
RubyPython.Py_IncRef pVal if rVal.kind_of? ::FFI::Pointer
|
|
296
|
+
rb_hash[rKey] = rVal
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
rb_hash
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Converts a pointer to a \Python object into a native Ruby type, if
|
|
303
|
+
# possible. If the conversion cannot be done, the Python object will be
|
|
304
|
+
# returned unmodified.
|
|
305
|
+
#
|
|
306
|
+
# [pObj] An FFI::Pointer to a \Python object.
|
|
307
|
+
def self.ptorObject(pObj)
|
|
308
|
+
if RubyPython::Macros.PyObject_TypeCheck(pObj, RubyPython::Python.PyString_Type.to_ptr) != 0
|
|
309
|
+
ptorString pObj
|
|
310
|
+
elsif RubyPython::Macros.PyObject_TypeCheck(pObj, RubyPython::Python.PyList_Type.to_ptr) != 0
|
|
311
|
+
ptorList pObj
|
|
312
|
+
elsif RubyPython::Macros.PyObject_TypeCheck(pObj, RubyPython::Python.PyInt_Type.to_ptr) != 0
|
|
313
|
+
ptorInt pObj
|
|
314
|
+
elsif RubyPython::Macros.PyObject_TypeCheck(pObj, RubyPython::Python.PyLong_Type.to_ptr) != 0
|
|
315
|
+
ptorLong pObj
|
|
316
|
+
elsif RubyPython::Macros.PyObject_TypeCheck(pObj, RubyPython::Python.PyFloat_Type.to_ptr) != 0
|
|
317
|
+
ptorFloat pObj
|
|
318
|
+
elsif RubyPython::Macros.PyObject_TypeCheck(pObj, RubyPython::Python.PyTuple_Type.to_ptr) != 0
|
|
319
|
+
ptorTuple pObj
|
|
320
|
+
elsif RubyPython::Macros.PyObject_TypeCheck(pObj, RubyPython::Python.PyDict_Type.to_ptr) != 0
|
|
321
|
+
ptorDict pObj
|
|
322
|
+
elsif pObj == RubyPython::Macros.Py_True
|
|
323
|
+
true
|
|
324
|
+
elsif pObj == RubyPython::Macros.Py_False
|
|
325
|
+
false
|
|
326
|
+
elsif pObj == RubyPython::Macros.Py_None
|
|
327
|
+
nil
|
|
328
|
+
else
|
|
329
|
+
pObj
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|