rupy
rupy copied to clipboard
Python inside Ruby, the unholy alliance!
= Rupy: Python in your Ruby
== Description
Rupy is a bridge between the Ruby and Python interpreters. It embeds a running Python interpreter in the application's process using FFI and provides a means for wrapping and converting Python objects. Rupy is based on Zach Raines's amazing {RubyPython}[http://raineszm.bitbucket.org/rubypython/] project.
Rupy uses FFI to marshall the data between the Ruby and Python VMs and make Python calls. Recently, Rupy has added the ability to:
- Inherit from Python classes;
- Configure callbacks from Python;
- Run Python generators (on Ruby 1.9.2 or later).
== Where
Rupy is currently managed from GitHub: [https://github.com/steeve/rupy].
== Synopsis
=== Basic Usage
require "rupy"
Rupy.start # start the Python VM
cPickle = Rupy.import("cPickle") p cPickle.dumps("Testing rupy").rubify
Rupy.stop # stop the Python VM
=== Specific Python Version
require "rupy"
Rupy.start(:python => "python2.7") # Can also be a full path
cPickle = Rupy.import("cPickle") p cPickle.dumps("Testing rupy").rubify
Rupy.stop # stop the Python VM
=== VirtualEnv
Easy
Rupy.start_from_virtualenv("/path/to/virtualenv")
Or verbose
Rupy.start(:python => "/path/to/virtualenv/bin/python") Rupy.activate
=== Iterator support
Python
def readfile(): for line in open("/some/file"): yield line
Ruby
readfile.to_enum.each do |line| puts line end
=== Python to Ruby callbacks
Python
def dosomething(callback): print callback(5)
Ruby
dosomething(lambda do |value| value * 2 end)
def mycallback(value) return value * 2 end
dosomething(method(:mycallback))
=== Python-style Generators
Python
def test_generator(callback): for i in callback(): print "Got %d" % i
Ruby
test_generator(Rupy.generator do (0..10).each do |i| Rupy.yield i end end)
== Features / Problems
=== Features
- Can handle simple conversion of Python builtin types to Ruby builtin types and vice versa
- Can import Python modules
- Can execute arbitrary methods on imported modules and return the result
- Python objects can be treated as Ruby objects!
- Python's standard library available to you from within Ruby.
- Pass Ruby methods and procs as callbacks and call them from within Python code.
- Specify the python executable to be loaded, including virtualenv.
=== Known Problems
- Builtin Python methods which require a top level frame object (eval, dir, ...) do not work properly at present.
- There is no support for passing complicated (non-basic) Ruby types to Python.
== Supported Versions
=== Python Rupy is known to work with the C-based Python interpreter, versions 2.4 through 2.7; no work has yet been done to enable Python 3.0 support or to work with alternative Python implementations.
=== Ruby Rupy is known to work with the C-based (MRI) Ruby interpreter on versions 1.8.7 and 1.9.2. However, it uses Ruby-FFI, so it may work with other implementations without modification.
== What's planned There are features that are not currently supported in Rupy that may be considered for future releases, dependent on need, interest, and solutions.
=== Simpler Imports It might be nice to have some nice import helpers provided by Rupy to make the interface more seamless and provide advanced import features:
==== Import Aliasing
Python
from mod2.mod1 import sym as mysym
Ruby
py :from => "mod2.mod1", :import => "sym", :as => "mysym" py :from => "mod2.mod1", :import => :sym, :as => :mysym py :from => [ :mod2, :mod1 ], :import => :sym, :as => :mysym
Python
import mod1 as mymod
Ruby
py :import => "mod1", :as => "mymod" py :import => :mod1, :as => :mymod
Python
from mod2.mod1 import *
Ruby
py :from => "mod2.mod1", :import => :* pyrequire "mod2/mod1" # ruby style imports
=== Python named arguments
Python
def foo(arg1, arg2): pass
Ruby
foo(:arg2 => "bar2", :arg1 => "bar1")
with Ruby 1.9
foo(arg2: "bar2", arg1: "bar1")
=== Catch Exceptions from Ruby
Python
class MyFirstException(Exception): pass
class MySecondException(MyFirstException): pass
def test(): raise MySecondException
Ruby
begin test rescue MyFirstException => e # We may need to work out name collisions puts e.message end
== Requirements
- Python >= 2.4, < 3.0
- Ruby >= 1.8.6
- You must be able to build the ffi gem under your environment.
Note: RubyPython and Rupy have been tested on Mac OS 10.5.x
== Install gem install rupy
== Why Rupy?
Steeve Morin: I'm in love with both languages and want to be able to take what's best from each. This is an idea that was in my head for quite some time, and seeing that Zach Raines only developed RubyPython sporadically, I decided to implement what was missing to address my use cases.
Austin Ziegler: I have a need to control some Python code through a Ruby application for a project I'm working on, so I found RubyPython.
I implemented and submitted a bug fix for Zach's implementation and he pointed me to Steeve's fork as something that would be developed more frequently. There's
== History This project owes a great debt to Zach Raines for RubyPython for the initial code. His original code (updated irregularly) can be found on BitBucket.
== License See License.rdoc for full details.
(The MIT License)
Copyright 2011 Steeve Morin, Austin Ziegler, and Zach Raines Portions copyright 2008–2011 Zach Raines
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.