From 67f9f22c4157e76442c256ab462ca380bb320b03 Mon Sep 17 00:00:00 2001 From: Sebastian Zumbrunn Date: Wed, 13 Nov 2024 13:51:36 +0100 Subject: [PATCH] fix after review --- rules/S7156/python/rule.adoc | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/rules/S7156/python/rule.adoc b/rules/S7156/python/rule.adoc index 58067db74b0..765f68971f1 100644 --- a/rules/S7156/python/rule.adoc +++ b/rules/S7156/python/rule.adoc @@ -1,30 +1,37 @@ :object_replacement_protocol: https://docs.python.org/3/library/copy.html#object.__replace__ +This rule raises an issue when ``++copy.replace++`` is used on an incorrect type. + == Why is this an issue? -Calling ``++copy.replace(...)++`` with an argument of an unsupported type will raise an ``++TypeError++``. -Types supported by ``++copy.replace(...)++`` must implement the {object_replacement_protocol}[replace protocol]. +Python 3.13 introduced the function ``++copy.replace(obj, /, **changes)++`` which creates a new duplicate of the same type as ``++obj++`` then updating the values of the fields provided in ``++changes++``. +However, calling ``++copy.replace(...)++`` with an argument of an unsupported type will raise an ``++TypeError++``. +In order for a type to be supported by ``++copy.replace(...)++``, the {object_replacement_protocol}[replace protocol] must be implemented. -The following built-in types are supported by ``++copy.replace(...)++`` +The following built-in types implement the {object_replacement_protocol}[replace protocol] and are thus supported by ``++copy.replace(...)++`` -* ``++collections.namedtuple()++`` -* ``++dataclasses.dataclass++`` * ``++datetime.datetime++``, ``++datetime.date++``, ``++datetime.time++`` * ``++inspect.Signature++``, ``++inspect.Parameter++`` * ``++types.SimpleNamespace++`` +* https://docs.python.org/3/library/typing.html#typing.NamedTuple[typed named tuples], ``++collections.namedtuple()++`` +* https://docs.python.org/3/library/dataclasses.html[data classes] * https://docs.python.org/3/reference/datamodel.html#code-objects[code objects] +=== Exceptions + +This issue is only raised for Python 3.13 and above, since the respective method isn't available in previous versions of Python. + == How to fix it -If the argument passed in is a class defined in this project then implementing the {object_replacement_protocol}[replace protocol] by defining the ``++__replace__++`` method. +If the argument passed to ``++copy.replace(...)++`` is a class defined in this project then, to fix the issue, implement the {object_replacement_protocol}[replace protocol] by defining the ``++__replace__++`` method in the class. -[source,python,diff-id=1,diff-type=compliant] +[source,python,diff-type=compliant] ---- class SomeClass: - def __init__(self, name) + def __init__(self, name): self.name = name - def __replace__(self, /, **changes) + def __replace__(self, /, **changes): return SomeClass(changes.get("name", self.name)) ---- @@ -40,7 +47,7 @@ class AClass: ... a = AClass() -b = copy.replace(a) # Noncompliant +b = copy.replace(a) # Noncompliant: AClass does not implement __replace__(...) ---- ==== Compliant solution @@ -73,6 +80,6 @@ Ensure that if the ``++__replace__++`` is implemented that the implementation cr == Resources === Documentation -* https://docs.python.org/3/library/copy.html#copy.replace -* https://docs.python.org/3/library/copy.html#object.\\__replace__ -* https://docs.python.org/3/whatsnew/3.13.html#copy +* Python Documentation - https://docs.python.org/3/library/copy.html#copy.replace[copy — Shallow and deep copy operations — copy.replace] +* Python Documentation - {object_replacement_protocol}[copy — Shallow and deep copy operations — object.\\__replace__] +* Python Documentation - https://docs.python.org/3/whatsnew/3.13.html#copy[What's New in Python 3.13]