Files
ruff/crates/ty_python_semantic/resources/mdtest/call/replace.md
Aria Desires ad3de4e488 [ty] Improve rendering of default values for function args (#22010)
## Summary

We're actually quite good at computing this but the main issue is just
that we compute it at the type-level and so wrap it in `Literal[...]`.
So just special-case the rendering of these to omit `Literal[...]` and
fallback to `...` in cases where the thing we'll show is probably
useless (i.e. `x: str = str`).

Fixes https://github.com/astral-sh/ty/issues/1882
2025-12-16 13:39:19 -05:00

1.5 KiB

replace

The replace function and the replace protocol were added in Python 3.13: https://docs.python.org/3/whatsnew/3.13.html#copy

[environment]
python-version = "3.13"

Basic

from copy import replace
from datetime import time

t = time(12, 0, 0)
t = replace(t, minute=30)

# TODO: this should be `time`, once we support specialization of generic protocols
reveal_type(t)  # revealed: Unknown

The __replace__ protocol

Dataclasses

Dataclasses support the __replace__ protocol:

from dataclasses import dataclass
from copy import replace

@dataclass
class Point:
    x: int
    y: int

reveal_type(Point.__replace__)  # revealed: (self: Point, *, x: int = ..., y: int = ...) -> Point

The __replace__ method can either be called directly or through the replace function:

a = Point(1, 2)

b = a.__replace__(x=3, y=4)
reveal_type(b)  # revealed: Point

b = replace(a, x=3, y=4)
# TODO: this should be `Point`, once we support specialization of generic protocols
reveal_type(b)  # revealed: Unknown

A call to replace does not require all keyword arguments:

c = a.__replace__(y=4)
reveal_type(c)  # revealed: Point

d = replace(a, y=4)
# TODO: this should be `Point`, once we support specialization of generic protocols
reveal_type(d)  # revealed: Unknown

Invalid calls to __replace__ or replace will raise an error:

e = a.__replace__(x="wrong")  # error: [invalid-argument-type]

# TODO: this should ideally also be emit an error
e = replace(a, x="wrong")