py2rb 0.1.2
A code translator using AST from Python to Ruby
License: MIT
Keywords: python ruby

py2rb.py
========

A code translator using AST from Python to Ruby.
This is basically a NodeVisitor with ruby output.
See ast documentation (https://docs.python.org/3/library/ast.html) for more information.

Installation
------------

Execute the following::

    pip install py2rb

    or

    git clone git://github.com/naitoh/py2rb.git

Dependencies
------------

- Python 3.5, 3.6
- Ruby 2.4 or later


Usage
--------

Sample 1::

    $ cat tests/basic/oo_inherit_simple.py
    class bar(object):

        def __init__(self,name):
            self.name = name

        def setname(self,name):
            self.name = name

    class foo(bar):

        registered = []

        def __init__(self,val,name):
            self.fval = val
            self.register(self)
            self.name = name

        def inc(self):
            self.fval += 1

        def msg(self, a=None, b=None, c=None):
            txt = ''
            varargs = a, b, c
            for arg in varargs:
                if arg is None:
                    continue
                txt += str(arg)
                txt += ","
            return txt + self.name + " says:"+str(self.fval)

        @staticmethod
        def register(f):
            foo.registered.append(f)

        @staticmethod
        def printregistered():
            for r in foo.registered:
                print(r.msg())

    a = foo(10,'a')
    a.setname('aaa')
    b = foo(20,'b')
    c = foo(30,'c')

    a.inc()
    a.inc()
    c.inc()

    print(a.msg())
    print(b.msg())
    print(c.msg(2,3,4))

    print("---")

    foo.printregistered()

The above will result in ::

    $ py2rb tests/basic/oo_inherit_simple.py
    class Bar
      def initialize(name)
        @name = name
      end
      def setname(name)
        @name = name
      end
    end
    class Foo < Bar
      def method_missing(method, *args)
        self.class.__send__ method, *args
      end
      @@registered = []
      def initialize(val, name)
        @fval = val
        Foo.register(self)
        @name = name
      end
      def inc()
        @fval += 1
      end
      def msg(a: nil, b: nil, c: nil)
        txt = ""
        varargs = [a, b, c]
        for arg in varargs
          if arg === nil
            next
          end
          txt += arg.to_s
          txt += ","
        end
        return ((txt + @name) + " says:") + @fval.to_s
      end
      def self.register(f)
        @@registered.push(f)
      end
      def self.printregistered()
        for r in @@registered
          print(r.msg())
        end
      end
      def self.registered; @@registered; end
      def self.registered=(val); @@registered=val; end
      def registered; @registered = @@registered if @registered.nil?; @registered; end
      def registered=(val); @registered=val; end
    end
    a = Foo.new(10, "a")
    a.setname("aaa")
    b = Foo.new(20, "b")
    c = Foo.new(30, "c")
    a.inc()
    a.inc()
    c.inc()
    print(a.msg())
    print(b.msg())
    print(c.msg(a: 2, b: 3, c: 4))
    print("---")
    Foo.printregistered()

Sample 2::

    $ cat tests/deep-learning-from-scratch/and_gate.py
    # coding: utf-8
    import numpy as np

    def AND(x1, x2):
        x = np.array([x1, x2])
        w = np.array([0.5, 0.5])
        b = -0.7
        tmp = np.sum(w*x) + b
        if tmp <= 0:
            return 0
        else:
            return 1

    if __name__ == '__main__':
        for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
            y = AND(xs[0], xs[1])
            print(str(xs) + " -> " + str(y))

The above will result in ::

    $ py2rb tests/deep-learning-from-scratch/and_gate.py
    require 'numo/narray'
    def AND(x1, x2)
      x = Numo::NArray.cast([x1, x2])
      w = Numo::NArray.cast([0.5, 0.5])
      b = -0.7
      tmp = ((w * x).sum()) + b
      if tmp <= 0
        return 0
      else
        return 1
      end
    end

    if __FILE__ == $0
      for xs in [[0, 0], [1, 0], [0, 1], [1, 1]]
        y = AND(xs[0], xs[1])
        print((xs.to_s + (" -> ")) + y.to_s)
      end
    end

Sample 3 (Convert all local dependent module files of specified Python file)::

    $ git clone git://github.com/chainer/chainer.git
    $ py2rb chainer/chainer/__init__.py -m -p chainer -r -w -f
    Try : chainer/chainer/__init__.py -> chainer/chainer/__init__.rb : [OK]
    Warning : yield is not supported :
    Warning : yield is not supported :
    Try  : chainer/chainer/configuration.py -> chainer/chainer/configuration.rb : [Warning]
    Try  : chainer/chainer/cuda.py -> chainer/chainer/cuda.rb : [OK]
          :
          :
    Try  : chainer/chainer/utils/array.py -> chainer/chainer/utils/array.rb : [OK]

Tests
-----

$ ./run_tests.py

Will run all tests, that are supposed to work. If any test fails, it's a bug.

$ ./run_tests.py -a

Will run all tests including those that are known to fail (currently). It
should be understandable from the output.

$ ./run_tests.py -x
or
$ ./run_tests.py --no-error

Will run tests but ignore if an error is raised by the test. This is not
affecting the error generated by the test files in the tests directory.

For more flags then described here

./run_tests.py -h


License
-------

MIT, see the LICENSE file for exact details.