Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a DeprecationWarning for when edit is false in configure_traits() #1272

Closed
wants to merge 11 commits into from

Conversation

avats-dev
Copy link
Contributor

@avats-dev avats-dev commented Aug 13, 2020

fixes #1271

somewhat similar to #792

Checklist

  • Tests
  • Update API reference (docs/source/traits_api_reference)
  • Update User manual (docs/source/traits_user_manual)
  • Update type annotation hints in traits-stubs

@kitchoi
Copy link
Contributor

kitchoi commented Aug 13, 2020

Hi @avats-dev

Thank you for this! I think the CI is unhappy about building the documentation, i.e. this line fails:

- pushd docs && python3 -m sphinx -b html -W source build && popd

The error message is the following:

Extension error:
Handler <function _process_docstring at 0x7f662dadf730> for event 'autodoc-process-docstring' threw an exception (exception: <method 'trait_items_event' of 'traits.ctraits.CHasTraits' objects> is not a module, class, method, function, traceback, frame, or code object)
The command "pushd docs && python3 -m sphinx -b html -W source build && popd" exited with 2.

The last successful build was using Sphinx 3.1.2. The CI build for this PR is using Sphinx 3.2.0.
Since the error message is complaining about a method that is not modified in this PR, I suspect the error to be orthogonal and may just be caused by the Sphinx upgrade (combined with an actual documentation issue).
If that is true, I think we can deal with this in a separate PR, not this one.

Back to the deprecation on edit. :)

I think the intended outcome of this deprecation is that no one should be calling configure_traits with the edit argument anymore.

e.g.
There should be no deprecation warnings for this:

model.configure_traits()

But there should be deprecation warning for this:

model.configure_traits(edit=True)

And deprecation warning for this:

model.configure_traits(edit=False)

I think in this PR, we get deprecation warning for this:

model.configure_traits(edit=False)

but not for this:

model.configure_traits(edit=True)

I think we want to emit deprecation even when edit is explicitly set to True. However, while we do that, we need to make sure no deprecation warnings is emitted if the argument is not set (because that's the goal).

So we are almost there, but not quite yet. Could you modify this PR please?

@kitchoi
Copy link
Contributor

kitchoi commented Aug 13, 2020

Since the error message is complaining about a method that is not modified in this PR, I suspect the error to be orthogonal and may just be caused by the Sphinx upgrade (combined with an actual documentation issue).
If that is true, I think we can deal with this in a separate PR, not this one.

Confirmed this is an issue for master too. I opened #1273.

@avats-dev
Copy link
Contributor Author

Thanks @kitchoi for the analysis and review. I think you're right about the deprecation warning if edit is set explicitly, I never thought about this. I will update the PR soon with the changes. :) 👨‍💻

And good catch on that failing CI.

@avats-dev
Copy link
Contributor Author

Hey @kitchoi , how can I check if the default argument is passed explicitly or not?

I got some insight from here and I'm thinking of using inspect module. I could use some help.

@kitchoi
Copy link
Contributor

kitchoi commented Aug 18, 2020

I'd probably change the default value of edit to None, then check for it inside the function body. It should be similar to the if filename is not None in the top of the function, but for edit, its value needs to be flipped back to True when the value is None.

@kitchoi
Copy link
Contributor

kitchoi commented Aug 18, 2020

I'd probably change the default value of edit to None, then check for it inside the function body. It should be similar to the if filename is not None in the top of the function, but for edit, its value needs to be flipped back to True when the value is None.

That said, this won't catch the situation where someone calls configure_traits(edit=None), but that should be rare (or nonexisting), and could almost be considered a misuse given the description of the method said the argument should be a bool.

I got some insight from here and I'm thinking of using inspect module. I could use some help.

Looks like inspect could be used to solve a more general problem, while it could probably solve the problem even for the configure_traits(edit=None) edge case, I am leaning towards thinking that might be an overkill.

@avats-dev
Copy link
Contributor Author

Looks like inspect could be used to solve a more general problem, while it could probably solve the problem even for the configure_traits(edit=None) edge case, I am leaning towards thinking that might be an overkill.

Ok, I also thought that it might be an overkill here, and so I think I'll just go with the edit=None idea and then flip it in the function to True if it is None. Thanks for the insight, will update the PR soon.

@mdickinson
Copy link
Member

Hi @avats-dev! Do you think you'll have time to finish this one off? Don't worry if not - just let us know, and we'll pick it up from here.

@avats-dev
Copy link
Contributor Author

avats-dev commented Sep 1, 2020

@mdickinson I got busy with something else so I couldn't complete this. I'll finish this soon. 🚀

@avats-dev
Copy link
Contributor Author

Updated 🎉
Suggestions @mdickinson @kitchoi

@mdickinson
Copy link
Member

The Appveyor failure is a known issue that's independent of this PR, and should be fixed by #1290.

@@ -2034,7 +2037,7 @@ def configure_traits(
with open(filename, "rb") as fd:
self.copy_traits(pickle.Unpickler(fd).load())

if edit:
if edit is None:
Copy link
Member

@mdickinson mdickinson Sep 7, 2020

Choose a reason for hiding this comment

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

I think we can refactor this a bit to remove duplication: the goal would be to not have the same logic expressed in different branches. (Read up on the "DRY Principle" for some of the rationale for avoiding duplication.)

If you do something like:

if edit is None:
    edit = True
else:
    warnings.warn(...)

here, then you should be able to leave the rest of the code unchanged.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But as we're showing warning for both edit=True and edit=False, then refactoring like

if edit is None:
    edit = True
else:
    warnings.warn(...)

would give warning even on None, but we don't want that.

I've added spaces as mentioned and refactored code. See if it's good?

Sorry for being late. I was out of station for some days so I was not able to work on this.

Copy link
Member

Choose a reason for hiding this comment

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

would give warning even on None

I don't see how. If edit is None, then the first branch of the if statement is taken, and no warning is given. If edit is not None, then the else branch is taken, and a warning is given. I think that exactly matches what we want, doesn't it?

Copy link
Member

@mdickinson mdickinson left a comment

Choose a reason for hiding this comment

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

Thanks for the new commits! There's a fix needed for the deprecation notes in the documentation, and a suggested reworking to remove some of the duplication.

traits/has_traits.py Outdated Show resolved Hide resolved
@mdickinson
Copy link
Member

The logic still isn't right here; luckily, the tests are failing, which is exactly what they're designed to do (yay!).

Can you dig into the test failures and figure out what's wrong? I also highly recommend running the tests yourself locally while you're developing, in addition to the manual testing.

You can run just the relevant tests with:

$ python -m unittest -v traits.tests.test_configure_traits

Here's what I currently see on my machine when I run those tests:

(traits) mdickinson@mirzakhani traits % python -m unittest traits.tests.test_configure_traits
..F.F.F/Users/mdickinson/Enthought/ETS/traits/traits/has_traits.py:2067: DeprecationWarning: The edit argument to configure_traits is deprecated, and will be removed in Traits 7.0.0
  warnings.warn(message, DeprecationWarning)
F
======================================================================
FAIL: test_filename_but_no_file (traits.tests.test_configure_traits.TestConfigureTraits)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/mdickinson/Enthought/ETS/traits/traits/tests/test_configure_traits.py", line 54, in test_filename_but_no_file
    self.assertTrue(os.path.exists(filename))
AssertionError: False is not true

======================================================================
FAIL: test_filename_with_existing_file_stores_updated_model (traits.tests.test_configure_traits.TestConfigureTraits)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/mdickinson/Enthought/ETS/traits/traits/tests/test_configure_traits.py", line 122, in test_filename_with_existing_file_stores_updated_model
    self.assertEqual(model.count, 23)
AssertionError: 52 != 23

======================================================================
FAIL: test_pickle_protocol (traits.tests.test_configure_traits.TestConfigureTraits)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/mdickinson/Enthought/ETS/traits/traits/tests/test_configure_traits.py", line 73, in test_pickle_protocol
    self.assertTrue(os.path.exists(filename))
AssertionError: False is not true

======================================================================
FAIL: test_simple_call (traits.tests.test_configure_traits.TestConfigureTraits)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/mdickinson/Enthought/ETS/traits/traits/tests/test_configure_traits.py", line 43, in test_simple_call
    self.assertEqual(mock_view.call_count, 1)
AssertionError: 0 != 1

----------------------------------------------------------------------
Ran 8 tests in 0.015s

FAILED (failures=4)

What we want to see here is no test failures, and no unsuppressed warnings.

@mdickinson
Copy link
Member

@avats-dev I opened a PR against your branch (avats-dev#1). That PR doesn't change the main logic, it just adds one test and expands the other two a bit, so that we have good test code to work against when validating the logic in the main function. (By the way, if you're interested in this approach to development, I recommend reading up on Test Driven Development.)

Augment and strengthen tests for deprecation of edit parameter
@avats-dev
Copy link
Contributor Author

@mdickinson , Why tests are passing on python 3.9?

@mdickinson
Copy link
Member

mdickinson commented Sep 21, 2020

Why tests are passing on python 3.9?

Probably because these tests aren't running on Python 3.9: we don't set up the GUI system on Python 3.9, since there are issues with the PySide2 back end.

If you look at the detailed test run results on Python 3.9, you'll see that the tests in this PR are skipped:

test_edit_not_given (traits.tests.test_configure_traits.TestConfigureTraits) ... skipped 'TraitsUI not available'
test_edit_when_false (traits.tests.test_configure_traits.TestConfigureTraits) ... skipped 'TraitsUI not available'
test_edit_when_true (traits.tests.test_configure_traits.TestConfigureTraits) ... skipped 'TraitsUI not available'

@mdickinson
Copy link
Member

@avats-dev It would be great to get this finished up and merged. Is there anything I can help with?

@mdickinson
Copy link
Member

@avats-dev I made a new PR (#1311) that builds on your commits to fix this issue. Thank you for your contributions here!

@mdickinson mdickinson closed this Oct 13, 2020
@avats-dev
Copy link
Contributor Author

@mdickinson sorry I couldn't complete this. Will contribute more when I'm free. Thanks for the PR.

@avats-dev avats-dev deleted the feature/deprecate-edit branch October 19, 2020 13:41
@mdickinson
Copy link
Member

@avats-dev No problem; thank you for the contribution! Note that my PR built on yours, so your commits did go into the master branch - you're now officially a Traits contributor.

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.

Deprecate the edit argument to configure_traits
3 participants