Module: Rupy

Defined in:
lib/rupy.rb,
lib/rupy/config.rb,
lib/rupy/macros.rb,
lib/rupy/python.rb,
lib/rupy/version.rb,
lib/rupy/pyobject.rb,
lib/rupy/operators.rb,
lib/rupy/conversion.rb,
lib/rupy/blankobject.rb,
lib/rupy/pygenerator.rb,
lib/rupy/pymainclass.rb,
lib/rupy/pythonerror.rb,
lib/rupy/rubypyproxy.rb

Overview

This module provides the direct user interface for the RubyPython extension.

RubyPython interfaces to the Python C API via the Python module using the Ruby FFI gem. However, the end user should only worry about dealing with the methods made avaiable via the RubyPython module.

Usage


It is important to remember that the Python Interpreter must be started before the bridge is functional. This will start the embedded interpreter. If this approach is used, the user should remember to call RubyPython.stop when they are finished with Python. Legacy Mode vs Normal Mode


By default RubyPython always returns a proxy class which refers method calls to the wrapped Python object. If you instead would like RubyPython to aggressively attempt conversion of return values, as it did in RubyPython 0.2.x, then you should set RubyPython.legacy_mode to true. In this case RubyPython will attempt to convert any return value from Python to a native Ruby type, and only return a proxy if conversion is not possible. For further examples see RubyPython.legacy_mode.

Examples:

RubyPython.start
cPickle = RubyPython.import "cPickle"
puts cPickle.dumps("RubyPython is awesome!").rubify
RubyPython.stop

Defined Under Namespace

Modules: Conversion, LegacyMode, Macros, Operators, Python, VERSION Classes: BlankObject, PyEnumerable, PyMainClass, PyObject, PythonError, RubyPyClass, RubyPyInstance, RubyPyModule, RubyPyProxy

Constant Summary collapse

OPTIONS =
{}
PyMain =
PyMainClass.instance

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.legacy_modeBoolean

Determines whether RubyPython is operating in Normal Mode or Legacy Mode. If legacy_mode is true, RubyPython switches into a mode compatible with versions < 0.3.0. All Python objects returned by method invocations are automatically converted to natve Ruby Types if RubyPython knows how to do this. Only if no such conversion is known are the objects wrapped in proxy objects. Otherwise RubyPython automatically wraps all returned objects as an instance of RubyPyProxy or one of its subclasses.

Examples:

Normal Mode

RubyPython.start
string = RubyPython.import 'string'
ascii_letters = string.ascii_letters # Here ascii_letters is a proxy object
puts ascii_letters.rubify # we use the rubify method to convert it to a
                          # native type
RubyPython.stop

Legacy Mode

RubyPython.legacy_mode = true
RubyPython.start
string = RubyPython.import 'string'
ascii_letters = string.ascii_letters # Here ascii_letters is a native ruby string
puts ascii_letters # No explicit conversion is neccessary
RubyPython.stop

Returns:

  • (Boolean)


58
59
60
# File 'lib/rupy.rb', line 58

def legacy_mode
  @legacy_mode
end

Class Method Details

.activateObject



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

def activate
    imp = import("imp")
    imp.load_source("activate_this", File.join(File.dirname(OPTIONS[:python]), "activate_this.py"))
end

.eval(code) ⇒ Object



11
12
13
14
15
16
17
# File 'lib/rupy/pygenerator.rb', line 11

def eval(code)
    globals = PyObject.new({
        "__builtins__" => PyMain.builtin.pObject,
    })
    empty_hash = PyObject.new({})
    ptr = Python.PyRun_String(code, Python::PY_FILE_INPUT, globals.pointer, empty_hash.pointer)
end

.generatorObject



40
41
42
43
44
45
46
47
48
# File 'lib/rupy/pygenerator.rb', line 40

def generator
    fib = Fiber.new do
        yield
        Python.PyErr_SetNone(Python.PyExc_StopIteration)
        FFI::Pointer::NULL
    end

    return lambda { generator_type.__call__(lambda { fib.resume }).pObject.pointer }
end

.generator_typeObject



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rupy/pygenerator.rb', line 19

def generator_type
    @generator_type ||= lambda do
        code = <<-eof
def rupy_generator(callback):
    while True:
yield callback()
        eof

        globals = PyObject.new({
            "__builtins__" => PyMain.builtin.pObject,
        })
        empty_hash = PyObject.new({})
        ptr = Python.PyRun_String(code, Python::PY_FILE_INPUT, globals.pointer, empty_hash.pointer)
        ptr = Python.PyRun_String("rupy_generator", Python::PY_EVAL_INPUT, globals.pointer, empty_hash.pointer)
        if PythonError.error?
            raise PythonError.handle_error
        end
        RubyPyProxy.new(PyObject.new(ptr))
    end.call
end

.import(mod_name) ⇒ RubyPyModule

Import a Python module into the interpreter and return a proxy object for it. This is the preferred way to gain access to Python object. module

Parameters:

  • mod_name (String)

    the name of the module to import

Returns:



108
109
110
111
112
113
114
115
116
# File 'lib/rupy.rb', line 108

def import(mod_name)
    req_all
    pModule = Python.PyImport_ImportModule mod_name
    if(PythonError.error?)
        raise PythonError.handle_error
    end
    pymod = PyObject.new pModule
    RubyPyModule.new(pymod)
end

.req_allObject



60
61
62
63
64
65
66
67
68
# File 'lib/rupy.rb', line 60

def req_all
    require 'rupy/core_ext/string'
    require 'rupy/python'
    require 'rupy/pythonerror'
    require 'rupy/pyobject'
    require 'rupy/rubypyproxy'
    require 'rupy/pymainclass'
    require 'rupy/pygenerator'
end

.run(&block) ⇒ Object

The same as session except that the block is executed within the scope of the RubyPython module.



133
134
135
136
137
# File 'lib/rupy.rb', line 133

def run(&block)
    start
    result = module_eval(&block)
    stop
end

.sessionObject

Execute the given block, starting the Python interperter before its execution and stopping the interpreter after its execution. The last expression of the block is returned; be careful that this is not a Python object as it will become invalid when the interpreter is stopped.

Parameters:

  • block (Block)

    the code to be executed while the interpreter is running

Returns:

  • the result of evaluating the given block



124
125
126
127
128
129
# File 'lib/rupy.rb', line 124

def session
    start
    result = yield
    stop
    result
end

.start(options = {}) ⇒ Boolean

Starts ups the Python interpreter. This method must be run before using any Python code. The only alternatives are use of the session and run methods.

Returns:

  • (Boolean)

    returns true if the interpreter was started here and false otherwise



75
76
77
78
79
80
81
82
83
# File 'lib/rupy.rb', line 75

def start(options = {})
    OPTIONS.merge!(options)
    req_all
    if Python.Py_IsInitialized != 0
        return false
    end
    Python.Py_Initialize
    true
end

.start_from_virtualenv(virtualenv) ⇒ Object



144
145
146
147
# File 'lib/rupy.rb', line 144

def start_from_virtualenv(virtualenv)
    start(:python => File.join(virtualenv, "bin", "python"))
    activate
end

.stopBoolean

Stops the Python interpreter if it is running. Returns true if the intepreter is stopped by this invocation. All wrapped Python objects should be considered invalid after invocation of this method.

Returns:

  • (Boolean)

    returns true if the interpreter was stopped here and false otherwise



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rupy.rb', line 90

def stop
    req_all
    if Python.Py_IsInitialized !=0
        PyMain.main = nil
        PyMain.builtin = nil
        Rupy::Operators.send :class_variable_set, '@@operator', nil
        Python.Py_Finalize
        Rupy::PyObject::AutoPyPointer.current_pointers.clear
        return true
    end
    false
end

.yield(*args) ⇒ Object



50
51
52
# File 'lib/rupy/pygenerator.rb', line 50

def yield(*args)
    Fiber.yield(*args)
end