enthought / traits

Observable typed attributes for Python classes
Other
421 stars 85 forks source link

`Constant` constraint not enforced in `Union` #1784

Open k2bd opened 3 months ago

k2bd commented 3 months ago

Constant constraint is not enforced when initializing Union (came up in writing tests for #1298)

class TestClass(HasTraits):
    attribute = Union(None, Constant(123))

a = TestClass(attribute=456)  # No exception raised
a.attribute  # 456
k2bd commented 3 months ago

Sorry for the edits, I think there are multiple things going on here, which threw me off.


Scenario 1: Setting default_value on Union:

class TestClass(HasTraits):
    attribute = Union(None, Constant(123), default_value=55)

a = TestClass()
a.attribute  # 55

No validation -> I think this may be a need for some additional validation logic in Union's __init__. I think this isn't directly related to Constant but to a lack of validation in Union (though simply adding validation at the moment I think would cause issues specifically with Constant; see Scenario 2)


Scenario 2: Set value on an existing HasTraits object w/ Union trait

class TestClass(HasTraits):
    attribute = Union(None, Constant(123))

a = TestClass()
a.attribute = 456

a.attribute  # 456

I think the cause of this is that the validate method of Constant is permissive; doesn't use its setter logic:

class TestClass(HasTraits):
    attribute = Constant(123)

a = TestClass()
const_trait = a.traits()["attribute"]

const_trait.validate(a, "attribute", 456)  # 456

And this is used in Union to validate new values

This may have effects elsewhere too