Skip to content

Commit

Permalink
fix after review
Browse files Browse the repository at this point in the history
  • Loading branch information
Seppli11 committed Nov 13, 2024
1 parent 1a20440 commit 55577ac
Showing 1 changed file with 16 additions and 13 deletions.
29 changes: 16 additions & 13 deletions rules/S7156/python/rule.adoc
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
: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 provides 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]

== 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))
----

Expand All @@ -40,7 +43,7 @@ class AClass:
...
a = AClass()
b = copy.replace(a) # Noncompliant
b = copy.replace(a) # Noncompliant: AClass does not implement __replace__(...)
----

==== Compliant solution
Expand Down Expand Up @@ -73,6 +76,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]

0 comments on commit 55577ac

Please sign in to comment.