rubypython-raspi 0.1.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.
- data/.autotest +3 -0
- data/.gitignore +18 -0
- data/.hgignore +20 -0
- data/.hgtags +10 -0
- data/.rspec +2 -0
- data/Contributors.rdoc +10 -0
- data/History.rdoc +192 -0
- data/License.rdoc +26 -0
- data/Manifest.txt +43 -0
- data/PostInstall.txt +16 -0
- data/README.rdoc +272 -0
- data/Rakefile +108 -0
- data/autotest/discover.rb +1 -0
- data/lib/rubypython.rb +284 -0
- data/lib/rubypython/blankobject.rb +23 -0
- data/lib/rubypython/conversion.rb +286 -0
- data/lib/rubypython/legacy.rb +18 -0
- data/lib/rubypython/macros.rb +56 -0
- data/lib/rubypython/operators.rb +124 -0
- data/lib/rubypython/pygenerator.rb +61 -0
- data/lib/rubypython/pymainclass.rb +80 -0
- data/lib/rubypython/pyobject.rb +232 -0
- data/lib/rubypython/python.rb +195 -0
- data/lib/rubypython/pythonerror.rb +80 -0
- data/lib/rubypython/rubypyproxy.rb +336 -0
- data/lib/rubypython/type.rb +20 -0
- data/spec/basic_spec.rb +50 -0
- data/spec/callback_spec.rb +53 -0
- data/spec/conversion_spec.rb +68 -0
- data/spec/legacy_spec.rb +46 -0
- data/spec/pymainclass_spec.rb +24 -0
- data/spec/pyobject_spec.rb +246 -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 +62 -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 +67 -0
- metadata +200 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubypython'
|
2
|
+
|
3
|
+
# A quick way to activate <em>Legacy Mode</em> for a project. Requiring
|
4
|
+
# +'rubypython/legacy' automatically activates +RubyPython.legacy_mode+ on
|
5
|
+
# the project. This mode is deprecated and will be removed.
|
6
|
+
module RubyPython::LegacyMode
|
7
|
+
# Enables +RubyPython.legacy_mode+.
|
8
|
+
def self.setup_legacy
|
9
|
+
RubyPython.legacy_mode = true
|
10
|
+
end
|
11
|
+
|
12
|
+
# Disables +RubyPython.legacy_mode+.
|
13
|
+
def self.teardown_legacy
|
14
|
+
RubyPython.legacy_mode = false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
RubyPython::LegacyMode.setup_legacy
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'rubypython/python'
|
3
|
+
|
4
|
+
# Contains Python C API macros reimplemented in Ruby. For internal use only.
|
5
|
+
module RubyPython::Macros #:nodoc:
|
6
|
+
# Returns the reference count for the provided pointer.
|
7
|
+
def self.Py_REFCNT(pObjPointer)
|
8
|
+
pStruct = RubyPython::Python::PyObjectStruct.new pObjPointer
|
9
|
+
pStruct[:ob_refcnt]
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the object type for the provided pointer.
|
13
|
+
def self.Py_TYPE(pObjPointer)
|
14
|
+
pStruct = RubyPython::Python::PyObjectStruct.new pObjPointer
|
15
|
+
pStruct[:ob_type]
|
16
|
+
end
|
17
|
+
|
18
|
+
# This has been modified from the C API macro to allow for multiple
|
19
|
+
# pointer objects to be passed. It simplifies a number of checks.
|
20
|
+
def self.PyObject_TypeCheck(pObject, pTypePointer)
|
21
|
+
type = self.Py_TYPE(pObject)
|
22
|
+
|
23
|
+
[ pTypePointer ].flatten.each do |pointer|
|
24
|
+
return 1 if type == pointer
|
25
|
+
end
|
26
|
+
|
27
|
+
return 0
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.Py_True
|
31
|
+
RubyPython::Python.Py_TrueStruct.to_ptr
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.Py_False
|
35
|
+
RubyPython::Python.Py_ZeroStruct.to_ptr
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.Py_None
|
39
|
+
RubyPython::Python.Py_NoneStruct.to_ptr
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.Py_RETURN_FALSE
|
43
|
+
RubyPython::Python.Py_IncRef(self.Py_False)
|
44
|
+
self.Py_False
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.Py_RETURN_TRUE
|
48
|
+
RubyPython::Python.Py_IncRef(self.Py_True)
|
49
|
+
self.Py_True
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.Py_RETURN_NONE
|
53
|
+
RubyPython::Python.Py_IncRef(self.Py_None)
|
54
|
+
self.Py_None
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# A mixin module to provide method delegation to a proxy class. This is done
|
2
|
+
# either by delegating to methods defined on the wrapped object or by using
|
3
|
+
# the \Python _operator_ module. A large number of the methods are
|
4
|
+
# dynamically generated and so their documentation is not provided here. In
|
5
|
+
# general all operators that can be overloaded are delegated.
|
6
|
+
module RubyPython::Operators
|
7
|
+
# Provides access to the \Python _operator_ module.
|
8
|
+
def self.operator_
|
9
|
+
@@operator ||= RubyPython.import('operator')
|
10
|
+
end
|
11
|
+
|
12
|
+
# Creates a method to delegate a binary operation. The result of the
|
13
|
+
# operation will follow the conversion rules appropriate to the current
|
14
|
+
# mode of operation as set by {RubyPython.legacy_mode}.
|
15
|
+
# [rname] The name of the Ruby method for this operation. Can be either a
|
16
|
+
# Symbol or a String.
|
17
|
+
# [pname] The name of the \Python magic method to which this method should
|
18
|
+
# be delegated.
|
19
|
+
def self.bin_op(rname, pname)
|
20
|
+
define_method rname.to_sym do |other|
|
21
|
+
self.__send__(pname, other)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Creates a method to delegate a relational operator. The result of the
|
26
|
+
# delegated method will always be converted to a Ruby type so that simple
|
27
|
+
# boolean testing may occur. These methods are implemented with calls the
|
28
|
+
# _operator_ module.
|
29
|
+
#
|
30
|
+
# [rname] The name of the Ruby method for this operation. Can be a Symbol
|
31
|
+
# or a String.
|
32
|
+
# [pname] The name of the \Python magic method to which this method should
|
33
|
+
# be delegated.
|
34
|
+
def self.rel_op(rname, pname)
|
35
|
+
define_method rname.to_sym do |other|
|
36
|
+
RubyPython::Operators.operator_.__send__(pname, self, other).rubify
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Creates a method to delegate a relational operator. The result of the
|
41
|
+
# operation will follow the conversion rules appropriate to the current
|
42
|
+
# mode of operation as set by {RubyPython.legacy_mode}. These methods are
|
43
|
+
# implemented with calls the _operator_ module.
|
44
|
+
# [rname] The name of the Ruby method for this operation. Can be a Symbol
|
45
|
+
# or a String.
|
46
|
+
# [pname] The name of the \Python magic method to which this method should
|
47
|
+
# be delegated.
|
48
|
+
def self.unary_op(rname, pname)
|
49
|
+
define_method rname.to_sym do
|
50
|
+
RubyPython::Operators.operator_.__send__(pname, self)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
[
|
55
|
+
[:+, '__add__'],
|
56
|
+
[:-, '__sub__'],
|
57
|
+
[:*, '__mul__'],
|
58
|
+
[:/, '__div__'],
|
59
|
+
[:&, '__and__'],
|
60
|
+
[:^, '__xor__'],
|
61
|
+
[:%, '__mod__'],
|
62
|
+
[:**, '__pow__'],
|
63
|
+
[:>>, '__rshift__'],
|
64
|
+
[:<<, '__lshift__'],
|
65
|
+
[:|, '__or__']
|
66
|
+
].each do |args|
|
67
|
+
bin_op *args
|
68
|
+
end
|
69
|
+
|
70
|
+
[
|
71
|
+
[:~, :__invert__],
|
72
|
+
[:+@, :__pos__],
|
73
|
+
[:-@, :__neg__]
|
74
|
+
].each do |args|
|
75
|
+
unary_op *args
|
76
|
+
end
|
77
|
+
|
78
|
+
[
|
79
|
+
[:==, 'eq'],
|
80
|
+
[:<, 'lt'],
|
81
|
+
[:<=, 'le'],
|
82
|
+
[:>, 'gt'],
|
83
|
+
[:>=, 'ge'],
|
84
|
+
[:equal?, 'is_']
|
85
|
+
].each do |args|
|
86
|
+
rel_op *args
|
87
|
+
end
|
88
|
+
|
89
|
+
# Delegates object indexed access to the wrapped \Python object.
|
90
|
+
def [](index)
|
91
|
+
self.__getitem__ index
|
92
|
+
end
|
93
|
+
|
94
|
+
# Delegates setting of various indices to the wrapped \Python object.
|
95
|
+
def []=(index, value)
|
96
|
+
self.__setitem__ index, value
|
97
|
+
end
|
98
|
+
|
99
|
+
# Delegates membership testing to \Python.
|
100
|
+
def include?(item)
|
101
|
+
self.__contains__(item).rubify
|
102
|
+
end
|
103
|
+
|
104
|
+
# Delegates Comparison to \Python.
|
105
|
+
def <=>(other)
|
106
|
+
RubyPython::PyMain.cmp(self, other)
|
107
|
+
end
|
108
|
+
|
109
|
+
class << self
|
110
|
+
# Called by RubyPython when the interpreter is started or stopped so
|
111
|
+
# that the necessary preparation or cleanup can be done. For internal
|
112
|
+
# use only.
|
113
|
+
def python_interpreter_update(status)
|
114
|
+
case status
|
115
|
+
when :stop
|
116
|
+
@@operator = nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
private :python_interpreter_update
|
120
|
+
end
|
121
|
+
|
122
|
+
# Aliases eql? to == for Python objects.
|
123
|
+
alias_method :eql?, :==
|
124
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "rubypython/python"
|
2
|
+
require "rubypython/conversion"
|
3
|
+
require 'rubypython/macros'
|
4
|
+
require 'rubypython/conversion'
|
5
|
+
require 'rubypython/pyobject'
|
6
|
+
require "rubypython/pymainclass"
|
7
|
+
require "rubypython/rubypyproxy"
|
8
|
+
|
9
|
+
if defined? Fiber
|
10
|
+
module RubyPython
|
11
|
+
class << self
|
12
|
+
# Creates a \Python generator object called +rubypython_generator+
|
13
|
+
# that accepts a callback and yields to it.
|
14
|
+
#
|
15
|
+
# *Note*: This method only exists in the RubyPython if the Fiber
|
16
|
+
# exists.
|
17
|
+
def generator_type
|
18
|
+
@generator_type ||= lambda do
|
19
|
+
code = <<-EOM
|
20
|
+
def rubypython_generator(callback):
|
21
|
+
while True:
|
22
|
+
yield callback()
|
23
|
+
EOM
|
24
|
+
|
25
|
+
globals = PyObject.new({ "__builtins__" => PyMain.builtin.pObject, })
|
26
|
+
empty_hash = PyObject.new({})
|
27
|
+
ptr = Python.PyRun_String(code, Python::PY_FILE_INPUT, globals.pointer, empty_hash.pointer)
|
28
|
+
ptr = Python.PyRun_String("rubypython_generator", Python::PY_EVAL_INPUT, globals.pointer, empty_hash.pointer)
|
29
|
+
raise PythonError.handle_error if PythonError.error?
|
30
|
+
RubyPyProxy.new(PyObject.new(ptr))
|
31
|
+
end.call
|
32
|
+
end
|
33
|
+
|
34
|
+
# Creates a Ruby lambda that acts like a \Python generator. Uses
|
35
|
+
# +RubyPython.generator_type+ and Fiber to work the generator as a
|
36
|
+
# coroutine.
|
37
|
+
#
|
38
|
+
# *Note*: This method only exists in the RubyPython if the Fiber
|
39
|
+
# exists.
|
40
|
+
def generator
|
41
|
+
return lambda do |*args|
|
42
|
+
fib = Fiber.new do
|
43
|
+
yield *args
|
44
|
+
Python.PyErr_SetNone(Python.PyExc_StopIteration)
|
45
|
+
FFI::Pointer::NULL
|
46
|
+
end
|
47
|
+
generator_type.__call__(lambda { fib.resume })
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Performs a +Fiber.yield+ with the provided arguments, continuing the
|
52
|
+
# coroutine execution of the generator.
|
53
|
+
#
|
54
|
+
# *Note*: This method only exists in the RubyPython if the Fiber
|
55
|
+
# exists.
|
56
|
+
def yield(*args)
|
57
|
+
Fiber.yield(*args)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rubypython/blankobject'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
module RubyPython
|
5
|
+
# A singleton object providing access to the \Python <tt>__main__</tt> and
|
6
|
+
# <tt>__builtin__</tt> modules. This can be conveniently accessed through
|
7
|
+
# +PyMain+. The <tt>__main__</tt> namespace is searched before the
|
8
|
+
# <tt>__builtin__</tt> namespace. As such, naming clashes will be resolved
|
9
|
+
# in that order.
|
10
|
+
#
|
11
|
+
# RubyPython::PyMain.dir("dir") # => ['__add__', '__class__', … ]
|
12
|
+
#
|
13
|
+
# === Block Syntax
|
14
|
+
# PyMainClass provides experimental block support for called methods. A
|
15
|
+
# block may be passed to a method call and the object returned by the
|
16
|
+
# function call will be passed as an argument to the block.
|
17
|
+
#
|
18
|
+
# RubyPython::PyMain.dir("dir") { |a| a.rubify.map { |e| e.to_sym } }
|
19
|
+
# # => [:__add__, :__class__, :__contains__, … ]
|
20
|
+
class PyMainClass < RubyPython::BlankObject
|
21
|
+
include Singleton
|
22
|
+
|
23
|
+
# Returns a proxy object wrapping the \Python <tt>__main__</tt> namespace.
|
24
|
+
def main
|
25
|
+
@main ||= RubyPython.import "__main__"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a proxy object wrapping the \Python <tt>__builtin__</tt>
|
29
|
+
# namespace.
|
30
|
+
def builtin
|
31
|
+
@builtin ||= RubyPython.import "__builtin__"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Delegates any method calls on this object to the \Python
|
35
|
+
# <tt>__main__</tt> or <tt>__builtin__</tt> namespaces, in that order. If
|
36
|
+
# a block is provided, the result of calling the \Python method will be
|
37
|
+
# yielded as an argument to the block.
|
38
|
+
#
|
39
|
+
# [name] The name of the \Python method or function to call.
|
40
|
+
# [args] The arguments to pass to the \Python method.
|
41
|
+
# [block] A block to execute with the result of calling the \Python
|
42
|
+
# method. If a block is provided, the result of the block is returned,
|
43
|
+
# not the result of the \Python method.
|
44
|
+
def method_missing(name, *args, &block)
|
45
|
+
proxy = if main.respond_to?(name)
|
46
|
+
main
|
47
|
+
elsif builtin.respond_to?(name)
|
48
|
+
builtin
|
49
|
+
else
|
50
|
+
super(name, *args)
|
51
|
+
end
|
52
|
+
result = if proxy.is_real_method?(name)
|
53
|
+
proxy.__send__(name, *args)
|
54
|
+
else
|
55
|
+
proxy.__send__(:method_missing, name, *args)
|
56
|
+
end
|
57
|
+
|
58
|
+
if block
|
59
|
+
block.call(result)
|
60
|
+
else
|
61
|
+
result
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Called by RubyPython when the interpreter is started or stopped so
|
66
|
+
# that the neccesary preparation or cleanup can be done. For internal
|
67
|
+
# use only.
|
68
|
+
def python_interpreter_update(status)
|
69
|
+
case status
|
70
|
+
when :stop
|
71
|
+
@main = nil
|
72
|
+
@builtin = nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
private :python_interpreter_update
|
76
|
+
end
|
77
|
+
|
78
|
+
# The accessible instance of PyMainClass.
|
79
|
+
PyMain = RubyPython::PyMainClass.instance
|
80
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'rubypython/python'
|
2
|
+
require 'rubypython/macros'
|
3
|
+
require 'rubypython/conversion'
|
4
|
+
require 'ffi'
|
5
|
+
|
6
|
+
# This object is an opaque wrapper around the C Py…Object types used by the
|
7
|
+
# \Python C API.
|
8
|
+
#
|
9
|
+
# This class is *only* for RubyPython internal use.
|
10
|
+
class RubyPython::PyObject # :nodoc: all
|
11
|
+
# This class wraps C <tt>Py…Object</tt>s so that the RubyPython::Python
|
12
|
+
# reference count is automatically decreased when the Ruby object
|
13
|
+
# referencing them goes out of scope.
|
14
|
+
class AutoPyPointer < FFI::AutoPointer # :nodoc:
|
15
|
+
class << self
|
16
|
+
# Keeps track of which objects are associated with the currently
|
17
|
+
# running RubyPython::Python interpreter, so that RubyPython knows not
|
18
|
+
# to try to decrease the reference counts of the others when garbage
|
19
|
+
# collecting.
|
20
|
+
attr_accessor :current_pointers
|
21
|
+
|
22
|
+
# When used along with the FFI Library method is executed whenever a
|
23
|
+
# pointer is garbage collected so that cleanup can be done. In our
|
24
|
+
# case we decrease the reference count of the held pointer as long as
|
25
|
+
# the object is still good. There is really no reason the end-user
|
26
|
+
# would need to the use this method directly.
|
27
|
+
def release(pointer)
|
28
|
+
obj_id = pointer.object_id
|
29
|
+
deleted = @current_pointers.delete(obj_id)
|
30
|
+
if deleted and (RubyPython::Python.Py_IsInitialized != 0)
|
31
|
+
RubyPython::Python.Py_DecRef pointer
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Called by RubyPython when the interpreter is started or stopped so
|
36
|
+
# that the necessary preparation or cleanup can be done. For internal
|
37
|
+
# use only.
|
38
|
+
def python_interpreter_update(status)
|
39
|
+
case status
|
40
|
+
when :stop
|
41
|
+
current_pointers.clear
|
42
|
+
end
|
43
|
+
end
|
44
|
+
private :python_interpreter_update
|
45
|
+
end
|
46
|
+
|
47
|
+
self.current_pointers = {}
|
48
|
+
end
|
49
|
+
|
50
|
+
# The AutoPyPointer object which represents the RubyPython::Python
|
51
|
+
# Py…Object.
|
52
|
+
attr_reader :pointer
|
53
|
+
|
54
|
+
# [rObject] FFI Pointer objects passed into the constructor are wrapped in
|
55
|
+
# an AutoPyPointer and assigned to the +#pointer+ attribute. Other objects
|
56
|
+
# are converted, if possible, from their Ruby types to their \Python types
|
57
|
+
# and wrapped in an AutoPyPointer. The conversion is done with
|
58
|
+
# +RubyPython::Conversion.rtopObject+.
|
59
|
+
def initialize(rObject)
|
60
|
+
if rObject.kind_of? FFI::AutoPointer
|
61
|
+
new_pointer = FFI::Pointer.new rObject
|
62
|
+
@pointer = AutoPyPointer.new new_pointer
|
63
|
+
xIncref
|
64
|
+
elsif rObject.kind_of? FFI::Pointer
|
65
|
+
@pointer = AutoPyPointer.new rObject
|
66
|
+
else
|
67
|
+
@pointer = AutoPyPointer.new RubyPython::Conversion.rtopObject(rObject)
|
68
|
+
end
|
69
|
+
AutoPyPointer.current_pointers[@pointer.object_id] = true
|
70
|
+
end
|
71
|
+
|
72
|
+
# Attempts to convert the wrapped object to a native ruby type. Returns
|
73
|
+
# either the Ruby object or the unmodified \Python object.
|
74
|
+
def rubify
|
75
|
+
RubyPython::Conversion.ptorObject @pointer
|
76
|
+
end
|
77
|
+
|
78
|
+
# Tests whether the wrapped \Python object has a given attribute. Returns
|
79
|
+
# +true+ if the attribute exists.
|
80
|
+
# [attrName] The name of the attribute to look up.
|
81
|
+
def hasAttr(attrName)
|
82
|
+
RubyPython::Python.PyObject_HasAttrString(@pointer, attrName) == 1
|
83
|
+
end
|
84
|
+
|
85
|
+
# Retrieves an object from the wrapped \Python object.
|
86
|
+
# [attrName] The name of the attribute to fetch.
|
87
|
+
def getAttr(attrName)
|
88
|
+
pyAttr = RubyPython::Python.PyObject_GetAttrString(@pointer, attrName)
|
89
|
+
self.class.new pyAttr
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sets an attribute of the wrapped \Python object. Returns +true+ if the
|
93
|
+
# attribute was successfully set.
|
94
|
+
# [attrName] The name of the attribute to set.
|
95
|
+
# [rbPyAttr] A PyObject wrapper around the value that we wish to set the
|
96
|
+
# attribute to.
|
97
|
+
def setAttr(attrName, rbPyAttr)
|
98
|
+
RubyPython::Python.PyObject_SetAttrString(@pointer, attrName, rbPyAttr.pointer) != -1
|
99
|
+
end
|
100
|
+
|
101
|
+
# Calls the wrapped \Python object with the supplied arguments and keyword
|
102
|
+
# arguments. Returns a PyObject wrapper around the returned object, which
|
103
|
+
# may be +NULL+.
|
104
|
+
# [rbPyArgs] A PyObject wrapping a Tuple of the supplied arguments.
|
105
|
+
# [rbPyKeywords] A PyObject wrapping a Dict of keyword arguments.
|
106
|
+
def callObjectKeywords(rbPyArgs, rbPyKeywords)
|
107
|
+
pyReturn = RubyPython::Python.PyObject_Call(@pointer, rbPyArgs.pointer, rbPyKeywords.pointer)
|
108
|
+
self.class.new pyReturn
|
109
|
+
end
|
110
|
+
|
111
|
+
# Calls the wrapped \Python object with the supplied arguments. Returns a
|
112
|
+
# PyObject wrapper around the returned object, which may be +NULL+.
|
113
|
+
# [rbPyArgs] A PyObject wrapping a Tuple of the supplied arguments.
|
114
|
+
def callObject(rbPyArgs)
|
115
|
+
pyReturn = RubyPython::Python.PyObject_CallObject(@pointer, rbPyArgs.pointer)
|
116
|
+
self.class.new pyReturn
|
117
|
+
end
|
118
|
+
|
119
|
+
# Decrease the reference count of the wrapped object.
|
120
|
+
def xDecref
|
121
|
+
AutoPyPointer.release(@pointer)
|
122
|
+
@pointer.free
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
|
126
|
+
# Increase the reference count of the wrapped object
|
127
|
+
def xIncref
|
128
|
+
RubyPython::Python.Py_IncRef @pointer
|
129
|
+
nil
|
130
|
+
end
|
131
|
+
|
132
|
+
# Tests whether the wrapped object is +NULL+.
|
133
|
+
def null?
|
134
|
+
@pointer.null?
|
135
|
+
end
|
136
|
+
|
137
|
+
# Performs a compare on two Python objects. Returns a value similar to
|
138
|
+
# that of the spaceship operator (<=>).
|
139
|
+
def cmp(other)
|
140
|
+
RubyPython::Python.PyObject_Compare @pointer, other.pointer
|
141
|
+
end
|
142
|
+
|
143
|
+
# Tests whether the wrapped object is a function or a method. This is not
|
144
|
+
# the same as #callable? as many other \Python objects are callable.
|
145
|
+
def function_or_method?
|
146
|
+
check = RubyPython::Macros.PyObject_TypeCheck(@pointer, [
|
147
|
+
RubyPython::Python.PyFunction_Type.to_ptr,
|
148
|
+
RubyPython::Python.PyCFunction_Type.to_ptr,
|
149
|
+
RubyPython::Python.PyMethod_Type.to_ptr
|
150
|
+
])
|
151
|
+
check != 0
|
152
|
+
end
|
153
|
+
|
154
|
+
# Is the wrapped object callable?
|
155
|
+
def callable?
|
156
|
+
RubyPython::Python.PyCallable_Check(@pointer) != 0
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns the 'directory' of the RubyPython::Python object; similar to #methods in
|
160
|
+
# Ruby.
|
161
|
+
def dir
|
162
|
+
return self.class.new(RubyPython::Python.PyObject_Dir(@pointer)).rubify.map do |x|
|
163
|
+
x.to_sym
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Tests whether the wrapped object is a RubyPython::Python class (both new
|
168
|
+
# and old style).
|
169
|
+
def class?
|
170
|
+
check = RubyPython::Macros.PyObject_TypeCheck(@pointer, [
|
171
|
+
RubyPython::Python.PyClass_Type.to_ptr,
|
172
|
+
RubyPython::Python.PyType_Type.to_ptr
|
173
|
+
])
|
174
|
+
check != 0
|
175
|
+
end
|
176
|
+
|
177
|
+
# Manipulates the supplied PyObject instance such that it is suitable to
|
178
|
+
# passed to #callObject or #callObjectKeywords. If +rbObject+ is a tuple
|
179
|
+
# then the argument passed in is returned. If it is a list then the list
|
180
|
+
# is converted to a tuple. Otherwise returns a tuple with one element:
|
181
|
+
# +rbObject+.
|
182
|
+
# [rbObject] The argument to be turned into a Tuple.
|
183
|
+
def self.makeTuple(rbObject)
|
184
|
+
pTuple = nil
|
185
|
+
|
186
|
+
if RubyPython::Macros.PyObject_TypeCheck(rbObject.pointer, RubyPython::Python.PyList_Type.to_ptr) != 0
|
187
|
+
pTuple = RubyPython::Python.PySequence_Tuple(rbObject.pointer)
|
188
|
+
elsif RubyPython::Macros.PyObject_TypeCheck(rbObject.pointer, RubyPython::Python.PyTuple_Type.to_ptr) != 0
|
189
|
+
pTuple = rbObject.pointer
|
190
|
+
else
|
191
|
+
pTuple = RubyPython::Python.PyTuple_Pack(1, :pointer, rbObject.pointer)
|
192
|
+
end
|
193
|
+
|
194
|
+
self.new pTuple
|
195
|
+
end
|
196
|
+
|
197
|
+
# Wraps up the supplied arguments in a \Python List.
|
198
|
+
def self.newList(*args)
|
199
|
+
rbList = self.new RubyPython::Python.PyList_New(args.length)
|
200
|
+
|
201
|
+
args.each_with_index do |el, i|
|
202
|
+
el.xIncref # PyList_SetItem steals references!
|
203
|
+
RubyPython::Python.PyList_SetItem rbList.pointer, i, el.pointer
|
204
|
+
end
|
205
|
+
|
206
|
+
rbList
|
207
|
+
end
|
208
|
+
|
209
|
+
# Converts the supplied arguments to PyObject instances.
|
210
|
+
def self.convert(*args)
|
211
|
+
args.map do |arg|
|
212
|
+
if arg.kind_of? RubyPython::PyObject
|
213
|
+
arg
|
214
|
+
elsif arg.kind_of? RubyPython::RubyPyProxy
|
215
|
+
arg.pObject
|
216
|
+
else
|
217
|
+
RubyPython::PyObject.new arg
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Takes an array of wrapped \Python objects and wraps them in a Tuple such
|
223
|
+
# that they may be passed to #callObject.
|
224
|
+
# [args] An array of PyObjects; the arguments to be inserted into the
|
225
|
+
# Tuple.
|
226
|
+
def self.buildArgTuple(*args)
|
227
|
+
pList = newList(*args)
|
228
|
+
pTuple = makeTuple(pList)
|
229
|
+
pList.xDecref
|
230
|
+
pTuple
|
231
|
+
end
|
232
|
+
end
|