PythonのコードをPython ASTベースでRubyに変換を行う py2rb.py 0.1.0 をリリースしました。


8 RejectKaigi 2017 PythonPython ASTRuby py2rb.pypython  PyPI

pypi.python.org

github.com


py2rb.py Python Chainer  Ruby PythonRuby

py2rb.py  blog 

naitoh.hatenablog.com

特徴
  • Python ASTベースで1行単位にRubyへ翻訳
    1. Python => Ruby (メソッド,クラス,変数) : decorator や yield 等は未サポート
    2. import 文を解釈し、ローカルのモジュールファイルを参照&一括変換
    3. Python標準ライブラリ=>Ruby標準ライブラリ : (Chainer で使われている 73 モジュール のうち 10モジュールを仮実装)
  • ドメインが同じライブラリ間でPython=>Rubyに置き換え
    1. numpy => Numo::NArray (Chainer で使われている 116 メソッド のうち 31メソッドを仮実装)
    2. unittest => test::unit (Chainer で使われている 33 メソッド のうち 4メソッドを仮実装)
実行方法
$ py2rb
Usage: py2rb.py [options] filename.py
    or py2rb.py [-w [-f]] [-(r|b)] [-v] filename.py
    or py2rb.py -p foo/bar/ -m [-w [-f]] [-(r|b)] [-v] foo/bar/filename.py
    or py2rb -l lib_store_directory/ [-f]

Usage  Python 
(0.1.0 import )
"-w" filename.py  filename.rb 
 filename.rb  Skip  "-f" 
"-m" 



Python :
$ git clone git://github.com/naitoh/py2rb.git
$ cat py2rb/tests/strings/zipstring.py
s1 = "hello"
s2 = "world"
s3 = "abcd"

s4 = list(zip(s1,s2,s3))

for item in s4:
    print("----")
    for val in item:
        print(val)

Python:
$ python py2rb/tests/strings/zipstring.py
----
h
w
a
----
e
o
b
----
l
r
c
----
l
l
d

:
$ py2rb -r py2rb/tests/strings/zipstring.py
# frozen_string_literal: true

require 'module'

using EnumerableEx
using PythonZipEx
using PythonPrintEx
using PythonIsBoolEx
using PythonIndexEx
using PythonFindEx
using PythonSplitEx
using PythonStripEx
using PythonStringCountEx
using PythonRemoveEx
using PythonMethodEx

s1 = "hello"
s2 = "world"
s3 = "abcd"
s4 = zip_p(s1, s2, s3).to_a
for item in s4
  print("----")
  for val in item
    print(val)
  end
end

 Python  zip  Ruby zip_p 
Python  Ruby 使
"using PythonZipEx"  using 

"-w" 
$ py2rb -r py2rb/tests/strings/zipstring.py -w
Try  : py2rb/tests/strings/zipstring.py -> py2rb/tests/strings/zipstring.rb : [OK]

"-l" 
$ py2rb -l .
OK :  ./module.rb file was stored.

Ruby  -I  module.rb 

Ruby:
$ ruby -I . py2rb/tests/strings/zipstring.rb
----
h
w
a
----
e
o
b
----
l
r
c
----
l
l
d

Python 

chainer 

$ git clone git://github.com/chainer/chainer.git
$ cat chainer/chainer/variable.py
import collections
import copy
import heapq
import traceback
import warnings
import weakref

import numpy

import chainer
from chainer.backends import cuda
from chainer import initializers
from chainer.initializers import constant
from chainer.utils import argument

def _check_grad_type(func, x, gx):
    if x.data is None orgxis None:
        # ``x.data is None`` implies that the data array is not retained
        return
    if not isinstance(gx, type(x.data)):
        msg = ('Type of data and grad mismatch\n%s != %s' %
               (type(x.data), type(gx)))
        typ = TypeError
    elif gx.dtype != x.data.dtype:
        msg = ('Dtype of data and grad mismatch\n%s != %s' %
               (x.data.dtype, gx.dtype))
        typ = TypeError
    elif gx.shape != x.data.shape:
        msg = ('Shape of data and grad mismatch\n%s != %s' %
               (x.data.shape, gx.shape))
        typ = ValueError
    else:
        return

    detail = ''
    if func:
        detail = 'Function `{0}` ({1}) has a bug.\n'.format(
            type(func)._impl_name, func.label)
        stack = func.stack
        if stack:
            detail += 'Stacktrace of the function is below:\n'
            for line in traceback.format_list(func.stack):
                detail += line
        detail += '''
Please report this error to the issue tracker with the stack trace,
the information of your environment, and your script:
https://github.com/chainer/chainer/issues/new.
'''.format(type(func).__name__, func.label)

    raise typ(detail + msg)
(略)

$ py2rb -p chainer chainer/chainer/variable.py
module Chainer
  module Variable
    require 'weakref'
    require_relative 'backends/cuda'
    include Chainer::Backends
    require_relative 'chainer'
    include Chainer
    require_relative 'initializers/constant'
    include Chainer::Initializers
    require_relative 'utils/argument'
    include Chainer::Utils
    def _check_grad_type(func, x, gx)
      if is_bool((x.data === nil)||(gx === nil))
        return
      end
      if is_bool(!(gx.is_a? (x.data).class))
        msg = "Type of data and grad mismatch
%s != %s" % [(x.data).class, (gx).class]
        typ = ArgumentError
      else
        if gx.dtype != x.data.dtype
          msg = "Dtype of data and grad mismatch
%s != %s" % [x.data.dtype, gx.dtype]
          typ = ArgumentError
        else
          if gx.shape != x.data.shape
            msg = "Shape of data and grad mismatch
%s != %s" % [x.data.shape, gx.shape]
            typ = TypeError
          else
            return
          end
        end
      end
      detail = ""
      if is_bool(func)
        detail = "Function `{0}` ({1}) has a bug.
".format((func).class._impl_name, func.label)
        stack = func.stack
        if is_bool(stack)
          detail += "Stacktrace of the function is below:
"
          for line in (func.stack).to_a
            detail += line
          end
        end
        detail += "
Please report this error to the issue tracker with the stack trace,
the information of your environment, and your script:
https://github.com/chainer/chainer/issues/new.
".format((func).class.__name__, func.label)
      end
      raise typ, (detail)+(msg)
    end
(略)



Python "-m"  "-p" python  ( chainer/chainer/variable.py) 便
$ py2rb -p chainer chainer/chainer/variable.py -m -w
Try  : chainer/chainer/functions/math/fmod.py -> chainer/chainer/functions/math/fmod.rb : [OK]
Try  : chainer/chainer/functions/array/expand_dims.py -> chainer/chainer/functions/array/expand_dims.rb : [OK]
Try  : chainer/chainer/functions/pooling/average_pooling_nd.py -> chainer/chainer/functions/pooling/average_pooling_nd.rb : [OK]
Warning : syntax not supported (<_ast.ExtSlice object at 0x102df11d0>)
Warning : ExtSlice not supported (path[]) in Assign(ast.Subscript)
Warning : syntax not supported (<_ast.ExtSlice object at 0x102df11d0>)
Warning : syntax not supported (<_ast.ExtSlice object at 0x102dd35f8>)
Warning : syntax not supported (<_ast.ExtSlice object at 0x102ddef28>)
()

 Warning 

Red Data Tool  Chainer  Ruby Red Chainer  Join  py2rb.py 使 (py2rb.py )

github.com

Red Chainer  py2rb.py 

使