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 ?
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.