Repository navigation
🐛 sphinx-needs: needs_functions shapes that crashed the build now warn - #2112
Merged
Merged
Conversation
A dict never registered anything (iterating it gives its keys, which the entry check already refused), so the changelog sentence on values that used to register names a set, a frozenset or a generator of functions, not any collection.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2112 +/- ##
==========================================
+ Coverage 92.48% 92.49% +0.01%
==========================================
Files 136 136
Lines 19416 19429 +13
==========================================
+ Hits 17957 17971 +14
+ Misses 1459 1458 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
What
Package:
packages/sphinx-needs.Follow-up to #2079, which made a non-callable
needs_functionsentry aneeds.configwarning.Three neighbouring shapes still ended the build during
config-inited, before a single document was read:conf.pyneeds_functions = NoneTypeError: 'NoneType' object is not iterable(frommerge_default_configs)needs_functions = my_functionTypeError: 'function' object is not iterableneeds_functions = [functools.partial(f, x=1)], or an instance with__call__AttributeError: 'functools.partial' object has no attribute '__name__'(fromadd_function)A string,
needs_functions = "my_function", did not crash but was read one character at a time: oneneeds_functions entry 'm' is not callable and is ignoredwarning per character.Each is now reported and the build continues:
A value that is not a list (or tuple) is ONE warning naming its type, and nothing is registered from it (the built-in functions still are):
Sphinx's own type check (
check_confval_types,config-initedpriority 800) would report the same value again(
The config value `needs_functions' has type `NoneType'; expected `list'., measured), so after warning the value isreplaced with the confval's default
[]; it is reported once, underneeds.configlike its neighbours.The declared
types=(list,)is unchanged.A set of functions, or another iterable of functions that is neither a list nor a tuple (a frozenset, a generator), used to register its functions beside
Sphinx's own type warning, and is now ignored with the same
needs.configwarning.A tuple is still registered, as before (Sphinx's own type warning for it is unchanged).
An entry that is callable but has no
__name__is skipped with one warning, and the rest of the list is still registered:A non-callable entry keeps 🐛 sphinx-needs: a TOML
functionskey warns instead of crashing #2079's warning, unchanged.The API path,
add_dynamic_function(app, func)withoutname=for a callable without a__name__, raised a bareAttributeError. It now raisesNeedsApiConfigException(asadd_warningdoes for a missing argument):Dynamic function functools.partial(...) has no __name__; pass the name to call it by with name=....The rule is one sentence in the
add_dynamic_functiondocstring, and in the Registration section ofdynamic_functions.rst.The changelog bullet is marked (changed output): every changed shape crashed or already warned, but a set-valued
needs_functions({my_function}), which Sphinx already reported as the wrong type, had its functions registered and their[[my_function()]]calls resolved; it is now ignored, so those calls reportUnknown function 'my_function'.Why
Issue #2073, the follow-up of #2064's second item:
needs_functionsvalues and entries that end the build with a tracebackinstead of a configuration warning, so a mistake in
conf.pyis reported like the others and the build continues.Closes #2073
Tests
All in
tests/test_needs_from_toml_functions.py, the suite #2079 wrote forneeds_functions; each build test is a real in-process buildasserting the whole
build_warnings(app)list and that the build completes. The tests for the crashing shapes were committed firstand were red against master; the tuple test guards what master already did.
test_a_needs_functions_value_that_is_not_a_list_warns_once_and_is_ignored[none]None: one warning, no Sphinx duplicate,needs_functions == [], only the built-ins registered…[bare-function]…[string]…[set]test_a_needs_functions_entry_without_a_name_warns_and_is_ignored[partial]functools.partialis skipped with one warning; the next entry is registered and resolves in a need…[instance]__call__: the sametest_a_needs_functions_tuple_is_still_registeredhas type `tuple'; expected `list'.test_add_dynamic_function_asks_for_a_name_for_a_callable_without_oneNeedsApiConfigExceptionasking forname=, registers nothing; withname=it registersMutation checks (each applied, the file run, reverted):
[none],[bare-function](crash),[string](per-character list),[set](registered beside Sphinx's warning)listonlyUnknown function 'answer')__name__guard[partial],[instance](crash)[partial],[instance](assert [] == [...])add_functionreadsfunction.__name__againAttributeError)uv run poe lintanduv run poe typecheckpass. The full suite passes apart from the graphviz-rendering tests, which needdotand failidentically without this change on a machine that lacks it.
Checklist
Built, adversarially reviewed and validated in an orchestrated Claude Code session from the issue, the code and the
tests of 🐛 sphinx-needs: a TOML
functionskey warns instead of crashing #2079; every line was read by its builder, its reviewer and the orchestrator, and the tests were committedfirst and shown red against master.
uv run poe test-needs) and they pass (the graphviz renders excepted on a machinewithout
dot, identically to master).docs/dynamic_functions.rst, the Registration section).docs/changelog.rsthas an entry under Unreleased.uv run poe lintanduv run poe typecheckpass.ubCode
Nothing to match in ubCode, because ubCode registers no Python callables:
needs_functionsis aconf.pyvalue it never reads(
docs/source/configuration/needs.rst:1684: "Functions a project registers throughneeds_functionsare not resolved"), and afunctionskey under[needs]inubproject.tomlis dropped silently, becauseNeedsConfigcarries#[serde(default)]withoutdeny_unknown_fields(rust/ubc_config/src/needs/input.rs:23-25); reporting unknown keys is the open useblocks/ubcode#2931.The shapes fixed here are Python-object shapes (a partial,
None, a bare function) that cannot be written in TOML.(Measured at ubCode
origin/main,8bece77.)Follow-ups
list(
The config value `needs_functions' has type `tuple'; expected `list'., unchanged from master).Declaring
types=(list, tuple)would be a separate, deliberate change to the confval.When squashing, strip the
Co-authored-bytrailer GitHub proposes.