Support positional-only arguments in the strict sense#30
Open
maread99 wants to merge 3 commits into
Open
Conversation
Previously valimp ignored any '/' in a decorated function's signature, allowing intended positional-only arguments to be passed as keyword arguments. valimp now enforces positional-only arguments: a positional-only argument can only be passed positionally. Passing it by keyword raises an `InputsError`, unless the signature provides for **kwargs, in which case the keyword input is absorbed by **kwargs (consistent with standard Python behaviour). The verification is implemented within `validate_against_signature`, which covers the other signature checks. `inspect.signature` is interrogated to identify positional-only parameters (these are not distinguished by `inspect.getfullargspec`). The coerce/parse logic of the reconstruction loop has been factored into a new `apply_metadata` helper so that values absorbed by **kwargs under a positional-only name are validated, coerced and parsed consistently with other **kwargs inputs. Tests added to cover the new verification and the **kwargs absorption behaviour. The corresponding 'does not currently support' note has been removed from the module docstring and the README.
Doc and other non-functional revisions.
When a positional-only argument is received both positionally and as a keyword absorbed by **kwargs, and both values are invalid against their respective type annotations, both errors are now reported. Previously the absorbed value's error overrode the positional argument's error as both were keyed by the same parameter name in the consolidated errors mapping. The absorbed value's error is filed under a disambiguated key (e.g. "a (**kwargs)") only when the same name already carries an error from a positionally-received value, so ordinary cases are unaffected. Test added for the doubly-invalid collision case.
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.
Summary
Previously
valimpignored any/in a decorated function's signature, allowing arguments intended to be positional-only to be passed as keyword arguments.valimpnow enforces positional-only arguments in the strict sense: a positional-only argument can only be passed positionally. Passing it by keyword raises anInputsError, unless the signature provides for**kwargs, in which case the keyword input is absorbed by**kwargs— consistent with standard Python behaviour.Implementation
validate_against_signature, which covers the other signature checks. It receives the list of positional-only parameter names and the list of those invalidly received as keyword arguments.inspect.signatureis interrogated to identify positional-only parameters, sinceinspect.getfullargspecdoes not distinguish them (they are lumped intospec.args).wrapped_f, any keyword input matching a positional-only parameter name is removed fromkwargsup front: it never binds to the parameter. If the signature has no**kwargsit is reported via a dedicated"Got positional-only argument(s) passed as keyword argument(s): ..."error; otherwise it is absorbed into**kwargs(and a required positional-only parameter not also passed positionally is correctly reported as missing).apply_metadatahelper so that values absorbed by**kwargsunder a positional-only name are validated, coerced and parsed consistently with other**kwargsinputs.Behaviour examples
Documentation
The "does not currently support positional-only arguments" note has been removed from both the module docstring and the README.
Testing
**kwargsabsorption (with and without a default), the required-but-missing case, validation/coercion of absorbed values, and a decorated method.pytest: all 35 tests pass.ruff check/ruff format: clean.mypy: no new errors introduced (count is one lower than the pre-existing baseline).https://claude.ai/code/session_015Ci5jP93WGZiN2UE3SXyoh
Generated by Claude Code