write initial version of S7156
This commit is contained in:
parent
cbd6564edd
commit
1a20440092
@ -1,13 +1,12 @@
|
|||||||
{
|
{
|
||||||
"title": "FIXME",
|
"title": "\"copy.replace\" should not be invoked with an unsupported argument",
|
||||||
"type": "CODE_SMELL",
|
"type": "CODE_SMELL",
|
||||||
"status": "ready",
|
"status": "ready",
|
||||||
"remediation": {
|
"remediation": {
|
||||||
"func": "Constant\/Issue",
|
"func": "Constant/Issue",
|
||||||
"constantCost": "5min"
|
"constantCost": "5min"
|
||||||
},
|
},
|
||||||
"tags": [
|
"tags": [],
|
||||||
],
|
|
||||||
"defaultSeverity": "Major",
|
"defaultSeverity": "Major",
|
||||||
"ruleSpecification": "RSPEC-7156",
|
"ruleSpecification": "RSPEC-7156",
|
||||||
"sqKey": "S7156",
|
"sqKey": "S7156",
|
||||||
@ -17,8 +16,7 @@
|
|||||||
"code": {
|
"code": {
|
||||||
"impacts": {
|
"impacts": {
|
||||||
"MAINTAINABILITY": "HIGH",
|
"MAINTAINABILITY": "HIGH",
|
||||||
"RELIABILITY": "MEDIUM",
|
"RELIABILITY": "MEDIUM"
|
||||||
"SECURITY": "LOW"
|
|
||||||
},
|
},
|
||||||
"attribute": "CONVENTIONAL"
|
"attribute": "CONVENTIONAL"
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,32 @@
|
|||||||
FIXME: add a description
|
:object_replacement_protocol: https://docs.python.org/3/library/copy.html#object.__replace__
|
||||||
|
|
||||||
// If you want to factorize the description uncomment the following line and create the file.
|
|
||||||
//include::../description.adoc[]
|
|
||||||
|
|
||||||
== Why is this an issue?
|
== Why is this an issue?
|
||||||
|
|
||||||
FIXME: remove the unused optional headers (that are commented out)
|
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].
|
||||||
|
|
||||||
//=== What is the potential impact?
|
The following built-in types are 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/reference/datamodel.html#code-objects[code objects]
|
||||||
|
|
||||||
== How to fix it
|
== How to fix it
|
||||||
//== How to fix it in FRAMEWORK NAME
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
[source,python,diff-id=1,diff-type=compliant]
|
||||||
|
----
|
||||||
|
class SomeClass:
|
||||||
|
def __init__(self, name)
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __replace__(self, /, **changes)
|
||||||
|
return SomeClass(changes.get("name", self.name))
|
||||||
|
----
|
||||||
|
|
||||||
=== Code examples
|
=== Code examples
|
||||||
|
|
||||||
@ -18,27 +34,45 @@ FIXME: remove the unused optional headers (that are commented out)
|
|||||||
|
|
||||||
[source,python,diff-id=1,diff-type=noncompliant]
|
[source,python,diff-id=1,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
FIXME
|
import copy
|
||||||
|
|
||||||
|
class AClass:
|
||||||
|
...
|
||||||
|
|
||||||
|
a = AClass()
|
||||||
|
b = copy.replace(a) # Noncompliant
|
||||||
----
|
----
|
||||||
|
|
||||||
==== Compliant solution
|
==== Compliant solution
|
||||||
|
|
||||||
[source,python,diff-id=1,diff-type=compliant]
|
[source,python,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
FIXME
|
import copy
|
||||||
|
|
||||||
|
class AClass:
|
||||||
|
...
|
||||||
|
def __replace__(self, /, **changes):
|
||||||
|
...
|
||||||
|
|
||||||
|
a = AClass()
|
||||||
|
b = copy.replace(a) # Compliant
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ADataClass:
|
||||||
|
...
|
||||||
|
|
||||||
|
c = ADataClass()
|
||||||
|
d = copy.replace(c) # Compliant
|
||||||
----
|
----
|
||||||
|
|
||||||
//=== How does this work?
|
=== Pitfalls
|
||||||
|
|
||||||
//=== Pitfalls
|
Ensure that if the ``++__replace__++`` is implemented that the implementation creates a new object instead of updating the old one.
|
||||||
|
|
||||||
//=== Going the extra mile
|
|
||||||
|
|
||||||
|
|
||||||
//== Resources
|
== Resources
|
||||||
//=== Documentation
|
=== Documentation
|
||||||
//=== Articles & blog posts
|
* https://docs.python.org/3/library/copy.html#copy.replace
|
||||||
//=== Conference presentations
|
* https://docs.python.org/3/library/copy.html#object.\\__replace__
|
||||||
//=== Standards
|
* https://docs.python.org/3/whatsnew/3.13.html#copy
|
||||||
//=== External coding guidelines
|
|
||||||
//=== Benchmarks
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user