PyO3 / PyO3/pyo3

[feat]: allowing all fields to be set as default for `FromPyObject`

Open
#5,163 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
16.2k
Forks
1k
Avg merge
2d 6h
Merged PRs (30d)
66

Description

In https://github.com/PyO3/pyo3/pull/4829#issuecomment-2577336141, FromPyObject was intentionally designed to disallow all fields being set with #[pyo3(default)]. I wonder if this is because:

ref: https://github.com/PyO3/pyo3/pull/4829#issuecomment-2572971732

the surprising behavior that a variant Foo { #[pyo3(default)] value: usize } becomes a catch-all just like the Foo {} variant.

However, for me, this behavior makes sense, as I use it to extract class Foo(TypedDict, total=False) for typed kwargs.

// 💥 cannot derive FromPyObject for structs and variants with only default values
#[derive(FromPyObject)]
#[pyo3(from_item_all)]
pub struct Foo {
    #[pyo3(default)]
    id: Option<i32>,
}

#[pyfunction]
#[pyo3(signature = (**kwargs))]
fn foo(kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<()> {
    let foo: Option<Foo> = kwargs.map(|kwargs| kwargs.extract::<Foo>()).transpose()?;
    Ok(())
}
from typing_extensions import NotRequired, TypedDict, Unpack


class Foo(TypedDict, total=False):
    id: NotRequired[int]


def foo(**kwargs: Unpack[Foo]) -> None: ...

foo()  # ok
foo(id=1)  # ok
foo(id=1, foo=2)  # Err: no `foo` parameter

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The entry points named are FromPyObject, #[pyo3(default)], and #[pyo3(from_item_all)]; start by tracing how the derive handles structs or variants whose fields are all defaulted, using the linked PR discussion for the existing catch-all rationale. Done means the all-default Foo example derives and extracts optional id values while still rejecting unknown keys.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.