rubypython 0.6.2 → 0.6.3

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.
@@ -5,6 +5,10 @@ require 'rubypython/interpreter'
5
5
  module RubyPython
6
6
  # This module will hold the loaded RubyPython interpreter.
7
7
  module Python #:nodoc: all
8
+ @lock = Mutex.new
9
+ def self.synchronize(&block)
10
+ @lock.synchronize(&block)
11
+ end
8
12
  end
9
13
  end
10
14
 
@@ -13,183 +17,181 @@ class RubyPython::Interpreter
13
17
  # has been infected, the #infect! method is removed from
14
18
  # RubyPython::Interpreter.
15
19
  def infect!(mod)
16
- Mutex.new.synchronize do
17
- self.class.class_eval do
18
- undef :infect!
19
- end
20
-
21
- mod.extend ::FFI::Library
22
- # FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL
23
- mod.ffi_lib_flags :lazy, :global
24
- mod.ffi_lib self.library
25
-
26
- # This class is a little bit of a hack to extract the address of
27
- # global structs. If someone knows a better way please let me know.
28
- mod.module_eval do
29
- self.const_set :DummyStruct, Class.new(::FFI::Struct)
30
- self::DummyStruct.layout :dummy_var, :int
31
-
32
- self.const_set(:PY_FILE_INPUT, 257)
33
- self.const_set(:PY_EVAL_INPUT, 258)
34
- self.const_set(:METH_VARARGS, 0x0001)
35
-
36
- # Function methods & constants
37
- attach_function :PyCFunction_New, [:pointer, :pointer], :pointer
38
- callback :PyCFunction, [:pointer, :pointer], :pointer
39
-
40
- attach_function :PyRun_String, [:string, :int, :pointer, :pointer], :pointer
41
- attach_function :PyRun_SimpleString, [:string], :pointer
42
- attach_function :Py_CompileString, [:string, :string, :int], :pointer
43
- attach_function :PyEval_EvalCode, [:pointer, :pointer, :pointer], :pointer
44
- attach_function :PyErr_SetString, [:pointer, :string], :void
45
-
46
- # Python interpreter startup and shutdown
47
- attach_function :Py_IsInitialized, [], :int
48
- attach_function :Py_Initialize, [], :void
49
- attach_function :Py_Finalize, [], :void
50
-
51
- # Module methods
52
- attach_function :PyImport_ImportModule, [:string], :pointer
53
-
54
- # Object Methods
55
- attach_function :PyObject_HasAttrString, [:pointer, :string], :int
56
- attach_function :PyObject_GetAttrString, [:pointer, :string], :pointer
57
- attach_function :PyObject_SetAttrString, [:pointer, :string, :pointer], :int
58
- attach_function :PyObject_Dir, [:pointer], :pointer
59
-
60
- attach_function :PyObject_Compare, [:pointer, :pointer], :int
61
-
62
- attach_function :PyObject_Call, [:pointer, :pointer, :pointer], :pointer
63
- attach_function :PyObject_CallObject, [:pointer, :pointer], :pointer
64
- attach_function :PyCallable_Check, [:pointer], :int
65
-
66
- ### Python To Ruby Conversion
67
- # String Methods
68
- attach_function :PyString_AsString, [:pointer], :string
69
- attach_function :PyString_FromString, [:string], :pointer
70
- attach_function :PyString_AsStringAndSize, [:pointer, :pointer, :pointer], :int
71
- attach_function :PyString_FromStringAndSize, [:buffer_in, :ssize_t], :pointer
72
-
73
- # List Methods
74
- attach_function :PyList_GetItem, [:pointer, :int], :pointer
75
- attach_function :PyList_Size, [:pointer], :int
76
- attach_function :PyList_New, [:int], :pointer
77
- attach_function :PyList_SetItem, [:pointer, :int, :pointer], :void
78
-
79
- # Integer Methods
80
- attach_function :PyInt_AsLong, [:pointer], :long
81
- attach_function :PyInt_FromLong, [:long], :pointer
82
-
83
- attach_function :PyLong_AsLong, [:pointer], :long
84
- attach_function :PyLong_FromLong, [:pointer], :long
85
-
86
- # Float Methods
87
- attach_function :PyFloat_AsDouble, [:pointer], :double
88
- attach_function :PyFloat_FromDouble, [:double], :pointer
89
-
90
- # Tuple Methods
91
- attach_function :PySequence_List, [:pointer], :pointer
92
- attach_function :PySequence_Tuple, [:pointer], :pointer
93
- attach_function :PyTuple_Pack, [:int, :varargs], :pointer
94
-
95
- # Dict/Hash Methods
96
- attach_function :PyDict_Next, [:pointer, :pointer, :pointer, :pointer], :int
97
- attach_function :PyDict_New, [], :pointer
98
- attach_function :PyDict_SetItem, [:pointer, :pointer, :pointer], :int
99
- attach_function :PyDict_Contains, [:pointer, :pointer], :int
100
- attach_function :PyDict_GetItem, [:pointer, :pointer], :pointer
101
-
102
- # Error Methods
103
- attach_variable :PyExc_Exception, self::DummyStruct.by_ref
104
- attach_variable :PyExc_StopIteration, self::DummyStruct.by_ref
105
- attach_function :PyErr_SetNone, [:pointer], :void
106
- attach_function :PyErr_Fetch, [:pointer, :pointer, :pointer], :void
107
- attach_function :PyErr_Occurred, [], :pointer
108
- attach_function :PyErr_Clear, [], :void
109
-
110
- # Reference Counting
111
- attach_function :Py_IncRef, [:pointer], :void
112
- attach_function :Py_DecRef, [:pointer], :void
113
-
114
- # Type Objects
115
- # attach_variable :PyBaseObject_Type, self::DummyStruct.by_value # built-in 'object'
116
- # attach_variable :PyBaseString_Type, self::DummyStruct.by_value
117
- # attach_variable :PyBool_Type, self::DummyStruct.by_value
118
- # attach_variable :PyBuffer_Type, self::DummyStruct.by_value
119
- # attach_variable :PyByteArrayIter_Type, self::DummyStruct.by_value
120
- # attach_variable :PyByteArray_Type, self::DummyStruct.by_value
121
- attach_variable :PyCFunction_Type, self::DummyStruct.by_value
122
- # attach_variable :PyCObject_Type, self::DummyStruct.by_value
123
- # attach_variable :PyCallIter_Type, self::DummyStruct.by_value
124
- # attach_variable :PyCapsule_Type, self::DummyStruct.by_value
125
- # attach_variable :PyCell_Type, self::DummyStruct.by_value
126
- # attach_variable :PyClassMethod_Type, self::DummyStruct.by_value
127
- attach_variable :PyClass_Type, self::DummyStruct.by_value
128
- # attach_variable :PyCode_Type, self::DummyStruct.by_value
129
- # attach_variable :PyComplex_Type, self::DummyStruct.by_value
130
- # attach_variable :PyDictItems_Type, self::DummyStruct.by_value
131
- # attach_variable :PyDictIterItem_Type, self::DummyStruct.by_value
132
- # attach_variable :PyDictIterKey_Type, self::DummyStruct.by_value
133
- # attach_variable :PyDictIterValue_Type, self::DummyStruct.by_value
134
- # attach_variable :PyDictKeys_Type, self::DummyStruct.by_value
135
- # attach_variable :PyDictProxy_Type, self::DummyStruct.by_value
136
- # attach_variable :PyDictValues_Type, self::DummyStruct.by_value
137
- attach_variable :PyDict_Type, self::DummyStruct.by_value
138
- # attach_variable :PyEllipsis_Type, self::DummyStruct.by_value
139
- # attach_variable :PyEnum_Type, self::DummyStruct.by_value
140
- # attach_variable :PyFile_Type, self::DummyStruct.by_value
141
- attach_variable :PyFloat_Type, self::DummyStruct.by_value
142
- # attach_variable :PyFrame_Type, self::DummyStruct.by_value
143
- # attach_variable :PyFrozenSet_Type, self::DummyStruct.by_value
144
- attach_variable :PyFunction_Type, self::DummyStruct.by_value
145
- # attach_variable :PyGen_Type, self::DummyStruct.by_value
146
- # attach_variable :PyGetSetDescr_Type, self::DummyStruct.by_value
147
- # attach_variable :PyInstance_Type, self::DummyStruct.by_value
148
- attach_variable :PyInt_Type, self::DummyStruct.by_value
149
- attach_variable :PyList_Type, self::DummyStruct.by_value
150
- attach_variable :PyLong_Type, self::DummyStruct.by_value
151
- # attach_variable :PyMemberDescr_Type, self::DummyStruct.by_value
152
- # attach_variable :PyMemoryView_Type, self::DummyStruct.by_value
153
- attach_variable :PyMethod_Type, self::DummyStruct.by_value
154
- # attach_variable :PyModule_Type, self::DummyStruct.by_value
155
- # attach_variable :PyNullImporter_Type, self::DummyStruct.by_value
156
- # attach_variable :PyProperty_Type, self::DummyStruct.by_value
157
- # attach_variable :PyRange_Type, self::DummyStruct.by_value
158
- # attach_variable :PyReversed_Type, self::DummyStruct.by_value
159
- # attach_variable :PySTEntry_Type, self::DummyStruct.by_value
160
- # attach_variable :PySeqIter_Type, self::DummyStruct.by_value
161
- # attach_variable :PySet_Type, self::DummyStruct.by_value
162
- # attach_variable :PySlice_Type, self::DummyStruct.by_value
163
- # attach_variable :PyStaticMethod_Type, self::DummyStruct.by_value
164
- attach_variable :PyString_Type, self::DummyStruct.by_value
165
- # attach_variable :PySuper_Type, self::DummyStruct.by_value # built-in 'super'
166
- # attach_variable :PyTraceBack_Type, self::DummyStruct.by_value
167
- attach_variable :PyTuple_Type, self::DummyStruct.by_value
168
- attach_variable :PyType_Type, self::DummyStruct.by_value
169
- # attach_variable :PyUnicode_Type, self::DummyStruct.by_value
170
- # attach_variable :PyWrapperDescr_Type, self::DummyStruct.by_value
171
-
172
- attach_variable :Py_TrueStruct, :_Py_TrueStruct, self::DummyStruct.by_value
173
- attach_variable :Py_ZeroStruct, :_Py_ZeroStruct, self::DummyStruct.by_value
174
- attach_variable :Py_NoneStruct, :_Py_NoneStruct, self::DummyStruct.by_value
175
-
176
- # This is an implementation of the basic structure of a Python PyObject
177
- # struct. The C struct is actually much larger, but since we only access
178
- # the first two data members via FFI and always deal with struct
179
- # pointers there is no need to mess around with the rest of the object.
180
- self.const_set :PyObjectStruct, Class.new(::FFI::Struct)
181
- self::PyObjectStruct.layout :ob_refcnt, :ssize_t,
182
- :ob_type, :pointer
183
-
184
- # This struct is used when defining Python methods.
185
- self.const_set :PyMethodDef, Class.new(::FFI::Struct)
186
- self::PyMethodDef.layout :ml_name, :pointer,
187
- :ml_meth, :PyCFunction,
188
- :ml_flags, :int,
189
- :ml_doc, :pointer
190
- end
20
+ self.class.class_eval do
21
+ undef :infect!
22
+ end
191
23
 
24
+ mod.extend ::FFI::Library
25
+ # FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL
26
+ mod.ffi_lib_flags :lazy, :global
27
+ mod.ffi_lib self.library
28
+
29
+ # This class is a little bit of a hack to extract the address of
30
+ # global structs. If someone knows a better way please let me know.
31
+ mod.module_eval do
32
+ self.const_set :DummyStruct, Class.new(::FFI::Struct)
33
+ self::DummyStruct.layout :dummy_var, :int
34
+
35
+ self.const_set(:PY_FILE_INPUT, 257)
36
+ self.const_set(:PY_EVAL_INPUT, 258)
37
+ self.const_set(:METH_VARARGS, 0x0001)
38
+
39
+ # Function methods & constants
40
+ attach_function :PyCFunction_New, [:pointer, :pointer], :pointer
41
+ callback :PyCFunction, [:pointer, :pointer], :pointer
42
+
43
+ attach_function :PyRun_String, [:string, :int, :pointer, :pointer], :pointer
44
+ attach_function :PyRun_SimpleString, [:string], :pointer
45
+ attach_function :Py_CompileString, [:string, :string, :int], :pointer
46
+ attach_function :PyEval_EvalCode, [:pointer, :pointer, :pointer], :pointer
47
+ attach_function :PyErr_SetString, [:pointer, :string], :void
48
+
49
+ # Python interpreter startup and shutdown
50
+ attach_function :Py_IsInitialized, [], :int
51
+ attach_function :Py_Initialize, [], :void
52
+ attach_function :Py_Finalize, [], :void
53
+
54
+ # Module methods
55
+ attach_function :PyImport_ImportModule, [:string], :pointer
56
+
57
+ # Object Methods
58
+ attach_function :PyObject_HasAttrString, [:pointer, :string], :int
59
+ attach_function :PyObject_GetAttrString, [:pointer, :string], :pointer
60
+ attach_function :PyObject_SetAttrString, [:pointer, :string, :pointer], :int
61
+ attach_function :PyObject_Dir, [:pointer], :pointer
62
+
63
+ attach_function :PyObject_Compare, [:pointer, :pointer], :int
64
+
65
+ attach_function :PyObject_Call, [:pointer, :pointer, :pointer], :pointer
66
+ attach_function :PyObject_CallObject, [:pointer, :pointer], :pointer
67
+ attach_function :PyCallable_Check, [:pointer], :int
68
+
69
+ ### Python To Ruby Conversion
70
+ # String Methods
71
+ attach_function :PyString_AsString, [:pointer], :string
72
+ attach_function :PyString_FromString, [:string], :pointer
73
+ attach_function :PyString_AsStringAndSize, [:pointer, :pointer, :pointer], :int
74
+ attach_function :PyString_FromStringAndSize, [:buffer_in, :ssize_t], :pointer
75
+
76
+ # List Methods
77
+ attach_function :PyList_GetItem, [:pointer, :int], :pointer
78
+ attach_function :PyList_Size, [:pointer], :int
79
+ attach_function :PyList_New, [:int], :pointer
80
+ attach_function :PyList_SetItem, [:pointer, :int, :pointer], :void
81
+
82
+ # Integer Methods
83
+ attach_function :PyInt_AsLong, [:pointer], :long
84
+ attach_function :PyInt_FromLong, [:long], :pointer
85
+
86
+ attach_function :PyLong_AsLong, [:pointer], :long
87
+ attach_function :PyLong_FromLong, [:pointer], :long
88
+
89
+ # Float Methods
90
+ attach_function :PyFloat_AsDouble, [:pointer], :double
91
+ attach_function :PyFloat_FromDouble, [:double], :pointer
92
+
93
+ # Tuple Methods
94
+ attach_function :PySequence_List, [:pointer], :pointer
95
+ attach_function :PyList_AsTuple, [:pointer], :pointer
96
+ attach_function :PyTuple_Pack, [:int, :varargs], :pointer
97
+
98
+ # Dict/Hash Methods
99
+ attach_function :PyDict_Next, [:pointer, :pointer, :pointer, :pointer], :int
100
+ attach_function :PyDict_New, [], :pointer
101
+ attach_function :PyDict_SetItem, [:pointer, :pointer, :pointer], :int
102
+ attach_function :PyDict_Contains, [:pointer, :pointer], :int
103
+ attach_function :PyDict_GetItem, [:pointer, :pointer], :pointer
104
+
105
+ # Error Methods
106
+ attach_variable :PyExc_Exception, self::DummyStruct.by_ref
107
+ attach_variable :PyExc_StopIteration, self::DummyStruct.by_ref
108
+ attach_function :PyErr_SetNone, [:pointer], :void
109
+ attach_function :PyErr_Fetch, [:pointer, :pointer, :pointer], :void
110
+ attach_function :PyErr_Occurred, [], :pointer
111
+ attach_function :PyErr_Clear, [], :void
112
+
113
+ # Reference Counting
114
+ attach_function :Py_IncRef, [:pointer], :void
115
+ attach_function :Py_DecRef, [:pointer], :void
116
+
117
+ # Type Objects
118
+ # attach_variable :PyBaseObject_Type, self::DummyStruct.by_value # built-in 'object'
119
+ # attach_variable :PyBaseString_Type, self::DummyStruct.by_value
120
+ # attach_variable :PyBool_Type, self::DummyStruct.by_value
121
+ # attach_variable :PyBuffer_Type, self::DummyStruct.by_value
122
+ # attach_variable :PyByteArrayIter_Type, self::DummyStruct.by_value
123
+ # attach_variable :PyByteArray_Type, self::DummyStruct.by_value
124
+ attach_variable :PyCFunction_Type, self::DummyStruct.by_value
125
+ # attach_variable :PyCObject_Type, self::DummyStruct.by_value
126
+ # attach_variable :PyCallIter_Type, self::DummyStruct.by_value
127
+ # attach_variable :PyCapsule_Type, self::DummyStruct.by_value
128
+ # attach_variable :PyCell_Type, self::DummyStruct.by_value
129
+ # attach_variable :PyClassMethod_Type, self::DummyStruct.by_value
130
+ attach_variable :PyClass_Type, self::DummyStruct.by_value
131
+ # attach_variable :PyCode_Type, self::DummyStruct.by_value
132
+ # attach_variable :PyComplex_Type, self::DummyStruct.by_value
133
+ # attach_variable :PyDictItems_Type, self::DummyStruct.by_value
134
+ # attach_variable :PyDictIterItem_Type, self::DummyStruct.by_value
135
+ # attach_variable :PyDictIterKey_Type, self::DummyStruct.by_value
136
+ # attach_variable :PyDictIterValue_Type, self::DummyStruct.by_value
137
+ # attach_variable :PyDictKeys_Type, self::DummyStruct.by_value
138
+ # attach_variable :PyDictProxy_Type, self::DummyStruct.by_value
139
+ # attach_variable :PyDictValues_Type, self::DummyStruct.by_value
140
+ attach_variable :PyDict_Type, self::DummyStruct.by_value
141
+ # attach_variable :PyEllipsis_Type, self::DummyStruct.by_value
142
+ # attach_variable :PyEnum_Type, self::DummyStruct.by_value
143
+ # attach_variable :PyFile_Type, self::DummyStruct.by_value
144
+ attach_variable :PyFloat_Type, self::DummyStruct.by_value
145
+ # attach_variable :PyFrame_Type, self::DummyStruct.by_value
146
+ # attach_variable :PyFrozenSet_Type, self::DummyStruct.by_value
147
+ attach_variable :PyFunction_Type, self::DummyStruct.by_value
148
+ # attach_variable :PyGen_Type, self::DummyStruct.by_value
149
+ # attach_variable :PyGetSetDescr_Type, self::DummyStruct.by_value
150
+ # attach_variable :PyInstance_Type, self::DummyStruct.by_value
151
+ attach_variable :PyInt_Type, self::DummyStruct.by_value
152
+ attach_variable :PyList_Type, self::DummyStruct.by_value
153
+ attach_variable :PyLong_Type, self::DummyStruct.by_value
154
+ # attach_variable :PyMemberDescr_Type, self::DummyStruct.by_value
155
+ # attach_variable :PyMemoryView_Type, self::DummyStruct.by_value
156
+ attach_variable :PyMethod_Type, self::DummyStruct.by_value
157
+ # attach_variable :PyModule_Type, self::DummyStruct.by_value
158
+ # attach_variable :PyNullImporter_Type, self::DummyStruct.by_value
159
+ # attach_variable :PyProperty_Type, self::DummyStruct.by_value
160
+ # attach_variable :PyRange_Type, self::DummyStruct.by_value
161
+ # attach_variable :PyReversed_Type, self::DummyStruct.by_value
162
+ # attach_variable :PySTEntry_Type, self::DummyStruct.by_value
163
+ # attach_variable :PySeqIter_Type, self::DummyStruct.by_value
164
+ # attach_variable :PySet_Type, self::DummyStruct.by_value
165
+ # attach_variable :PySlice_Type, self::DummyStruct.by_value
166
+ # attach_variable :PyStaticMethod_Type, self::DummyStruct.by_value
167
+ attach_variable :PyString_Type, self::DummyStruct.by_value
168
+ # attach_variable :PySuper_Type, self::DummyStruct.by_value # built-in 'super'
169
+ # attach_variable :PyTraceBack_Type, self::DummyStruct.by_value
170
+ attach_variable :PyTuple_Type, self::DummyStruct.by_value
171
+ attach_variable :PyType_Type, self::DummyStruct.by_value
172
+ # attach_variable :PyUnicode_Type, self::DummyStruct.by_value
173
+ # attach_variable :PyWrapperDescr_Type, self::DummyStruct.by_value
174
+
175
+ attach_variable :Py_TrueStruct, :_Py_TrueStruct, self::DummyStruct.by_value
176
+ attach_variable :Py_ZeroStruct, :_Py_ZeroStruct, self::DummyStruct.by_value
177
+ attach_variable :Py_NoneStruct, :_Py_NoneStruct, self::DummyStruct.by_value
178
+
179
+ # This is an implementation of the basic structure of a Python PyObject
180
+ # struct. The C struct is actually much larger, but since we only access
181
+ # the first two data members via FFI and always deal with struct
182
+ # pointers there is no need to mess around with the rest of the object.
183
+ self.const_set :PyObjectStruct, Class.new(::FFI::Struct)
184
+ self::PyObjectStruct.layout :ob_refcnt, :ssize_t,
185
+ :ob_type, :pointer
186
+
187
+ # This struct is used when defining Python methods.
188
+ self.const_set :PyMethodDef, Class.new(::FFI::Struct)
189
+ self::PyMethodDef.layout :ml_name, :pointer,
190
+ :ml_meth, :PyCFunction,
191
+ :ml_flags, :int,
192
+ :ml_doc, :pointer
192
193
  end
194
+
193
195
  end
194
196
  private :infect!
195
197
  end
@@ -41,7 +41,7 @@ class RubyPython::PythonError < RuntimeError
41
41
 
42
42
  # Decrease the reference count. This will happen anyway when they go out
43
43
  # of scope but might as well.
44
- rbValue.xDecref
44
+ rbValue.xDecref if not rbValue.null?
45
45
  pyName = rbType.getAttr("__name__")
46
46
 
47
47
  rbType.xDecref
@@ -88,16 +88,10 @@ module RubyPython
88
88
  end
89
89
 
90
90
  # Handles the job of wrapping up anything returned by a RubyPyProxy
91
- # instance. The behavior differs depending on the value of
92
- # +RubyPython.legacy_mode+. If legacy mode is inactive, every returned
93
- # object is wrapped by an instance of +RubyPyProxy+. If legacy mode is
94
- # active, RubyPython first attempts to convert the returned object to a
95
- # native Ruby type, and then only wraps the object if this fails.
91
+ # instance. Every returned # object is wrapped by an instance of +RubyPyProxy+
96
92
  def _wrap(pyobject)
97
93
  if pyobject.class?
98
94
  RubyPyClass.new(pyobject)
99
- elsif RubyPython.__send__ :legacy_mode?
100
- pyobject.rubify
101
95
  else
102
96
  RubyPyProxy.new(pyobject)
103
97
  end
@@ -136,7 +130,6 @@ module RubyPython
136
130
  # attempting to call a method with keyword arguments.
137
131
  # 4. The Python method or value will be called, if it's callable.
138
132
  # 5. RubyPython will wrap the return value in a RubyPyProxy object
139
- # (unless legacy_mode has been turned on).
140
133
  # 6. If a block has been provided, the wrapped return value will be
141
134
  # passed into the block.
142
135
  def method_missing(name, *args, &block)
@@ -156,7 +149,7 @@ module RubyPython
156
149
 
157
150
  if name =~ /=$/
158
151
  return @pObject.setAttr(name.chomp('='),
159
- PyObject.convert(*args).first)
152
+ PyObject.new(args.pop))
160
153
  elsif name =~ /!$/
161
154
  kwargs = true
162
155
  name.chomp! "!"
@@ -171,31 +164,10 @@ module RubyPython
171
164
  pReturn = pFunc
172
165
  else
173
166
  if kwargs and args.last.is_a?(Hash)
174
- pKeywords = PyObject.convert(args.pop).first
167
+ pKeywords = PyObject.new args.pop
175
168
  end
176
-
177
- orig_args = args
178
- args = PyObject.convert(*args)
179
- pTuple = PyObject.buildArgTuple(*args)
180
- pReturn = if pKeywords
181
- pFunc.callObjectKeywords(pTuple, pKeywords)
182
- else
183
- pFunc.callObject(pTuple)
184
- end
185
-
186
- # Clean up unused Python vars instead of waiting on Ruby's GC to
187
- # do it.
169
+ pReturn = _method_call(pFunc, args, pKeywords)
188
170
  pFunc.xDecref
189
- pTuple.xDecref
190
- pKeywords.xDecref if pKeywords
191
- orig_args.each_with_index do |arg, i|
192
- # Only decref objects that were created in PyObject.convert.
193
- if !arg.kind_of?(RubyPython::PyObject) and !arg.kind_of?(RubyPython::RubyPyProxy)
194
- args[i].xDecref
195
- end
196
- end
197
-
198
- raise PythonError.handle_error if PythonError.error?
199
171
  end
200
172
  else
201
173
  pReturn = pFunc
@@ -210,10 +182,33 @@ module RubyPython
210
182
  end
211
183
  end
212
184
 
185
+ #Handles the of calling a wrapped callable Python object at a higher level
186
+ #than +PyObject#callObject+. For internal use only.
187
+ def _method_call(pFunc, args, pKeywords)
188
+ pTuple = PyObject.buildArgTuple(*args)
189
+ pReturn = if pKeywords
190
+ pFunc.callObjectKeywords(pTuple, pKeywords)
191
+ else
192
+ pFunc.callObject(pTuple)
193
+ end
194
+
195
+ # Clean up unused Python vars instead of waiting on Ruby's GC to
196
+ # do it.
197
+ pTuple.xDecref
198
+ pKeywords.xDecref if pKeywords
199
+ raise PythonError.handle_error if PythonError.error?
200
+ pReturn
201
+ end
202
+ private :_method_call
203
+
213
204
  # RubyPython will attempt to translate the wrapped object into a native
214
205
  # Ruby object. This will only succeed for simple built-in type.
215
206
  def rubify
216
- @pObject.rubify
207
+ converted = @pObject.rubify
208
+ if converted.kind_of? ::FFI::Pointer
209
+ converted = self.class.new converted
210
+ end
211
+ converted
217
212
  end
218
213
 
219
214
  # Returns the String representation of the wrapped object via a call to
@@ -305,10 +300,7 @@ module RubyPython
305
300
  # Create an instance of the wrapped class. This is a workaround for the
306
301
  # fact that \Python classes are meant to be callable.
307
302
  def new(*args)
308
- args = PyObject.convert(*args)
309
- pTuple = PyObject.buildArgTuple(*args)
310
- pReturn = @pObject.callObject(pTuple)
311
- raise PythonError.handle_error if PythonError.error?
303
+ pReturn = _method_call(@pObject, args, nil)
312
304
  RubyPyInstance.new pReturn
313
305
  end
314
306
  end