traits
traits copied to clipboard
Trait initializers don't work consistent when copying with deepcopy
Don't know if this a bug, but at least i stumbled upon it:
According to documentation using "traits_init", overriding "init" or using dynamic initialization with "_name_default" should all lead to the same behavior. Nevertheless using "traits_init" yields different results when copying objects using this method.
import copy
from traits.api import *
class Bla(HasTraits):
blubb = Int(0)
class BaseModel(HasTraits):
bla: Bla = Instance(Bla)
class DunderInitModel(BaseModel):
def __init__(self, **traits):
super().__init__(**traits)
self.bla = Bla()
class TraitInitModel(BaseModel):
def traits_init(self):
self.bla = Bla()
if __name__ == '__main__':
m1 = DunderInitModel()
m1.bla.blubb = 999
print(f"Model1.bla.blubb (__init__): {copy.deepcopy(m1).bla.blubb}")
m2 = TraitInitModel()
m2.bla.blubb = 999
print(f"Model2.bla.blubb (traits_init): {copy.deepcopy(m2).bla.blubb}")
prints out:
Model1.bla.blubb (__init__): 999
Model2.bla.blubb (traits_init): 0
Those two operations should get the same result, shouldn't they?
I can see that inside traits.has_traits.HasTraits.clone_traits, traits_init is executed after copy_traits, which overwrites the copied traits.
Using Win10, traits version 6.3.2, Python 3.8
Thanks for the report. I'm a bit confused, though: can you clarify the role of the copy in your example code? Did you intend the print
statements in your example to be printing values from m1_copy
, m2_copy
and m3_copy
? (Otherwise, I'm not sure what m1_copy
, m2_copy
and m3_copy
are doing. Or are you reporting that simply the act of copying changes the original, which would definitely be a clear bug?)
Note that for traits_init
to work in the way that you intend, you'd need to make an assignment self.blubb = 1
inside the traits_init
method; just returning 1
won't do anything useful.
Hey, sorry. When trying to reduce the problem in my application to be simply reproducible, this typo "return 1" in traits_init made the example look like it is showing the bug i have (my app uses assignment to self inside traits_init). In my application it's more complicated since i have nested HasTraits objects and there i definitely see a difference between traits_init and init. Let me check again how to reproduce with a simple example, sorry for the confusion.
Ok i got it. Now you should be able to reproduce.