Add copy.replace for 3.13 (#12262)

This commit is contained in:
Max Muoto
2024-07-22 20:34:34 -05:00
committed by GitHub
parent 128d8eb904
commit 2909053047
2 changed files with 34 additions and 1 deletions

View File

@@ -0,0 +1,21 @@
from __future__ import annotations
import copy
import sys
from typing_extensions import Self, assert_type
class ReplaceableClass:
def __init__(self, val: int) -> None:
self.val = val
def __replace__(self, val: int) -> Self:
cpy = copy.copy(self)
cpy.val = val
return cpy
if sys.version_info >= (3, 13):
obj = ReplaceableClass(42)
cpy = copy.replace(obj, val=23)
assert_type(cpy, ReplaceableClass)

View File

@@ -1,8 +1,16 @@
from typing import Any, TypeVar
import sys
from typing import Any, Protocol, TypeVar
from typing_extensions import ParamSpec, Self
__all__ = ["Error", "copy", "deepcopy"]
_T = TypeVar("_T")
_SR = TypeVar("_SR", bound=_SupportsReplace[Any])
_P = ParamSpec("_P")
class _SupportsReplace(Protocol[_P]):
# In reality doesn't support args, but there's no other great way to express this.
def __replace__(self, *args: _P.args, **kwargs: _P.kwargs) -> Self: ...
# None in CPython but non-None in Jython
PyStringMap: Any
@@ -11,6 +19,10 @@ PyStringMap: Any
def deepcopy(x: _T, memo: dict[int, Any] | None = None, _nil: Any = []) -> _T: ...
def copy(x: _T) -> _T: ...
if sys.version_info >= (3, 13):
__all__ += ["replace"]
def replace(obj: _SR, /, **changes: Any) -> _SR: ...
class Error(Exception): ...
error = Error