Closed mdsmarte closed 2 years ago
Thanks for the report. All things being equal, I'd expect not to be able to assign a List
where a tuple is expected, so I'd call this a bug in the bar
case. Though there's potential for breakage when we fix this, so I don't think it should be fixed in a bugfix release - it should wait for the next feature release.
Part of the difference is coming from the difference in validation between Tuple
and BaseTuple
: Tuple
insists on a tuple, while BaseTuple
happily accepts a list. But why we're ending up with the BaseTuple
validation behaviour instead of the Tuple
validation behaviour inside the list, I'm not sure. It may have to do with the way that the fast validation gets set.
Python 3.10.2 (main, Jan 15 2022, 10:49:49) [Clang 12.0.5 (clang-1205.0.22.11)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from traits.api import *
>>> class Test(HasTraits):
... foo = Tuple(Int(), Int())
... bar = BaseTuple(Int(), Int())
...
>>> t = Test()
>>> t.bar = [1, 2]
>>> t.bar
(1, 2)
>>> t.foo = [1, 2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mdickinson/Enthought/ETS/traits/traits/base_trait_handler.py", line 74, in error
raise TraitError(
traits.trait_errors.TraitError: The 'foo' trait of a Test instance must be a tuple of the form: (an integer, an integer), but a value of [1, 2] <class 'list'> was specified.
>>> t.foo
(0, 0)
Okay, I think there are two bugs here.
Tuple.validate
validation semantics (which are currently inherited from BaseTuple
) don't match the fast_validate validation. We can either fix this in BaseTuple
, or if we're feeling cautious, we can reimplement the validate
method in Tuple
. It's probably reasonably safe to fix in BaseTuple
if we're not releasing the change in a bugfix release.TraitListObject
is using .handler.validate
on the inner trait instead of plain old .validate
. I'm not sure what might break if we change this.Separately from this, we might want to tighten the BaseTuple
validation to only accept tuples. That would be a breaking change, so it would need a deprecation warning, but my guess would be that there's very little code that's using BaseTuple
directly.
Closing here. Current status:
Tuple()
is deprecated.BaseTuple()
is not yet deprecated; #1626 is open to track this.
The
Tuple
trait coerces list input to a tuple when it is nested within aList
trait, but not when it is a top-level trait.It is ambiguous which behavior is "correct." Should a top-level
Tuple
trait coerce a list to a tuple or should a nestedTuple
trait raise an error for list input?