Fix container from_string collation for a single allow_none value (#908)#945
Open
apoorvdarshan wants to merge 1 commit into
Open
Conversation
Container.from_string substituted None for a value that failed literal_eval, then passed it to validate. Since PR ipython#885 added an allow_none short-circuit to Instance.validate, that None is now accepted for allow_none containers instead of raising, so a single --Class.trait=value (e.g. List(allow_none=True)) resolves to None instead of ['value']. Validate the original string on parse failure instead of None. A bare string is not a container, so validation raises as it did before ipython#885, letting DeferredConfig.get_value fall back to collating the value into a single-item list. Fixes ipython#908
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #908.
Root cause
Container.from_string(traitlets/traitlets.py) turns a value that failsliteral_evalintoNone, then passes it tovalidate:Before #885,
Instance.validate(None, None)always raised (Noneis not alist/set/tuple), soDeferredConfigString.get_value/DeferredConfigList.get_valuecaught the error and let the original string "lie", which is later collated into a single-item list.PR #885 added an
allow_noneshort-circuit toInstance.validate:For an
allow_none=Truecontainer this now accepts the substitutedNoneinstead of raising, sofrom_stringreturnsNoneand the collation fallback never happens. A single--Class.trait=valuetherefore resolves toNoneinstead of['value'].(The regression was bisected to #885 in the issue, and the mechanism was identified by @krassowski there.)
Reproduction
Observed on current
main(wrong):Expected / after this fix (and the behaviour on 5.12.0, before #885):
Fix
In
Container.from_string, whenliteral_evalfails, validate the original string instead of substitutingNone:A bare string is not a container, so
validateraises exactly as it did before #885 (independent ofallow_none), andDeferredConfig.get_valuefalls back to collating the value into a single-item list. This is localized to theexceptbranch and does not touch theallow_nonehandling inInstance.validate; the successful-parse path (including the"None"convention already covered byfrom_string_list) is unchanged.Tests
Added to
tests/test_traitlets.py:test_container_from_string_single_value_allow_none(parametrized overList,Set,Tuple): assertsfrom_string("a_value")on anallow_none=Truecontainer raisesTraitErrorrather than silently returningNone.test_list_allow_none_single_cli_value_is_collated: end-to-end check that a single deferred config value resolves to['a_value'].Both tests fail on unmodified
main(the end-to-end one fails withassert None == ['a_value']) and pass with the fix. The full existing suite passes (591 passed, 1 skipped), andruff check,ruff format --check, andmypyare clean on the changed files.Disclosure: prepared with AI assistance; reviewed and verified locally.