gopy
gopy copied to clipboard
add snakecase conversion for struct fields in genStructInit
Hello there, first of all, thank you for this amazing project!
While experimenting with it, I came across something that seems like unusual behavior when passing arguments into a Python class constructor.
I wrote a small code in go:
package lib
import "fmt"
type Test struct {
Name string
}
func (t *Test) Print() {
fmt.Printf("%#v\n", t)
}
After bindings generation, init looks like this:
class Test(go.GoClass):
def __init__(self, *args, **kwargs):
if len(kwargs) == 1 and 'handle' in kwargs:
self.handle = kwargs['handle']
_ginit.IncRef(self.handle)
elif len(args) == 1 and isinstance(args[0], go.GoClass):
self.handle = args[0].handle
_ginit.IncRef(self.handle)
else:
self.handle = _ginit.lib_Test_CTor()
_ginit.IncRef(self.handle)
if 0 < len(args):
self.Name = args[0]
if "Name" in kwargs:
self.Name = kwargs["Name"]
And works as intended:
>>> t = lib.Test(Name="Name")
>>> t
lib.Test ( Name=Name, handle=1, )
>>> t.Print()
&lib.Test{Name:"Name"}
>>> t.Name = "New name"
>>> t
lib.Test ( Name=New name, handle=1, )
>>> t.Print()
&lib.Test{Name:"New name"}
But as soon as I pass -rename=true flag, magic is happening. Init function does not change and gopy generates setter/getter for renamed name field:
>>> t = lib.Test()
>>> t
lib.Test ( handle=2, name=, )
>>> del t
>>> t = lib.Test(Name="Name")
>>> t
lib.Test ( Name=Name, handle=1, name=, )
>>> t.print()
&lib.Test{Name:""}
>>> t.name = "Name"
>>> t
lib.Test ( Name=Name, handle=1, name=Name, )
>>> t.print()
&lib.Test{Name:"Name"}
>>> del t
>>> t = lib.Test(name="Name")
>>> t
lib.Test ( handle=3, name=, )
>>> t.print()
&lib.Test{Name:""}
>>> del t
>>> t = lib.Test("Name")
>>> t
lib.Test ( Name=Name, handle=4, name=, )
>>> t.print()
&lib.Test{Name:""}
Instead of assigning the value to name in constructor, it creates a new property inside the Python class that is never actually used. Even if I pass a string as an argument or try using the newly created snake-cased name nothing changes. The only way is to use setter/getter methods after the class is created.
This change adds snake-case conversion of struct fields, in __init__ the way it allows to pass variables into constructor.
>>> t = lib.Test("Name")
>>> t
lib.Test ( handle=1, name=Name, )
>>> t.print()
&lib.Test{Name:"Name"}
>>> del t
>>> t = lib.Test(name="Name")
>>> t
lib.Test ( handle=2, name=Name, )
>>> t.print()
&lib.Test{Name:"Name"}