rubypython 0.3.2 → 0.5.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 (51) hide show
  1. data/.autotest +3 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +13 -0
  4. data/.hgignore +14 -0
  5. data/.hgtags +7 -0
  6. data/.rspec +1 -1
  7. data/Contributors.rdoc +9 -0
  8. data/History.rdoc +148 -0
  9. data/{License.txt → License.rdoc} +7 -1
  10. data/Manifest.txt +15 -10
  11. data/PostInstall.txt +11 -4
  12. data/README.rdoc +272 -0
  13. data/Rakefile +107 -22
  14. data/autotest/discover.rb +1 -0
  15. data/lib/rubypython.rb +214 -120
  16. data/lib/rubypython/blankobject.rb +16 -14
  17. data/lib/rubypython/conversion.rb +242 -173
  18. data/lib/rubypython/legacy.rb +30 -31
  19. data/lib/rubypython/macros.rb +43 -34
  20. data/lib/rubypython/operators.rb +103 -101
  21. data/lib/rubypython/options.rb +41 -44
  22. data/lib/rubypython/pygenerator.rb +61 -0
  23. data/lib/rubypython/pymainclass.rb +46 -29
  24. data/lib/rubypython/pyobject.rb +193 -177
  25. data/lib/rubypython/python.rb +189 -176
  26. data/lib/rubypython/pythonerror.rb +54 -63
  27. data/lib/rubypython/pythonexec.rb +123 -0
  28. data/lib/rubypython/rubypyproxy.rb +213 -137
  29. data/lib/rubypython/type.rb +20 -0
  30. data/spec/basic_spec.rb +50 -0
  31. data/spec/callback_spec.rb +7 -17
  32. data/spec/conversion_spec.rb +7 -21
  33. data/spec/legacy_spec.rb +1 -16
  34. data/spec/pymainclass_spec.rb +6 -15
  35. data/spec/pyobject_spec.rb +39 -64
  36. data/spec/python_helpers/basics.py +20 -0
  37. data/spec/python_helpers/objects.py +24 -20
  38. data/spec/pythonerror_spec.rb +5 -17
  39. data/spec/refcnt_spec.rb +4 -10
  40. data/spec/rubypyclass_spec.rb +1 -11
  41. data/spec/rubypyproxy_spec.rb +45 -54
  42. data/spec/rubypython_spec.rb +45 -57
  43. data/spec/spec_helper.rb +49 -33
  44. metadata +87 -63
  45. data.tar.gz.sig +0 -0
  46. data/History.markdown +0 -97
  47. data/README.markdown +0 -105
  48. data/lib/rubypython/core_ext/string.rb +0 -7
  49. data/lib/rubypython/version.rb +0 -9
  50. data/spec/python_helpers/objects.pyc +0 -0
  51. metadata.gz.sig +0 -0
@@ -1,185 +1,198 @@
1
1
  require 'ffi'
2
- require 'open3'
3
2
  require 'rubypython/options'
3
+ require 'rubypython/pythonexec'
4
4
 
5
5
  module RubyPython
6
- #Check to see whether the Python Library has been loaded yet. If not
7
- #then we dfer loading the library until this file has been reloaded.
8
- if @loaded
9
- #This module provides access to the Python C API functions via the Ruby ffi
10
- #gem. Documentation for these functions may be found [here](http://docs.python.org/c-api/). Likewise the FFI gem documentation may be found [here](http://rdoc.info/projects/ffi/ffi).
11
- module Python
12
- extend FFI::Library
13
-
14
- PYTHON_EXE = RubyPython.options[:python_exe] || 'python'
15
- # This much we can assume works without anything special at all.
16
- PYTHON_VERSION = Open3.popen3("#{PYTHON_EXE} --version") { |i,o,e| e.read }.chomp.split[1].to_f
17
- PYTHON_NAME = "python#{PYTHON_VERSION}"
18
- LIB_NAME = "#{FFI::Platform::LIBPREFIX}#{PYTHON_NAME}"
19
- LIB_EXT = FFI::Platform::LIBSUFFIX
20
- PYTHON_SYS_PREFIX = %x{#{PYTHON_NAME} -c "import sys; print(sys.prefix)"}.chomp
21
-
22
- # Here's where we run into problems, as not everything works quite the
23
- # way we expect it to.
24
- #
25
- # The default libname will be something like libpython2.6.so (or .dylib)
26
- # or maybe even python2.6.dll on Windows.
27
- libname = "#{LIB_NAME}.#{LIB_EXT}"
28
-
29
- # We may need to look in multiple locations for Python, so let's build
30
- # this as an array.
31
- locations = [ File.join(PYTHON_SYS_PREFIX, "lib", libname) ]
32
-
33
- if FFI::Platform.mac?
34
- # On the Mac, let's add a special case that has even a different
35
- # libname. This may not be fully useful on future versions of OS X,
36
- # but it should work on 10.5 and 10.6. Even if it doesn't, the next
37
- # step will (/usr/lib/libpython<version>.dylib is a symlink to the
38
- # correct location).
39
- locations << File.join(PYTHON_SYS_PREFIX, "Python")
40
- # Let's also look in the location that was originally set in this
41
- # library:
42
- File.join(PYTHON_SYS_PREFIX, "lib", "#{PYTHON_NAME}", "config",
43
- libname)
44
- end
45
-
46
- if FFI::Platform.unix?
47
- # On Unixes, let's look in alternative places, too. Just in case.
48
- locations << File.join("/opt/local/lib", libname)
49
- locations << File.join("/opt/lib", libname)
50
- locations << File.join("/usr/local/lib", libname)
51
- locations << File.join("/usr/lib", libname)
52
- end
53
-
54
- # Get rid of redundant locations.
55
- locations.uniq!
56
-
57
- dyld_flags = FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL
58
- exceptions = []
59
-
60
- locations.each do |location|
61
- begin
62
- @ffi_libs = [ FFI::DynamicLibrary.open(location, dyld_flags) ]
63
- LIB = location
64
- break
65
- rescue LoadError => ex
66
- @ffi_libs = nil
67
- exceptions << ex
68
- end
69
- end
70
-
71
- raise exceptions.first if @ffi_libs.nil?
72
-
73
- #The class is a little bit of a hack to extract the address of global
74
- #structs. If someone knows a better way please let me know.
75
- class DummyStruct < FFI::Struct
76
- layout :dummy_var, :int
77
- end
78
-
79
- #Python interpreter startup and shutdown
80
- attach_function :Py_IsInitialized, [], :int
81
- attach_function :Py_Initialize, [], :void
82
- attach_function :Py_Finalize, [], :void
83
-
84
- #Module methods
85
- attach_function :PyImport_ImportModule, [:string], :pointer
86
-
87
- #Object Methods
88
- attach_function :PyObject_HasAttrString, [:pointer, :string], :int
89
- attach_function :PyObject_GetAttrString, [:pointer, :string], :pointer
90
- attach_function :PyObject_SetAttrString, [:pointer, :string, :pointer], :int
91
-
92
- attach_function :PyObject_Compare, [:pointer, :pointer], :int
93
-
94
- attach_function :PyObject_CallObject, [:pointer, :pointer], :pointer
95
- attach_function :PyCallable_Check, [:pointer], :int
96
-
97
- ###Python To Ruby Conversion
98
- #String Methods
99
- attach_function :PyString_AsString, [:pointer], :string
100
- attach_function :PyString_FromString, [:string], :pointer
101
-
102
- #List Methods
103
- attach_function :PyList_GetItem, [:pointer, :int], :pointer
104
- attach_function :PyList_Size, [:pointer], :int
105
- attach_function :PyList_New, [:int], :pointer
106
- attach_function :PyList_SetItem, [:pointer, :int, :pointer], :void
107
-
108
- #Integer Methods
109
- attach_function :PyInt_AsLong, [:pointer], :long
110
- attach_function :PyInt_FromLong, [:long], :pointer
111
-
112
- attach_function :PyLong_AsLong, [:pointer], :long
113
- attach_function :PyLong_FromLong, [:pointer], :long
114
-
115
- #Float Methods
116
- attach_function :PyFloat_AsDouble, [:pointer], :double
117
- attach_function :PyFloat_FromDouble, [:double], :pointer
118
-
119
- #Tuple Methods
120
- attach_function :PySequence_List, [:pointer], :pointer
121
- attach_function :PySequence_Tuple, [:pointer], :pointer
122
- attach_function :PyTuple_Pack, [:int, :varargs], :pointer
123
-
124
- #Dict/Hash Methods
125
- attach_function :PyDict_Next, [:pointer, :pointer, :pointer, :pointer], :int
126
- attach_function :PyDict_New, [], :pointer
127
- attach_function :PyDict_SetItem, [:pointer, :pointer, :pointer], :int
128
- attach_function :PyDict_Contains, [:pointer, :pointer], :int
129
- attach_function :PyDict_GetItem, [:pointer, :pointer], :pointer
130
-
131
- #Function Constants
132
- METH_VARARGS = 1
133
- attach_function :PyCFunction_New, [:pointer, :pointer], :pointer
134
- callback :PyCFunction, [:pointer, :pointer], :pointer
135
-
136
- #Error Methods
137
- attach_function :PyErr_Fetch, [:pointer, :pointer, :pointer], :void
138
- attach_function :PyErr_Occurred, [], :pointer
139
- attach_function :PyErr_Clear, [], :void
140
-
141
- #Reference Counting
142
- attach_function :Py_IncRef, [:pointer], :void
143
- attach_function :Py_DecRef, [:pointer], :void
144
-
145
- #Type Objects
146
- attach_variable :PyString_Type, DummyStruct.by_value
147
- attach_variable :PyList_Type, DummyStruct.by_value
148
- attach_variable :PyInt_Type, DummyStruct.by_value
149
- attach_variable :PyLong_Type, DummyStruct.by_value
150
- attach_variable :PyFloat_Type, DummyStruct.by_value
151
- attach_variable :PyTuple_Type, DummyStruct.by_value
152
- attach_variable :PyDict_Type, DummyStruct.by_value
153
- attach_variable :PyFunction_Type, DummyStruct.by_value
154
- attach_variable :PyCFunction_Type, DummyStruct.by_value
155
- attach_variable :PyMethod_Type, DummyStruct.by_value
156
- attach_variable :PyType_Type, DummyStruct.by_value
157
- attach_variable :PyClass_Type, DummyStruct.by_value
158
-
159
- attach_variable :Py_TrueStruct, :_Py_TrueStruct, DummyStruct.by_value
160
- attach_variable :Py_ZeroStruct, :_Py_ZeroStruct, DummyStruct.by_value
161
- attach_variable :Py_NoneStruct, :_Py_NoneStruct, DummyStruct.by_value
162
-
163
- #This is an implementation of the basic structure of a Python PyObject
164
- #struct. The C struct is actually much larger, but since we only access
165
- #the first two data members via FFI and always deal with struct pointers
166
- #there is no need to mess around with the rest of the object.
167
- class PyObjectStruct < FFI::Struct
168
- layout :ob_refcnt, :int,
169
- :ob_type, :pointer
170
- end
171
-
172
- #This struct is used when defining Python methods.
173
- class PyMethodDef < FFI::Struct
174
- layout :ml_name, :pointer,
175
- :ml_meth, :PyCFunction,
176
- :ml_flags, :int,
177
- :ml_doc, :pointer
178
- end
6
+ unless defined? PYTHON_RB
7
+ PYTHON_RB = __FILE__
8
+ PYTHON_RB.freeze
9
+ end
10
+
11
+ module Python; end
12
+ end
179
13
 
14
+ if RubyPython.load_ffi?
15
+ # This module provides access to the \Python C API functions via the Ruby
16
+ # FFI gem.
17
+ #
18
+ # === Documentation
19
+ # * {Python C API}[http://docs.python.org/c-api/]
20
+ # * {Ruby FFI}[http://rdoc.info/projects/ffi/ffi]
21
+ module RubyPython::Python # :nodoc: all
22
+ extend FFI::Library
23
+
24
+ EXEC = RubyPython::PythonExec.new(RubyPython.options[:python_exe])
25
+
26
+ PYTHON_LIB = EXEC.library
27
+ # FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL
28
+ ffi_lib_flags :lazy, :global
29
+ ffi_lib EXEC.library
30
+
31
+ # The class is a little bit of a hack to extract the address of global
32
+ # structs. If someone knows a better way please let me know.
33
+ class DummyStruct < FFI::Struct # :nodoc:
34
+ layout :dummy_var, :int
180
35
  end
181
36
 
182
- else
183
- module Python; end
37
+ PY_FILE_INPUT = 257
38
+ PY_EVAL_INPUT = 258
39
+
40
+ # Function methods & constants
41
+ METH_VARARGS = 0x0001
42
+ attach_function :PyCFunction_New, [:pointer, :pointer], :pointer
43
+ callback :PyCFunction, [:pointer, :pointer], :pointer
44
+
45
+ attach_function :PyRun_String, [:string, :int, :pointer, :pointer], :pointer
46
+ attach_function :PyRun_SimpleString, [:string], :pointer
47
+ attach_function :Py_CompileString, [:string, :string, :int], :pointer
48
+ attach_function :PyEval_EvalCode, [:pointer, :pointer, :pointer], :pointer
49
+ attach_function :PyErr_SetString, [:pointer, :string], :void
50
+
51
+ # Python interpreter startup and shutdown
52
+ attach_function :Py_IsInitialized, [], :int
53
+ attach_function :Py_Initialize, [], :void
54
+ attach_function :Py_Finalize, [], :void
55
+
56
+ # Module methods
57
+ attach_function :PyImport_ImportModule, [:string], :pointer
58
+
59
+ # Object Methods
60
+ attach_function :PyObject_HasAttrString, [:pointer, :string], :int
61
+ attach_function :PyObject_GetAttrString, [:pointer, :string], :pointer
62
+ attach_function :PyObject_SetAttrString, [:pointer, :string, :pointer], :int
63
+ attach_function :PyObject_Dir, [:pointer], :pointer
64
+
65
+ attach_function :PyObject_Compare, [:pointer, :pointer], :int
66
+
67
+ attach_function :PyObject_Call, [:pointer, :pointer, :pointer], :pointer
68
+ attach_function :PyObject_CallObject, [:pointer, :pointer], :pointer
69
+ attach_function :PyCallable_Check, [:pointer], :int
70
+
71
+ ### Python To Ruby Conversion
72
+ # String Methods
73
+ attach_function :PyString_AsString, [:pointer], :string
74
+ attach_function :PyString_FromString, [:string], :pointer
75
+ attach_function :PyString_AsStringAndSize, [:pointer, :pointer, :pointer], :int
76
+ attach_function :PyString_FromStringAndSize, [:buffer_in, :ssize_t], :pointer
77
+
78
+ # List Methods
79
+ attach_function :PyList_GetItem, [:pointer, :int], :pointer
80
+ attach_function :PyList_Size, [:pointer], :int
81
+ attach_function :PyList_New, [:int], :pointer
82
+ attach_function :PyList_SetItem, [:pointer, :int, :pointer], :void
83
+
84
+ # Integer Methods
85
+ attach_function :PyInt_AsLong, [:pointer], :long
86
+ attach_function :PyInt_FromLong, [:long], :pointer
87
+
88
+ attach_function :PyLong_AsLong, [:pointer], :long
89
+ attach_function :PyLong_FromLong, [:pointer], :long
90
+
91
+ # Float Methods
92
+ attach_function :PyFloat_AsDouble, [:pointer], :double
93
+ attach_function :PyFloat_FromDouble, [:double], :pointer
94
+
95
+ # Tuple Methods
96
+ attach_function :PySequence_List, [:pointer], :pointer
97
+ attach_function :PySequence_Tuple, [:pointer], :pointer
98
+ attach_function :PyTuple_Pack, [:int, :varargs], :pointer
99
+
100
+ # Dict/Hash Methods
101
+ attach_function :PyDict_Next, [:pointer, :pointer, :pointer, :pointer], :int
102
+ attach_function :PyDict_New, [], :pointer
103
+ attach_function :PyDict_SetItem, [:pointer, :pointer, :pointer], :int
104
+ attach_function :PyDict_Contains, [:pointer, :pointer], :int
105
+ attach_function :PyDict_GetItem, [:pointer, :pointer], :pointer
106
+
107
+ # Error Methods
108
+ attach_variable :PyExc_Exception, DummyStruct.by_ref
109
+ attach_variable :PyExc_StopIteration, DummyStruct.by_ref
110
+ attach_function :PyErr_SetNone, [:pointer], :void
111
+ attach_function :PyErr_Fetch, [:pointer, :pointer, :pointer], :void
112
+ attach_function :PyErr_Occurred, [], :pointer
113
+ attach_function :PyErr_Clear, [], :void
114
+
115
+ # Reference Counting
116
+ attach_function :Py_IncRef, [:pointer], :void
117
+ attach_function :Py_DecRef, [:pointer], :void
118
+
119
+ # Type Objects
120
+ # attach_variable :PyBaseObject_Type, DummyStruct.by_value # built-in 'object'
121
+ # attach_variable :PyBaseString_Type, DummyStruct.by_value
122
+ # attach_variable :PyBool_Type, DummyStruct.by_value
123
+ # attach_variable :PyBuffer_Type, DummyStruct.by_value
124
+ # attach_variable :PyByteArrayIter_Type, DummyStruct.by_value
125
+ # attach_variable :PyByteArray_Type, DummyStruct.by_value
126
+ attach_variable :PyCFunction_Type, DummyStruct.by_value
127
+ # attach_variable :PyCObject_Type, DummyStruct.by_value
128
+ # attach_variable :PyCallIter_Type, DummyStruct.by_value
129
+ # attach_variable :PyCapsule_Type, DummyStruct.by_value
130
+ # attach_variable :PyCell_Type, DummyStruct.by_value
131
+ # attach_variable :PyClassMethod_Type, DummyStruct.by_value
132
+ attach_variable :PyClass_Type, DummyStruct.by_value
133
+ # attach_variable :PyCode_Type, DummyStruct.by_value
134
+ # attach_variable :PyComplex_Type, DummyStruct.by_value
135
+ # attach_variable :PyDictItems_Type, DummyStruct.by_value
136
+ # attach_variable :PyDictIterItem_Type, DummyStruct.by_value
137
+ # attach_variable :PyDictIterKey_Type, DummyStruct.by_value
138
+ # attach_variable :PyDictIterValue_Type, DummyStruct.by_value
139
+ # attach_variable :PyDictKeys_Type, DummyStruct.by_value
140
+ # attach_variable :PyDictProxy_Type, DummyStruct.by_value
141
+ # attach_variable :PyDictValues_Type, DummyStruct.by_value
142
+ attach_variable :PyDict_Type, DummyStruct.by_value
143
+ # attach_variable :PyEllipsis_Type, DummyStruct.by_value
144
+ # attach_variable :PyEnum_Type, DummyStruct.by_value
145
+ # attach_variable :PyFile_Type, DummyStruct.by_value
146
+ attach_variable :PyFloat_Type, DummyStruct.by_value
147
+ # attach_variable :PyFrame_Type, DummyStruct.by_value
148
+ # attach_variable :PyFrozenSet_Type, DummyStruct.by_value
149
+ attach_variable :PyFunction_Type, DummyStruct.by_value
150
+ # attach_variable :PyGen_Type, DummyStruct.by_value
151
+ # attach_variable :PyGetSetDescr_Type, DummyStruct.by_value
152
+ # attach_variable :PyInstance_Type, DummyStruct.by_value
153
+ attach_variable :PyInt_Type, DummyStruct.by_value
154
+ attach_variable :PyList_Type, DummyStruct.by_value
155
+ attach_variable :PyLong_Type, DummyStruct.by_value
156
+ # attach_variable :PyMemberDescr_Type, DummyStruct.by_value
157
+ # attach_variable :PyMemoryView_Type, DummyStruct.by_value
158
+ attach_variable :PyMethod_Type, DummyStruct.by_value
159
+ # attach_variable :PyModule_Type, DummyStruct.by_value
160
+ # attach_variable :PyNullImporter_Type, DummyStruct.by_value
161
+ # attach_variable :PyProperty_Type, DummyStruct.by_value
162
+ # attach_variable :PyRange_Type, DummyStruct.by_value
163
+ # attach_variable :PyReversed_Type, DummyStruct.by_value
164
+ # attach_variable :PySTEntry_Type, DummyStruct.by_value
165
+ # attach_variable :PySeqIter_Type, DummyStruct.by_value
166
+ # attach_variable :PySet_Type, DummyStruct.by_value
167
+ # attach_variable :PySlice_Type, DummyStruct.by_value
168
+ # attach_variable :PyStaticMethod_Type, DummyStruct.by_value
169
+ attach_variable :PyString_Type, DummyStruct.by_value
170
+ # attach_variable :PySuper_Type, DummyStruct.by_value # built-in 'super'
171
+ # attach_variable :PyTraceBack_Type, DummyStruct.by_value
172
+ attach_variable :PyTuple_Type, DummyStruct.by_value
173
+ attach_variable :PyType_Type, DummyStruct.by_value
174
+ # attach_variable :PyUnicode_Type, DummyStruct.by_value
175
+ # attach_variable :PyWrapperDescr_Type, DummyStruct.by_value
176
+
177
+ attach_variable :Py_TrueStruct, :_Py_TrueStruct, DummyStruct.by_value
178
+ attach_variable :Py_ZeroStruct, :_Py_ZeroStruct, DummyStruct.by_value
179
+ attach_variable :Py_NoneStruct, :_Py_NoneStruct, DummyStruct.by_value
180
+
181
+ # This is an implementation of the basic structure of a Python PyObject
182
+ # struct. The C struct is actually much larger, but since we only access
183
+ # the first two data members via FFI and always deal with struct
184
+ # pointers there is no need to mess around with the rest of the object.
185
+ class PyObjectStruct < FFI::Struct
186
+ layout :ob_refcnt, :ssize_t,
187
+ :ob_type, :pointer
188
+ end
189
+
190
+ # This struct is used when defining Python methods.
191
+ class PyMethodDef < FFI::Struct
192
+ layout :ml_name, :pointer,
193
+ :ml_meth, :PyCFunction,
194
+ :ml_flags, :int,
195
+ :ml_doc, :pointer
196
+ end
184
197
  end
185
198
  end
@@ -1,78 +1,69 @@
1
1
  require 'rubypython/python'
2
2
  require 'rubypython/macros'
3
3
 
4
+ # Raised when an error occurs in the \Python interpreter.
5
+ class RubyPython::PythonError < RuntimeError
6
+ # Creates the PythonError.
7
+ # [typeName] The class name of the \Python error.
8
+ # [msg] The message attached to the \Python error.
9
+ def initialize(typeName, msg)
10
+ @type = typeName
11
+ super([typeName, msg].join(': '))
12
+ end
4
13
 
5
- module RubyPython
6
-
7
- #Raised when an error occurs in the Python interpreter.
8
- class PythonError < Exception
9
-
10
- #@param [String] typeName the class name of the Python error
11
- #@param [String] msg the message attached to the Python error
12
- def initialize(typeName, msg)
13
- @type = typeName
14
- super([typeName, msg].join(': '))
15
- end
16
-
17
- #This method should be called when an error has occured in the
18
- #Python interpreter. This acts as factory function for PythonError
19
- #objects. The function fetchs calls {fetch} to get the error
20
- #information from the Python interpreter and uses this to build
21
- #a PythonError object. It then calls {clear} to clear the error
22
- #flag of the python interpreter
23
- #@return [PythonError] an error enscapsulating the Python error
24
- def self.handle_error
25
- rbType, rbValue, rbTraceback = fetch()
26
-
27
- if not rbValue.null?
28
- msg = rbValue.getAttr("__str__").callObject PyObject.buildArgTuple
29
- msg = msg.rubify
30
- else
31
- msg = nil
32
- end
33
-
34
- #Decrease the reference count. This will happen anyway when they go
35
- #out of scope but might as well.
36
- rbValue.xDecref
37
- rbTraceback.xDecref
38
- pyName = rbType.getAttr("__name__")
14
+ # This method should be called when an error has occurred in the \Python
15
+ # interpreter. This acts as factory function for PythonError objects. The
16
+ # function fetches calls +#fetch+ to get the error information from the
17
+ # \Python interpreter and uses this to build a PythonError object. It then
18
+ # calls +#clear to clear the error flag in the python interpreter. After
19
+ # the error flag has been cleared, the PythonError object is returned.
20
+ def self.handle_error
21
+ rbType, rbValue, rbTraceback = fetch()
39
22
 
40
- rbType.xDecref
41
- rbName = pyName.rubify
42
- pyName.xDecref
23
+ if not rbValue.null?
24
+ msg = rbValue.getAttr("__str__").callObject RubyPython::PyObject.buildArgTuple
25
+ msg = msg.rubify
26
+ else
27
+ msg = nil
28
+ end
43
29
 
44
- PythonError.clear
30
+ # Decrease the reference count. This will happen anyway when they go out
31
+ # of scope but might as well.
32
+ rbValue.xDecref
33
+ rbTraceback.xDecref
34
+ pyName = rbType.getAttr("__name__")
45
35
 
46
- PythonError.new(rbName, msg)
47
- end
36
+ rbType.xDecref
37
+ rbName = pyName.rubify
38
+ pyName.xDecref
48
39
 
49
- #A wrapper to the Python C API PyErr_Fetch function.
50
- #@return [Array<PyObject>] an array containing three {PyObject} instances.
51
- # representing the Type, Value, and stacktrace of the python
52
- # error respectively.
53
- def self.fetch
54
- typePointer = FFI::MemoryPointer.new :pointer
55
- valuePointer = FFI::MemoryPointer.new :pointer
56
- tracebackPointer = FFI::MemoryPointer.new :pointer
40
+ RubyPython::PythonError.clear
41
+ RubyPython::PythonError.new(rbName, msg)
42
+ end
57
43
 
58
- Python.PyErr_Fetch typePointer, valuePointer, tracebackPointer
44
+ # A wrapper to the \Python C API +PyErr_Fetch+ function. Returns an array
45
+ # with three PyObject instances, representing the Type, the Value, and the
46
+ # stack trace of the Python error.
47
+ def self.fetch
48
+ typePointer = FFI::MemoryPointer.new :pointer
49
+ valuePointer = FFI::MemoryPointer.new :pointer
50
+ tracebackPointer = FFI::MemoryPointer.new :pointer
59
51
 
60
- rbType = PyObject.new typePointer.read_pointer
61
- rbValue = PyObject.new valuePointer.read_pointer
62
- rbTraceback = PyObject.new tracebackPointer.read_pointer
63
- [rbType, rbValue, rbTraceback]
64
- end
52
+ RubyPython::Python.PyErr_Fetch typePointer, valuePointer, tracebackPointer
65
53
 
66
- #Determines whether an error has occured in the python interpreter.
67
- def self.error?
68
- !Python.PyErr_Occurred.null?
69
- end
54
+ rbType = RubyPython::PyObject.new typePointer.read_pointer
55
+ rbValue = RubyPython::PyObject.new valuePointer.read_pointer
56
+ rbTraceback = RubyPython::PyObject.new tracebackPointer.read_pointer
57
+ [rbType, rbValue, rbTraceback]
58
+ end
70
59
 
71
- #Resets the Python interpreter error flag
72
- #@return [void]
73
- def self.clear
74
- Python.PyErr_Clear
75
- end
60
+ # Determines whether an error has occurred in the \Python interpreter.
61
+ def self.error?
62
+ !RubyPython::Python.PyErr_Occurred.null?
63
+ end
76
64
 
65
+ # Resets the \Python interpreter error flag
66
+ def self.clear
67
+ RubyPython::Python.PyErr_Clear
77
68
  end
78
69
  end