pythonenthought

AttributeError: 'TraitCompound' object has no attribute 'clone'


Let's say I want to create, using the Traits package, a "bases" attribute that can be a 'none' string or a dictionary with keys which are ‘hrf’ or ‘fourier’ or ‘fourier_han’ or ‘gamma’ or ‘fir’ and with values which are a dictionary with keys which are ‘derivs’ or ‘length' or ‘order’ and with values which are a list or a float). Ex:

bases == 'none'
or
bases == {'hrf': {'derivs': [0, 0]}}
or
bases == {'fourier': {'length': 1.4, 'order': 3}}

if I define a 'none' string or a dictionary with keys which are ‘hrf’ or ‘fourier’ or ‘fourier_han’ or ‘gamma’ or ‘fir’ and with values which are a dictionary with keys which are ‘derivs’ or ‘length' or ‘order’ and with values which are a list) it's working fine:

>>> import traits.api as traits
>>> class Foo(traits.HasTraits):
...  bases = traits.Either(traits.Dict(traits.Enum("hrf","fourier","fourier_han","gamma","fir"),traits.Dict(traits.Enum("derivs","length","order"), traits.List)),'none',default={"hrf":{"derivs":[0,0]}})
... 
>>> foo=Foo()
>>> foo.bases
{'hrf': {'derivs': [0, 0]}}

But this is not exactly what I want. If now I try to give the possibility to use list or float in the inside dictionary, it's not working:

 >>> import traits.api as traits
 >>> class Foo(traits.HasTraits):
...  bases = traits.Either(traits.Dict(traits.Enum("hrf","fourier","fourier_han","gamma","fir"),traits.Dict(traits.Enum("derivs","length","order"), traits.Either(traits.List, traits.Float))),'none',default={"hrf":{"derivs":[0,0]}})
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in Foo
  File "/home/econdami/.local/lib/python3.7/site-packages/traits/trait_types.py", line 2804, in __init__
    handler = handler.clone()
AttributeError: 'TraitCompound' object has no attribute 'clone'

why ?


Solution

  • It's not the first time I've interact with the team that develops the Traits project.

    As always, they very quickly managed to solve the problem and gave a very detailed answer on it.

    In a nutshell, as early as Traits 6.1, on the one hand, prefer:

    traits.Union(traits.Float, traits.List)
    

    to

    traits.Either(traits.Float, traits.List)
    

    On the other hand, pay attention to the default_value argument for Union() (default for Either()). It would be better to initialise it by other means.