Skip to content

Instantly share code, notes, and snippets.

@reusee
Created June 20, 2011 16:49
Show Gist options
  • Save reusee/1035975 to your computer and use it in GitHub Desktop.
Save reusee/1035975 to your computer and use it in GitHub Desktop.
Python to php translator, compile python script to php
import ast
from cStringIO import StringIO
import sys
INFSTR = '1e308'
def interleave(inter, f, seq):
seq = iter(seq)
try:
f(next(seq))
except StopIteration:
pass
else:
for x in seq:
inter()
f(x)
class PythonToPhp:
def __init__(self, source, indent = 0):
tree = ast.parse(source)
self.code = StringIO()
self.tabstop = 2
self._indent = indent
self.dispatch(tree)
def get_code(self):
return self.code.getvalue()
def fill(self, text = ''):
self.code.write('\n%s%s' % (' ' * self.tabstop * self._indent, text))
def write(self, text):
self.code.write(text)
def enter(self):
self.code.write(' {')
self._indent += 1
def leave(self):
self._indent -= 1
self.fill('}')
def error(self, msg):
print msg
sys.exit()
def dispatch(self, tree):
if isinstance(tree, list):
for t in tree:
self.dispatch(t)
return
meth = getattr(self, '_%s' % tree.__class__.__name__)
return meth(tree)
########## Transform Methods ##########
def _Module(self, tree):
for stmt in tree.body:
self.dispatch(stmt)
### Statement ###
def _Expr(self, tree):
self.fill()
self.dispatch(tree.value)
self.write(';')
def _Import(self, t):
self.error('import not supported')
def _ImportFrom(self, t):
self.error('import not supported')
def _Assign(self, t):
self.fill()
for target in t.targets:
if isinstance(target, ast.Tuple):
self._lvalue_tuple(target)
else:
self.dispatch(target)
self.write(' = ')
self.dispatch(t.value)
self.write(';')
def _AugAssign(self, t):
self.fill()
self.dispatch(t.target)
name = t.op.__class__.__name__
if name == 'Pow':
self.write(' = pow(')
self.dispatch(t.target)
self.write(', ')
self.dispatch(t.value)
self.write(');')
elif name == 'FloorDiv':
self.write(' = floor(')
self.dispatch(t.target)
self.write(' / ')
self.dispatch(t.value)
self.write(');')
else:
self.write(' %s= ' % self.binop[t.op.__class__.__name__])
self.dispatch(t.value)
self.write(';')
def _Return(self, t):
self.fill('return')
if t.value:
self.write(' ')
self.dispatch(t.value)
self.write(';')
def _Pass(self, t):
self.fill(';')
def _Break(self, t):
self.fill('break;')
def _Continue(self, t):
self.fill('continue;')
def _Delete(self, t):
for target in t.targets:
self.fill('unset(')
self.dispatch(target)
self.write(');')
def _Assert(self, t):
self.fill('assert(')
self.dispatch(t.test)
self.write(');')
def _Exec(self, t):
self.fill('eval(')
self.dispatch(t.body)
self.write(');')
def _Print(self, t):
self.fill('echo ')
sep = ''
for e in t.values:
self.write(sep)
self.dispatch(e)
sep = ', '
if t.nl:
self.write(sep)
self.write("'<br />'")
self.write(';')
def _Global(self, t):
self.fill('global ')
interleave(lambda: self.write(', '), self.write, t.names)
self.write(';')
def _Yield(self, t):
self.error('yield not supported')
def _Raise(self, t):
self.error('Exceptions not supported')
def _TryExcept(self, t):
self.error('Exceptions not supported')
def _TryFinally(self, t):
self.error('Exceptions not supported')
def _ExceptHandler(self, t):
self.error('Exceptions not supported')
def _ClassDef(self, t):
self.error('Class not supported')
def _FunctionDef(self, t):
self.fill('function ' + t.name + '(')
self.dispatch(t.args)
self.write(')')
self.enter()
self.dispatch(t.body)
self.leave()
def _For(self, t):
self.fill('foreach (')
self.dispatch(t.iter)
self.write(' as ')
self.dispatch(t.target)
self.write(')')
self.enter()
self.dispatch(t.body)
self.leave()
if t.orelse:
self.error('else clause for for statement not supported')
def _If(self, t):
self.fill("if (")
self.dispatch(t.test)
self.write(')')
self.enter()
self.dispatch(t.body)
self.leave()
# collapse nested ifs into equivalent elifs.
while (t.orelse and len(t.orelse) == 1 and
isinstance(t.orelse[0], ast.If)):
t = t.orelse[0]
self.fill("elseif (")
self.dispatch(t.test)
self.write(')')
self.enter()
self.dispatch(t.body)
self.leave()
# final else
if t.orelse:
self.fill("else")
self.enter()
self.dispatch(t.orelse)
self.leave()
def _While(self, t):
self.fill("while (")
self.dispatch(t.test)
self.write(')')
self.enter()
self.dispatch(t.body)
self.leave()
if t.orelse:
self.error('else clause for while statement not supported')
def _With(self, t):
self.error('with statement not supported')
### Expression ###
def _Str(self, t):
self.write(repr(t.s))
def _Name(self, t):
if t.id == 'True':
self.write('true')
elif t.id == 'False':
self.write('false')
elif t.id == 'None':
self.write('null')
else:
self.write('$%s' % t.id)
def _Repr(self, t):
self.write('var_export(')
self.dispatch(t.value)
self.write(", true)")
def _Num(self, t):
repr_n = repr(t.n)
if repr_n.startswith('-'):
self.write('(')
self.write(repr_n.replace('inf', INFSTR))
if repr_n.startswith('-'):
self.write(')')
def _List(self, t):
self.write('array(')
interleave(lambda: self.write(", "), self.dispatch, t.elts)
self.write(')')
def _ListComp(self, t):
if len(t.generators) > 1:
self.error('multiple generators in comprehension not supported')
generator = t.generators.pop()
self._comprehension(generator, 'left')
self.dispatch(t.elt)
self._comprehension(generator, 'right')
def _comprehension(self, t, part = 'left'):
if part == 'left':
if t.ifs:
self.write('array_filter(array_map(function(')
else:
self.write('array_map(function(')
self.dispatch(t.target)
self.write(') { return ')
elif part == 'right':
self.write('; }, ')
self.dispatch(t.iter)
if t.ifs:
self.write('), function(')
self.dispatch(t.target)
self.write(') { return ')
for if_clause in t.ifs:
self.dispatch(if_clause)
self.write('; })')
else:
self.write(')')
def _GeneratorExp(self, t):
if len(t.generators) > 1:
self.error('multiple generators in comprehension not supported')
generator = t.generators.pop()
self._comprehension(generator, 'left')
self.dispatch(t.elt)
self._comprehension(generator, 'right')
def _SetComp(self, t):
if len(t.generators) > 1:
self.error('multiple generators in comprehension not supported')
self.write('array_unique(')
generator = t.generators.pop()
self._comprehension(generator, 'left')
self.dispatch(t.elt)
self._comprehension(generator, 'right')
self.write(')')
def _DictComp(self, t):
self.error('dict comprehension not supported')
def _IfExp(self, t):
self.write("((")
self.dispatch(t.test)
self.write(') ? (')
self.dispatch(t.body)
self.write(') : (')
self.dispatch(t.orelse)
self.write('))')
def _Set(self, t):
assert(t.elts) # should be at least one element
self.write('array_unique(array(')
interleave(lambda: self.write(", "), self.dispatch, t.elts)
self.write('))')
def _Dict(self, t):
self.write('array(')
def write_pair(pair):
k, v = pair
self.dispatch(k)
self.write(' => ')
self.dispatch(v)
interleave(lambda: self.write(', '), write_pair, zip(t.keys, t.values))
self.write(')')
def _Tuple(self, t):
self.write('array(')
interleave(lambda: self.write(", "), self.dispatch, t.elts)
self.write(')')
def _lvalue_tuple(self, t):
self.write('list(')
interleave(lambda: self.write(", "), self.dispatch, t.elts)
self.write(')')
unop = {"Invert":"~", "Not": "!", "UAdd":"+", "USub":"-"}
def _UnaryOp(self, t):
self.write("(")
self.write(self.unop[t.op.__class__.__name__])
self.write(" ")
if isinstance(t.op, ast.USub) and isinstance(t.operand, ast.Num):
self.write("(")
self.dispatch(t.operand)
self.write(")")
else:
self.dispatch(t.operand)
self.write(")")
binop = {
"Add":"+",
"Sub":"-",
"Mult":"*",
"Div":"/",
"Mod":"%",
"LShift":"<<",
"RShift":">>",
"BitOr":"|",
"BitXor":"^",
"BitAnd":"&",
}
def _BinOp(self, t):
name = t.op.__class__.__name__
if name == 'Pow':
self.write("(pow(")
self.dispatch(t.left)
self.write(', ')
self.dispatch(t.right)
self.write('))')
elif name == 'FloorDiv':
self.write('(floor(')
self.dispatch(t.left)
self.write(' / ')
self.dispatch(t.right)
self.write('))')
elif name == 'Mod' and isinstance(t.left, ast.Str):
self.write('sprintf(')
self.dispatch(t.left)
self.write(', ')
if isinstance(t.right, ast.Str):
self.dispatch(t.right)
elif isinstance(t.right, ast.Tuple):
interleave(lambda: self.write(", "), self.dispatch, t.right.elts)
else:
self.error('impossible string substript error')
self.write(')')
else:
self.write("(")
self.dispatch(t.left)
self.write(" " + self.binop[name] + " ")
self.dispatch(t.right)
self.write(")")
cmpops = {
"Eq":"==",
"NotEq":"!=",
"Lt":"<",
"LtE":"<=",
"Gt":">",
"GtE":">=",
"Is":"===",
"IsNot":"!==",
}
def _Compare(self, t):
name = t.ops[0].__class__.__name__
self.write("(")
if name == 'In':
comparator = t.comparators.pop()
self.write('in_array(')
self.dispatch(t.left)
self.write(', ')
self.dispatch(comparator)
self.write(') || array_key_exists(')
self.dispatch(t.left)
self.write(', ')
self.dispatch(comparator)
self.write(')')
elif name == 'NotIn':
comparator = t.comparators.pop()
self.write('!in_array(')
self.dispatch(t.left)
self.write(', ')
self.dispatch(comparator)
self.write(') && !array_key_exists(')
self.dispatch(t.left)
self.write(', ')
self.dispatch(comparator)
self.write(')')
else:
self.dispatch(t.left)
for o, e in zip(t.ops, t.comparators):
self.write(" " + self.cmpops[o.__class__.__name__] + " ")
self.dispatch(e)
self.write(")")
boolops = {ast.And: '&&', ast.Or: '||'}
def _BoolOp(self, t):
self.write("(")
s = " %s " % self.boolops[t.op.__class__]
interleave(lambda: self.write(s), self.dispatch, t.values)
self.write(")")
def _Attribute(self,t):
self.dispatch(t.value)
self.write("->")
self.write(t.attr)
def _func_name(self, t):
self.write('%s' % t.id)
def _Call(self, t):
self._func_name(t.func)
self.write("(")
comma = False
for e in t.args:
if comma: self.write(", ")
else: comma = True
self.dispatch(e)
for e in t.keywords:
if comma: self.write(", ")
else: comma = True
self.dispatch(e)
if t.starargs:
self.error('function vararg not supported')
if t.kwargs:
self.error('function kwarg not supported')
self.write(")")
def _Subscript(self, t):
if isinstance(t.slice, ast.Index):
#self.dispatch(t.value)
#self.write("[")
#self.dispatch(t.slice)
#self.write("]")
self.write('pyphp_subscript(')
self.dispatch(t.value)
self.write(', ')
self.dispatch(t.slice)
self.write(')')
elif isinstance(t.slice, ast.Slice):
self.write('array_slice(')
self.dispatch(t.value)
self.write(', ')
self.dispatch(t.slice)
self.write(')')
def _Ellipsis(self, t):
self.error('ellipsis not supported')
def _Index(self, t):
self.dispatch(t.value)
def _Slice(self, t):
if t.lower:
self.dispatch(t.lower)
else:
self.write('0')
if t.upper:
self.write(", ")
self.write('(')
self.dispatch(t.upper)
self.write(' - ')
if t.lower:
self.dispatch(t.lower)
else:
self.write('0')
self.write(')')
if t.step:
self.error('slice step not supported')
def _ExtSlice(self, t):
self.error('extslice not supported')
#interleave(lambda: self.write(', '), self.dispatch, t.dims)
### Others ###
def _arguments(self, t):
first = True
defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
for a,d in zip(t.args, defaults):
if first: first = False
else: self.write(", ")
self.dispatch(a),
if d:
self.write(" = ")
self.dispatch(d)
if t.vararg:
self.error('function vararg not supported')
if t.kwarg:
self.error('function kwarg not supported')
def _keyword(self, t):
self.write('$%s' % t.arg)
self.write(" = ")
self.dispatch(t.value)
def _Lambda(self, t):
self.write("(")
self.write("function(")
self.dispatch(t.args)
self.write(") {")
self.dispatch(t.body)
self.write("})")
def _alias(self, t):
self.error('alias not supported')
@jucier
Copy link

jucier commented Sep 19, 2015

d

@digitalgopnik
Copy link

Hey reusee,

nice and useful script, but how do i call it, if i want to convert my python_to_php_source_file.py to python_to_php_target_file.php?

Thanks,

ratze90 :) 👍

@vahidvdn
Copy link

vahidvdn commented Feb 6, 2017

Any example for using this?

@bitsnaps
Copy link

bitsnaps commented Apr 29, 2017

here is a simple usage:

s = 'print("ok")'
py2php = PythonToPhp(s)
print py2php.get_code()

this will output:
echo 'ok', '<br />';

@smartleopard
Copy link

Hello, first of all thank you for sharing this code. But why did PythonToPhp undefined? I tried several times. Second question, can I use this code to convert a whole .py script? Thank you for helping me. Really appreciate your help.

@bplancher
Copy link

bplancher commented Jan 3, 2018

Hello (and happy new year !) !

Thanks for this useful code ^^

If i can add my 2 cents, i propose you to add those few lines at the end of your file, so that it can be used in command-line directly (this is a very quick and not good-practice-proof implementation, but still working):

if __name__ == '__main__':
    if sys.argv[1:]:
        with open(sys.argv[1], 'r') as srcfile:
            ret = PythonToPhp(srcfile.read())
            print ret.code.getvalue()

@ashbeats
Copy link

Created 7 years ago

@agnius-vasiliauskas
Copy link

When I try to convert this code to PHP :

def ln(x):
    n = 1000.0
    return n * ((x ** (1/n)) - 1)
def calcNumEntropyBits(s):
        if len(s) <= 0: return 0.0
        symCount = {}
        for c in s:
                if c not in symCount: symCount[c] = 1
                else: symCount[c] += 1
        entropy = 0.0
        for c,n in symCount.iteritems():
                prob = n / float(len(s))
                entropy += prob * (ln(prob)/ln(2))
        if entropy >= 0.0: return 0.0
        else: return -(entropy*len(s))

def testEntropy(s):
        print "Bits of entropy in '%s' is %.2f" % (s, calcNumEntropyBits(s))

testEntropy('hello world')
testEntropy('bubba dubba')
testEntropy('aaaaaaaaaaa')
testEntropy('aaaaabaaaaa')
testEntropy('abcdefghijk')

I get a translator error :

py2php = PythonToPhp(s)
File "/py2php/py2php.py", line 25, in init
self.dispatch(tree)
File "/py2php/py2php.py", line 54, in dispatch
return meth(tree)
File "/py2php/py2php.py", line 60, in _Module
self.dispatch(stmt)
File "/py2php/py2php.py", line 54, in dispatch
return meth(tree)
File "/py2php/py2php.py", line 179, in _FunctionDef
self.dispatch(t.body)
File "/py2php/py2php.py", line 51, in dispatch
self.dispatch(t)
File "/py2php/py2php.py", line 54, in dispatch
return meth(tree)
File "/py2php/py2php.py", line 184, in _For
self.dispatch(t.iter)
File "/py2php/py2php.py", line 54, in dispatch
return meth(tree)
File "/py2php/py2php.py", line 464, in _Call
self._func_name(t.func)
File "/py2php/py2php.py", line 461, in _func_name
self.write('%s' % t.id)
AttributeError: 'Attribute' object has no attribute 'id'

Can you fix this converter error ?

@hsa599
Copy link

hsa599 commented May 27, 2021

Thank you for this useful code

@rai-shahnawaz
Copy link

How can I use this script? please explain.

@dheerendra-inspizone
Copy link

import requests

print('################################################################\n'
'Simple Program in Python to use certificate generated for Get API\n'
'################################################################\n'
'Please get ready the GET API URL\n')

try:
request_url = input("Enter URL to continue: ")
response = requests.get(request_url, cert=('/Users/Ming/SampleCode/cert.pem', '/Users/Ming/SampleCode/key.pem')
)
print("Status Code: ", response.status_code)
print(response.json())
except:
print("Please check whether input URL or certificate path is valid")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment