Skip to content

fix: allow C-implemented built-ins (e.g. dict, int) as Optional defaults#349

Open
Labib-Bin-Salam wants to merge 1 commit into
keleshev:masterfrom
Labib-Bin-Salam:fix/optional-default-builtin-callables
Open

fix: allow C-implemented built-ins (e.g. dict, int) as Optional defaults#349
Labib-Bin-Salam wants to merge 1 commit into
keleshev:masterfrom
Labib-Bin-Salam:fix/optional-default-builtin-callables

Conversation

@Labib-Bin-Salam

Copy link
Copy Markdown

Closes #272.

Problem

_invoke_with_optional_kwargs (added in #268 to forward validate() keyword arguments to callable Optional defaults) calls inspect.signature(f) unconditionally. For many C-implemented built-ins — dict, int, and others — inspect.signature raises ValueError: no signature found for builtin type, so those callables can no longer be used as defaults:

>>> from schema import Schema, Optional
>>> Schema({Optional("k", default=dict): dict}).validate({})
ValueError: no signature found for builtin type <class 'dict'>

(Exactly which built-ins are affected varies by Python version — on 3.13 dict and int still raise, on older versions more do — but the breakage has been present since 0.7.5.)

Fix

Catch the introspection failure and fall back to calling the default with no arguments. That is the only sensible call for a callable whose signature cannot be inspected, and it restores the behaviour these defaults had before keyword-argument forwarding was introduced. Callables that do expose a signature are untouched, so kwarg forwarding still works:

>>> Schema({Optional("k", default=dict): dict}).validate({})
{'k': {}}

Notes

`_invoke_with_optional_kwargs` called `inspect.signature(f)` on the
default callable, but that raises `ValueError` for many C-implemented
built-ins (e.g. `dict`, `int`). This made them unusable as `Optional`
defaults, so

    Schema({Optional("k", default=dict): dict}).validate({})

raised instead of returning `{"k": {}}`.

Catch the introspection failure and fall back to calling the default
with no arguments -- the only sensible call for such callables, and the
behaviour they had before validate() keyword arguments were forwarded to
defaults. Callables that do expose a signature are unaffected, so
keyword-argument forwarding still works.

Closes keleshev#272.
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.

Optional default-parsing fails for C-based callables

1 participant