Class: Rupy::RubyPyProxy

Inherits:
BlankObject show all
Includes:
Operators
Defined in:
lib/rupy/rubypyproxy.rb

Overview

This is the object that the end user will most often be interacting with. It holds a reference to an object in the Python VM an delegates method calls to it, wrapping and returning the results. The user should not worry about reference counting of this object an instance will decrement its objects reference count when it is garbage collected.

Note: All RubyPyProxy objects become invalid when the Python interpreter is halted.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Operators

#<=>, #[], #[]=, bin_op, #include?, operator_, rel_op, unary_op

Methods inherited from BlankObject

hide

Constructor Details

#initialize(pObject) ⇒ RubyPyProxy

Returns a new instance of RubyPyProxy.



21
22
23
24
25
26
27
# File 'lib/rupy/rubypyproxy.rb', line 21

def initialize(pObject)
    if pObject.kind_of? PyObject
        @pObject = pObject
    else
        @pObject = PyObject.new pObject
    end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

Implements the method call delegation.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rupy/rubypyproxy.rb', line 64

def method_missing(name, *args, &block)
    name = name.to_s

    if(name.end_with? "?")
        begin
            RubyPyProxy.reveal(name.to_sym)
            return self.__send__(name.to_sym, *args, &block)
        rescue RuntimeError => exc
            raise NoMethodError.new(name) if exc.message =~ /Don't know how to reveal/
            raise
        end
    end


    if(name.end_with? "=")
        setter = true
        name.chomp! "="
    else
        setter=false
    end

    if(!@pObject.hasAttr(name) and !setter)
        raise NoMethodError.new(name)
    end


    args = PyObject.convert(*args)

    if setter
        return @pObject.setAttr(name, args[0])
    end

    pFunc = @pObject.getAttr(name)

    if pFunc.callable?
        if args.empty? and pFunc.class?
            pReturn = pFunc
        else
            pTuple = PyObject.buildArgTuple(*args)
            pReturn = pFunc.callObject(pTuple)
            if PythonError.error?
                raise PythonError.handle_error
            end
        end
    else
        pReturn = pFunc
    end

    return _wrap(pReturn)
end

Instance Attribute Details

#pObjectObject (readonly)

Returns the value of attribute pObject.



19
20
21
# File 'lib/rupy/rubypyproxy.rb', line 19

def pObject
  @pObject
end

Instance Method Details

#_wrap(pyobject) ⇒ Object

Handles the job of wrapping up anything returned by a Rupy::RubyPyProxy instance. The behavior differs depending on the value of RubyPython.legacy_mode. If legacy mode is inactive, every returned object is wrapped by an instance of Rupy::RubyPyProxy. If legacy mode is active, RubyPython first attempts to convert the returned object to a native Ruby type, and then only wraps the object if this fails.



35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rupy/rubypyproxy.rb', line 35

def _wrap(pyobject)
    if pyobject.class?
        RubyPyClass.new(pyobject)
    elsif Rupy.legacy_mode
        pyobject.rubify
    else
        RubyPyProxy.new(pyobject)
    end
rescue Conversion::UnsupportedConversion => exc
    RubyPyProxy.new pyobject
end

#inspectString

Returns the string representation of the wrapped object via a call to the object’s _repr_ method. Falls back on the default Ruby behavior when this method cannot be found.

Returns:



126
127
128
129
130
131
# File 'lib/rupy/rubypyproxy.rb', line 126

def inspect
    self.__repr__.rubify rescue _inspect
rescue
    class << self; define_method :_inspect, RubyPyProxy.find_hidden_method(:inspect); end
    _inspect
end

#is_real_method?Object

Moves the old respond_to? method to is_real_method?



50
# File 'lib/rupy/rubypyproxy.rb', line 50

alias :is_real_method? :respond_to?

#methodsObject



188
189
190
# File 'lib/rupy/rubypyproxy.rb', line 188

def methods
    return pObject.dir.map {|x| x.to_sym }
end

#respond_to?(mname) ⇒ Boolean

RubyPython checks the attribute dictionary of the wrapped object to check whether it will respond to a method call. This should not return false positives but it may return false negatives. The builitin Ruby respond_to? method has been aliased to is_real_method?.

Returns:

  • (Boolean)


56
57
58
59
60
61
# File 'lib/rupy/rubypyproxy.rb', line 56

def respond_to?(mname)
    return true if is_real_method?(mname)
    mname = mname.to_s
    return true if mname.end_with? '='
    @pObject.hasAttr(mname)
end

#rubifyObject

RubyPython will attempt to translate the wrapped object into a native Ruby object. This will only succeed for simple builtin type.



117
118
119
# File 'lib/rupy/rubypyproxy.rb', line 117

def rubify
    @pObject.rubify
end

#to_aArray<RubyPyProxy>

Converts the wrapped Python object to a Ruby Array. Note that this only converts one level, so a nested array will remain a proxy object. Only wrapped objects which have an _iter_ method may be converted using to_a.

Note that for Dict objects, this method returns what you would get in Python, not in Ruby i.e. a_dict.to_a returns an array of the dictionary’s keys.

Examples:

List

irb(main):001:0> RubyPython.start
=> true
irb(main):002:0> a_list = RubyPython::RubyPyProxy.new [1, 'a', 2, 'b']
=> [1, 'a', 2, 'b']
irb(main):003:0> a_list.kind_of? RubyPython::RubyPyProxy
=> true
irb(main):004:0> a_list.to_a
=> [1, 'a', 2, 'b']
irb(main):005:0> RubyPython.stop
=> true

Dict

irb(main):001:0> RubyPython.start
=> true
irb(main):002:0> a_dict = RubyPython::RubyPyProxy.new({1 => '2', :three => [4,5]})
=> {1: '2', 'three': [4, 5]}
irb(main):003:0> a_dict.kind_of? RubyPython::RubyPyProxy
=> true
irb(main):004:0> a_dict.to_a
=> [1, 'three']
irb(main):005:0> RubyPython.stop
=> true

Returns:



177
178
179
180
181
182
183
184
185
186
# File 'lib/rupy/rubypyproxy.rb', line 177

def to_a
    iter = self.__iter__
    ary = []
    loop do
        ary << iter.next()
    end
rescue PythonError => exc
    raise if exc.message !~ /StopIteration/
    ary
end

#to_enumObject



192
193
194
# File 'lib/rupy/rubypyproxy.rb', line 192

def to_enum
    return PyEnumerable.new(@pObject)
end

#to_sString

Returns the string representation of the wrapped object via a call to the object’s _str_ method. Falls back on the default Ruby behavior when this method cannot be found.

Returns:



138
139
140
141
142
143
# File 'lib/rupy/rubypyproxy.rb', line 138

def to_s
    self.__str__.rubify rescue _to_s
rescue
    class << self; define_method :_to_s, RubyPyProxy.find_hidden_method(:to_s); end
    _to_s
end