gopy icon indicating copy to clipboard operation
gopy copied to clipboard

add snakecase conversion for struct fields in genStructInit

Open emar-kar opened this issue 11 months ago • 0 comments

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"}

emar-kar avatar Dec 17 '24 17:12 emar-kar