enthought / enthought/traits

Using a function as a default for a Callable in a child class fails

Open
#411 11 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
462
Forks
90
PR merge metrics
No merged PRs in 30d

Description

I have a `HasTraits` class with some `Callable` traits, and a second class that derives from it. I was trying to set the defaults for these traits as class variables, but I noticed that sometimes these defaults didn't get applied. The following example will make this clear. Here I have two Callables in the base class, and one is initialized in the derived class with a builtin function and one with a regular function. The latter does not get applied.

```python
from traits.api import HasStrictTraits, Callable

def regular_fun():
pass

builtin_fun = print

class A(HasStrictTraits):
f1 = Callable()
f2 = Callable()

class B(A):
f1 = builtin_fun
f2 = regular_fun

if __name__ == '__main__':
b = B()
assert b.f1 is not None
assert b.f2 is not None
```

Under the tested version (4.6.0) the first assert passes (as expected), but the second assert fails (`b.f2` is None).

This is because in `MetaHasTraitsObject` we check whether items in the class_dict are functions: https://github.com/enthought/traits/blob/b5cf152c446bb87d575b5ecdc4cda7f8b646d96f/traits/has_traits.py#L550-L553

Builtin functions don't pass this check, but regular functions do. So `f2` gets treated in this block and ultimately ignored, but `f1` skips this block and ends up in the `else` where we look at inherited class traits:

https://github.com/enthought/traits/blob/b5cf152c446bb87d575b5ecdc4cda7f8b646d96f/traits/has_traits.py#L577-L590

Here, `builtin_fun` gets correctly set as the default for `f1`, but `f2` has already been treated and therefore keeps it None default.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.