Skip to content

Conversation

dbrattli
Copy link
Collaborator

@dbrattli dbrattli commented Aug 9, 2025

Why

Libraries like Pydantic expect constructor arguments to be named arguments. This PR fixes this issue.

[<Erase>]
type Field<'T> = 'T

module Field =
    [<Import("Field", "pydantic")>]
    [<Emit("$0(frozen=$1)")>]
    let Frozen (frozen: bool) : Field<'T> = nativeOnly

    [<Import("Field", "pydantic")>]
    [<Emit("$0(default=$1)")>]
    let Default(value: 'T) : Field<'T> = nativeOnly

[<Import("BaseModel", "pydantic")>]
type BaseModel () = class end

[<Py.ClassAttributes(style="attributes", init=false)>]
type PydanticUser(Name: string, Age: bigint, Email: string option, Enabled: bool) =
    inherit BaseModel()
    member val Name: string = Field.Frozen(true) with get, set
    member val Age: bigint = Age with get, set
    member val Email: string option = None with get, set
    member val Enabled: bool = Field.Default(false) with get, set

let user = PydanticUser(Name = "Test User", Age=23, Email=None, Enabled=true)

This will now translate to:

class PydanticUser(BaseModel):
    Age: int
    Email: str | None
    Enabled: bool = Field(default=False)
    Name: str = Field(frozen=True)

PydanticUser_reflection = _expr1

user: PydanticUser = PydanticUser(Name = "Test User", Age = 23, Email = None, Enabled = True)

@dbrattli dbrattli changed the title [Python] Imrpove Pydantic interop [Python] Improve Pydantic interop Aug 9, 2025
@dbrattli dbrattli merged commit 19d36fe into main Aug 10, 2025
20 checks passed
@dbrattli dbrattli deleted the python-pydantic-interop branch August 10, 2025 10:02
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.

1 participant