nottheswimmer / pytago Goto Github PK
View Code? Open in Web Editor NEWA source-to-source transpiler for Python to Go translation
Home Page: https://pytago.dev/
License: MIT License
A source-to-source transpiler for Python to Go translation
Home Page: https://pytago.dev/
License: MIT License
Hi there! Cool project. I gave it a play with some simple example code and noticed that looping over the lines of an open file object does not translate properly yet, so I thought I would leave this bug report here.
def main():
fh = open("file.txt")
for line in fh:
print(lin)
fh.close()
with open("file2.txt") as fh2:
for line in fh2:
print(line)
if __name__ == '__main__':
main()
Currently translates to:
package main
import "fmt"
func main() {
fh := open("file.txt")
for _, line := range fh {
fmt.Println(lin)
}
fh.close()
func() {
fh2 := open("file2.txt")
defer func() {
if err := fh2.Close(); err != nil {
panic(err)
}
}()
for _, line := range fh2 {
fmt.Println(line)
}
}()
}
# ecoding=utf-8
import json
import getopt
import os
import sys
import MySQLdb
Describe the bug
A clear and concise description of what the bug is.
tuple unpack
Python code example
The simplest possible Python code example to demonstrate the bug.
def main():
zz,*x = (0,0,0,0)
print(zz,x)
if __name__ == '__main__':
main()
Current behavior
What the program currently outputs for the code example.
package main
import "fmt"
func main() {
zz, x := 0, 0, 0, 0
fmt.Println(zz, x)
}
Expected behavior
A clear and concise description of what you expected to happen.
x becomes a tuple.
Go code example
Optional. An example of a satisfactory Go code output for the Python example.
this may helps
https://stackoverflow.com/questions/19832189/unpack-slices-on-assignment
Describe the bug
A clear and concise description of what the bug is.
map(int,["1","2"])
convert wrong
Python code example
The simplest possible Python code example to demonstrate the bug.
def main():
x=map(int,["1","2"])
print(x)
if __name__ == '__main__':
main()
Current behavior
What the program currently outputs for the code example.
package main
import "fmt"
func main() {
x := func() func() <-chan int {
wait := make(chan struct{})
yield := make(chan int)
go func() {
defer close(yield)
<-wait
for _, x := range []string{"1", "2"} {
yield <- int(x)
<-wait
}
}()
return func() <-chan int {
wait <- struct{}{}
return yield
}
}()
fmt.Println(x)
}
Expected behavior
A clear and concise description of what you expected to happen.
int should be translated.
Go code example
Optional. An example of a satisfactory Go code output for the Python example.
def main():
print(int("1"))
if __name__ == '__main__':
main()
this returns a good result.
package main
import (
"fmt"
"strconv"
)
func main() {
fmt.Println(func() int {
i, err := strconv.ParseInt("1", 10, 64)
if err != nil {
panic(err)
}
return int(i)
}())
}
usage: Pytago [-h] [-o OUTFILE] INFILE
pytago -o test.go test.py
It output an error when using the above command.
D:\PythonProject>pytago test.py
Traceback (most recent call last):
File "D:\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "D:\Python\Python310\lib\runpy.py", line 86, in _run_code
exec(code, run_globals)
File "D:\Python\Python310\Scripts\pytago.exe\__main__.py", line 7, in <module>
File "D:\Python\Python310\lib\site-packages\pytago\cmd.py", line 14, in main
go = python_to_go(f.read(), debug=False)
File "D:\Python\Python310\lib\site-packages\pytago\core.py", line 31, in python_to_go
return go_ast.unparse(go_tree, debug=debug)
File "D:\Python\Python310\lib\site-packages\pytago\go_ast\parsing.py", line 55, in unparse
externally_formatted_code = _golines(_gofumpt(_goimport(code)))
File "D:\Python\Python310\lib\site-packages\pytago\go_ast\parsing.py", line 251, in _goimport
p = Popen(["goimports"], stdout=PIPE, stderr=PIPE, stdin=PIPE)
File "D:\Python\Python310\lib\subprocess.py", line 966, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "D:\Python\Python310\lib\subprocess.py", line 1435, in _execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2]
It looks like it didn't find the file, but it does exist
Describe the bug
when using methods from the time
module, the only method that is translated properly is time.sleep()
, while the others result the same python code in Go.
Python code example
import time
def main():
print(time.time())
print(time.time_ns())
print(time.ctime(time.time()))
if __name__ == '__main__':
main()
Current behavior
the above three methods are not being translated into Go code but rather written as is in python, and this code is generated. which is not a valid Go code!
package main
import "fmt"
func main() {
fmt.Println(time.time())
fmt.Println(time.time_ns())
fmt.Println(time.ctime(time.time()))
}
Expected behavior
time.time()
should be translated into time.Now().Unix()
in Gotime.time_ns()
should be translated into time.Now().UnixNano()
in Gotime.ctime(time.time())
should be translated into time.Now()
in GoCorrect Go code example
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now().Unix())
fmt.Println(time.Now().UnixNano())
fmt.Println(time.Now())
}
Describe the bug
When the **
operator is used on integers in a list, they are passed to math.Pow
as-is. This does not work because math.Pow
takes float64 arguments.
Python code example
def main():
x = [2, 4]
print(x[0]**x[1])
if __name__ == '__main__':
main()
This works without a list because an integer literal is an untyped int
, which just becomes float64
when used in math.Pow
Current behavior
package main
import (
"fmt"
"math"
)
func main() {
x := []int{2, 4}
fmt.Println(math.Pow(x[0], x[1]))
}
Expected behavior
I expected there to be a type conversion to float64 before passing the value to math.Pow
Go code example
package main
import (
"fmt"
"math"
)
func main() {
x := []int{2, 4}
fmt.Println(math.Pow(float64(x[0]), float64(x[1])))
}
Describe the bug
when calling the type()
function in python it translates as is to the Go code, where it should translate to fmt.Printf("%T", v)
Python code example
def main():
b: bool = False
i: int = 12
c: chr = 'h'
f: float = 4.2
s: str = "bla bla"
print("type(b) = ", type(b))
print("type(i) = ", type(i))
print("type(c) = ", type(c))
print("type(f) = ", type(f))
print("type(s) = ", type(s))
if __name__ == '__main__':
main()
Current behavior
the python function type()
translates as is to Go(which Go doesn't have)
Expected behavior
package main
import "fmt"
func main() {
var b bool = false
var i int = 12
var c uint8 = 'h'
var f float64 = 4.2
var s string = "bla bla"
fmt.Printf("type(b) = %T\n", b)
fmt.Printf("type(i) = %T\n", i)
fmt.Printf("type(c) = %T\n", c)
fmt.Printf("type(f) = %T\n", f)
fmt.Printf("type(s) = %T\n", s)
}
Go code example
package main
func main() {
var b bool = false
var i int = 12
var c chr = "h" // here's bonus, chr doesn't translate well
var f float64 = 4.2
var s string = "bla bla"
fmt.Println("type(b) = ", type(b))
fmt.Println("type(i) = ", type(i))
fmt.Println("type(c) = ", type(c))
fmt.Println("type(f) = ", type(f))
fmt.Println("type(s) = ", type(s))
}
as seen the type functions translates as is to Go!
python's chr
type translates as is, where it should be translated into uint8
or rune
if it was unicode!
Describe the bug
Converting to bytes in python attempts to run a non-existent function bytes
.
Python code example
def main():
x = bytes("hello", "utf8")
print(x[0])
if __name__ == '__main__':
main()
Current behavior
package main
import "fmt"
func main() {
x := bytes("hello", "utf8")
fmt.Println(x[0])
}
Expected behavior
I expected the string to be converted to []byte
Go code example
package main
import "fmt"
func main() {
x := []byte("hello")
fmt.Println(x[0])
}
Describe the bug
Python classes have an __str__
method that defines how they are printed. Go structs have a String()
method that does the same.
Python code example
print("Hello, World!")
class A:
a = "huh?"
def __init__(self, val):
self.a = val
def __str__(self):
return self.a
val = A("ok")
print(val)
Current behavior
(relevant code):
func (self *A) __str__() {
return self.a
}
Expected behavior
func (self *A) String() {
return self.a
}
Describe the bug
Hi, I would like to transpile Python code with type annotations that include Optional
.
Python code example
Here's an example using a parameter, but ideally it would work anywhere type annotations are allowed.
from typing import Optional
def main(x: Optional[int] = None):
print("Hello world!")
Current behavior
Exception: [(<class 'pytago.go_ast.core.FuncLit'>, NotImplementedError(&ast.Ident { Name: "Optional" })), (<class 'pytago.go_ast.core.FuncType'>, NotImplementedError(&ast.Ident { Name: "Optional" }))]
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/username/pytago/pytago/go_ast/core.py", line 373, in _build_x_list
result = getattr(x_type, method)(x_node, **kwargs)
File "/Users/username/pytago/pytago/go_ast/core.py", line 893, in from_FunctionDef
rhs = build_expr_list([node])
File "/Users/username/pytago/pytago/go_ast/core.py", line 417, in build_expr_list
return _build_x_list(_EXPR_TYPES, "Expr", nodes, **kwargs)
File "/Users/username/pytago/pytago/go_ast/core.py", line 391, in _build_x_list
raise ValueError(f"No {x_name} type in {x_types} with {method}: "
ValueError: No Expr type in [<class 'pytago.go_ast.core.Expr'>, <class 'pytago.go_ast.core.ArrayType'>, <class 'pytago.go_ast.core.BadExpr'>, <class 'pytago.go_ast.core.BasicLit'>, <class 'pytago.go_ast.core.BinaryExpr'>, <class 'pytago.go_ast.core.Ident'>, <class 'pytago.go_ast.core.CallExpr'>, <class 'pytago.go_ast.core.ChanType'>, <class 'pytago.go_ast.core.CompositeLit'>, <class 'pytago.go_ast.core.Ellipsis'>, <class 'pytago.go_ast.core.FieldList'>, <class 'pytago.go_ast.core.FuncType'>, <class 'pytago.go_ast.core.FuncLit'>, <class 'pytago.go_ast.core.IndexExpr'>, <class 'pytago.go_ast.core.InterfaceType'>, <class 'pytago.go_ast.core.KeyValueExpr'>, <class 'pytago.go_ast.core.MapType'>, <class 'pytago.go_ast.core.ParenExpr'>, <class 'pytago.go_ast.core.SelectorExpr'>, <class 'pytago.go_ast.core.SliceExpr'>, <class 'pytago.go_ast.core.StarExpr'>, <class 'pytago.go_ast.core.StructType'>, <class 'pytago.go_ast.core.TypeAssertExpr'>, <class 'pytago.go_ast.core.UnaryExpr'>, <class 'pytago.go_ast.core.ValueSpec'>] with from_FunctionDef:
\```
def main(x: Optional[int]=None):
print('Hello world!')
\```
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/username/.pyenv/versions/pytago-venv-3.10.0/bin/pytago", line 33, in <module>
sys.exit(load_entry_point('pytago', 'console_scripts', 'pytago')())
File "/Users/username/pytago/pytago/cmd.py", line 14, in main
go = python_to_go(f.read(), debug=False)
File "/Users/username/pytago/pytago/core.py", line 30, in python_to_go
go_tree = go_ast.File.from_Module(py_tree)
File "/Users/username/pytago/pytago/go_ast/core.py", line 2520, in from_Module
go_module.Decls[:] = build_decl_list(node.body)
File "/Users/username/pytago/pytago/go_ast/core.py", line 431, in build_decl_list
decls.append(FuncDecl.from_global_code(node))
File "/Users/username/pytago/pytago/go_ast/core.py", line 2708, in from_global_code
body = from_this(BlockStmt, [node])
File "/Users/username/pytago/pytago/go_ast/core.py", line 343, in from_this
result = getattr(cls, from_method(node))(node)
File "/Users/username/pytago/pytago/go_ast/core.py", line 1280, in from_list
stmts = build_stmt_list(node_list)
File "/Users/username/pytago/pytago/go_ast/core.py", line 421, in build_stmt_list
return _build_x_list(_STMT_TYPES, "Stmt", nodes, **kwargs)
File "/Users/username/pytago/pytago/go_ast/core.py", line 378, in _build_x_list
raise type(e)(f"Unhandled exception for {x_name} type in {x_types} with {method}: "
ValueError: Unhandled exception for Stmt type in [<class 'pytago.go_ast.core.Stmt'>, <class 'pytago.go_ast.core.AssignStmt'>, <class 'pytago.go_ast.core.BadStmt'>, <class 'pytago.go_ast.core.BlockStmt'>, <class 'pytago.go_ast.core.BranchStmt'>, <class 'pytago.go_ast.core.CaseClause'>, <class 'pytago.go_ast.core.DeclStmt'>, <class 'pytago.go_ast.core.DeferStmt'>, <class 'pytago.go_ast.core.EmptyStmt'>, <class 'pytago.go_ast.core.ExprStmt'>, <class 'pytago.go_ast.core.ForStmt'>, <class 'pytago.go_ast.core.GoStmt'>, <class 'pytago.go_ast.core.IfStmt'>, <class 'pytago.go_ast.core.IncDecStmt'>, <class 'pytago.go_ast.core.LabeledStmt'>, <class 'pytago.go_ast.core.RangeStmt'>, <class 'pytago.go_ast.core.ReturnStmt'>, <class 'pytago.go_ast.core.SelectStmt'>, <class 'pytago.go_ast.core.SendStmt'>, <class 'pytago.go_ast.core.SwitchStmt'>, <class 'pytago.go_ast.core.TypeSwitchStmt'>] with from_FunctionDef:
\```
def main(x: Optional[int]=None):
print('Hello world!')
\```
Expected behavior
I expected that it would not raise an exception. In terms of output, perhaps a pointer to the type, an int in this case, would work. This would allow it to be nil
.
func main(x *int) {
fmt.Println("Hello world!")
}
Describe the bug
A clear and concise description of what the bug is.
Python code example
The simplest possible Python code example to demonstrate the bug.
def main():
def test(f):
def inner(*args):
print(args)
f(*args)
return inner
@test
def x(a,b):
return a,b
x(1,2)
if __name__ == '__main__':
main()
Current behavior
What the program currently outputs for the code example.
package main
import "fmt"
func main() {
test := func(f interface{}) {
inner := func() {
fmt.Println(args)
f(args...)
}
inner
}
x := func(a int, b int) [2]int {
return [2]int{a, b}
}
x(1, 2)
}
Expected behavior
A clear and concise description of what you expected to happen.
the decorator changes the function's behavior.
Go code example
Optional. An example of a satisfactory Go code output for the Python example.
Describe the bug
When I use pytago
on window 10
to translate hello.py
to main.go
. the result of main.go
is unexpted, what‘s wrong when I do this?
System: window 10
Python version: 3.10.0
Python source code: hello.py:
# For best results, keep your code inside functions
def main():
print("Hello world!")
if __name__ == '__main__':
main()
comand excuted: pytago -o main.go hello.py
result got: main.go
// # command-line-arguments
// C:\Users\ADMINI~1\AppData\Local\Temp\tmp257ukgv_.go:11:177: syntax error: unexpected <, expecting expression
// C:\Users\ADMINI~1\AppData\Local\Temp\tmp257ukgv_.go:11:192: more than one character in rune literal
// warning: -s is deprecated as it is always enabled
package main
import "fmt"
func main() {
fmt.Println("Hello world!")
}
It's probably my environment could not find go_ast on macOS?
Installed Go 1.16 and Python 3.10 beta 3 and go get other 2 dependencies:
/Library/Frameworks/Python.framework/Versions/3.10/bin/pytago
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/bin/pytago", line 5, in <module>
from pytago.cmd import main
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pytago/__init__.py", line 1, in <module>
from pytago.core import *
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pytago/core.py", line 3, in <module>
from pytago import go_ast
ImportError: cannot import name 'go_ast' from partially initialized module 'pytago' (most likely due to a circular import) (/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pytago/__init__.py)
Hello
Tried to convert sources from https://github.com/Rolf-Hempel/PlanetarySystemStacker/
Every file produces the same error:
raise ValueError(f"No {x_name} type in {x_types} with {method}: "
....
Don't know if it can be fixed easily though. I've used python long time ago and cannot get to the details.
I imagine changing stuff like this isn't within the scope of the project, but having at least an option to change snake_case variables to camel case could be useful to some people, especially those who aren't complete psychopaths.
I'll probably do this on my own time in a PR but I felt like opening this up in case somebody wants to do it instead of me, since it'll likely be awhile before I get around to it.
I can' get it to work in my environment. Even starting pytago without any arg leads to:
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "C:\Program Files\Python311\Scripts\pytago.exe\__main__.py", line 4, in <module>
File "C:\Program Files\Python311\Lib\site-packages\pytago\__init__.py", line 1, in <module>
from pytago.core import *
File "C:\Program Files\Python311\Lib\site-packages\pytago\core.py", line 24, in <module>
import astroid
File "C:\Program Files\Python311\Lib\site-packages\astroid\__init__.py", line 53, in <module>
from astroid import inference, raw_building
File "C:\Program Files\Python311\Lib\site-packages\astroid\inference.py", line 33, in <module>
import wrapt
File "C:\Program Files\Python311\Lib\site-packages\wrapt\__init__.py", line 10, in <module>
from .decorators import (adapter_factory, AdapterFactory, decorator,
File "C:\Program Files\Python311\Lib\site-packages\wrapt\decorators.py", line 34, in <module>
from inspect import ismethod, isclass, formatargspec
ImportError: cannot import name 'formatargspec' from 'inspect' (C:\Program Files\Python311\Lib\inspect.py)
(and the program aborts; similair Traceback if you try to import pytago
).
The python docu for 3.10.11 on inspect.formatargspec()
notes:
Deprecated since version 3.5: Use signature() and Signature Object, which provide a better introspecting API for callables.
where the 3.11 docu on inspect does not mention formatargspec()
.
My environment is:
Describe the bug
When using a list of different types, it is implemented as []interface{} as it should, but getting a value does not assert it to the proper type
Python code example
def main():
x = ["x", 1, 2, 3.0]
x.append(True)
print(x[1]+x[2])
if __name__ == '__main__':
main()
Current behavior
package main
import "fmt"
func main() {
x := []interface{}{"x", 1, 2, 3.0}
x = append(x, true)
fmt.Println(x[1] + x[2])
}
This creates an error because interfaces cannot be added.
Expected behavior
I expected that there would be a type assertion converting the values to int so they could be added
Go code example
package main
import "fmt"
func main() {
x := []interface{}{"x", 1, 2, 3.0}
x = append(x, true)
fmt.Println(x[1].(int) + x[2].(int))
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.