From 16be0cfffcf989bba67f0cf4842b48e842d39967 Mon Sep 17 00:00:00 2001 From: Geir Arne Hjelle Date: Sat, 28 Sep 2024 12:16:53 +0200 Subject: [PATCH] Final QA (#588) --- python-313/replace.py | 35 +++++++++++++++++++++++++++++++++++ python-313/typing/tree.py | 8 ++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/python-313/replace.py b/python-313/replace.py index 00b994bcc1..c392e1a766 100644 --- a/python-313/replace.py +++ b/python-313/replace.py @@ -21,3 +21,38 @@ class Person(NamedTuple): person = Person(name="Geir Arne", place="Oslo", version="3.12") print(copy.replace(person, version="3.13")) print(copy.replace(today, day=1)) + + +# %% Create a custom class that supports copy.replace() +class NamedContainer: + def __init__(self, name, **items): + print(f"Initializing {name} with {items}") + self.name = name + self.items = items + + def __replace__(self, **kwargs): + """.__replace__() is called by copy.replace()""" + if "name" in kwargs: + raise ValueError("'name' can't be updated") + + print(f"Replacing {kwargs} in {self.name}") + init_kwargs = {"name": self.name} | self.items | kwargs + + # Create a new object with updated arguments + cls = type(self) + return cls(**init_kwargs) + + def __repr__(self): + items = [f"{key}={value!r}" for key, value in self.items.items()] + return f"{type(self).__name__}(name='{self.name}', {", ".join(items)})" + + +capitals = NamedContainer( + "capitals", norway="oslo", sweden="Stockholm", denmark="Copenhagen" +) +print(f"{capitals = }") + +capitals = copy.replace(capitals, norway="Oslo") +print(f"{capitals = }") + +# copy.replace(capitals, name="Scandinavia") # Raises an error, name can't be replaced diff --git a/python-313/typing/tree.py b/python-313/typing/tree.py index f0fb417dd4..bc7471dbe5 100644 --- a/python-313/typing/tree.py +++ b/python-313/typing/tree.py @@ -4,7 +4,9 @@ def is_tree(obj: object) -> TypeGuard[Tree]: - return isinstance(obj, list) + return isinstance(obj, list) and all( + is_tree(elem) or isinstance(elem, int) for elem in obj + ) def get_left_leaf_value(tree_or_leaf: Tree | int) -> int: @@ -21,7 +23,9 @@ def get_left_leaf_value(tree_or_leaf: Tree | int) -> int: # type Tree = list[Tree | int] # # def is_tree(obj: object) -> TypeIs[Tree]: -# return isinstance(obj, list) +# return isinstance(obj, list) and all( +# is_tree(elem) or isinstance(elem, int) for elem in obj +# ) # # def get_left_leaf_value(tree_or_leaf: Tree | int) -> int: # if is_tree(tree_or_leaf):