Skip to content

Simplify deferred creation of default values#23

Closed
SylvainCorlay wants to merge 4 commits intoipython:masterfrom
SylvainCorlay:DefaultValue
Closed

Simplify deferred creation of default values#23
SylvainCorlay wants to merge 4 commits intoipython:masterfrom
SylvainCorlay:DefaultValue

Conversation

@SylvainCorlay
Copy link
Member

This is an attempt to simplify initialization of default values.

The behavior is slightly different in that now:

class Foo(HasTraits):
    bar = Int()

# triggers a trait notification
foo = Foo()
foo.bar = 0

# does not triggers a trait notification
foo = Foo(bar=0)
foo.bar = 0

# accessing the uninitialized trait initiates the default value
foo = Foo()
print(foo.bar)  # prints 0

Previously, the first example would not trigger a trait notification since 0 is equal to the default value which was initialized. I realize this is quite a change, but it really simplifies the code.

@SylvainCorlay
Copy link
Member Author

@takluyver let me know what you think. This is completely deferring the initialization of default values to the first __get__ call. I like that it removes a lot of code.

@SylvainCorlay SylvainCorlay force-pushed the DefaultValue branch 5 times, most recently from 2b47c9f to 5ac9d8b Compare June 3, 2015 03:28
@SylvainCorlay
Copy link
Member Author

This actually does what @minrk was suggesting there ipython/ipython#8107 (comment) .

This should make a lot of the allow_none=True introduced in ipython/ipython#8107 and ipython/ipython#7708 unnecessary.

@SylvainCorlay SylvainCorlay force-pushed the DefaultValue branch 4 times, most recently from 674c49f to 1793f0c Compare June 4, 2015 21:13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like these removed tests should still be failing, rather than removed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it requires adding a request for the trait, that's okay, too, but the tests shouldn't be removed altogether.

@SylvainCorlay SylvainCorlay force-pushed the DefaultValue branch 2 times, most recently from ee5a17f to 776cb87 Compare June 5, 2015 03:12
@SylvainCorlay
Copy link
Member Author

Rebased upon #28

@takluyver
Copy link
Member

I think we can avoid the behaviour change if, in __set__, we change this:

try:
    old_value = obj._trait_values[self.name]
except KeyError:
    old_value = Undefined

to this:

try:
    old_value = obj._trait_values[self.name]
except KeyError:
    old_value = self.default_value

self.default_value is Undefined in cases where there's no obvious default, but it is e.g. 0 for an integer if no default was supplied.

@SylvainCorlay SylvainCorlay force-pushed the DefaultValue branch 3 times, most recently from b59b345 to 4b3242f Compare June 10, 2015 14:28
@SylvainCorlay
Copy link
Member Author

@takluyver I tried your suggestion but it still fails the test for bad defaults.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to avoid adding yet another method, especially in a PR called 'Simplify...'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is part of #28, can we debate this there?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed like these two PRs were part of the same thing, but I guess that's not how you see it? Should I ignore this one until we have reached a decision on #28?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess so.

@takluyver
Copy link
Member

It looks like you've got rid of all the changes to tests - does that mean that it no longer changes behaviour?

@SylvainCorlay
Copy link
Member Author

No, a commit is missing. Just need a minute.

takluyver added a commit to takluyver/traitlets that referenced this pull request Jun 12, 2015
This is an alternative to ipython#23 and ipython#28

There is already a mechanism for dynamic default values with
_foo_default methods, which are not called unless needed. This makes the
default values for Instance traitlets use that same mechanism, avoiding
instantiating classes unless those traitlets are explicitly requested
without being assigned first.

Along the way, two other changes to behaviour, and hence to tests, came
in. Dict traitlets are based on Instance, so their behaviour changes in
the same way. And a Type() traitlet with no class specified now gets a
default value of object instead of None, because the former is valid
when allow_none is True.

It was also possible to clean up some parts of the machinery.
@SylvainCorlay
Copy link
Member Author

Closing this one for now, since it changes the behavior and we are close to 4.0.

@minrk minrk modified the milestone: no action Nov 9, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants