-
-
Save reusee/1035975 to your computer and use it in GitHub Desktop.
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') |
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 :) 👍
Any example for using this?
here is a simple usage:
s = 'print("ok")'
py2php = PythonToPhp(s)
print py2php.get_code()
this will output:
echo 'ok', '<br />';
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.
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()
Created 7 years ago
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 ?
Thank you for this useful code
How can I use this script? please explain.
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")
d