Skip to content

Commit 191a852

Browse files
GCI96 PandasRequireUsecolsArgument fix : resolve conflicts
Co-authored-by: DataLabGroupe-CreditAgricole <[email protected]>
2 parents dbc69a5 + e346945 commit 191a852

File tree

8 files changed

+222
-1
lines changed

8 files changed

+222
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
<<<<<<< HEAD
1213
- [#71](https://github.com/green-code-initiative/creedengo-python/pull/71) Add rule GCI96 Require Usecols Argument in Pandas Read Functions
14+
=======
15+
- [#72](https://github.com/green-code-initiative/creedengo-python/pull/72) Add rule GCI97 Optimize square computation (scalar vs vectorized method)
16+
>>>>>>> upstream/main
1317
1418
### Changed
1519

src/it/java/org/greencodeinitiative/creedengo/python/integration/tests/GCIRulesIT.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,18 @@ void testGCI96() {
287287

288288
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
289289
}
290+
void testGCI97(){
291+
String filePath = "src/optimizeSquareComputation.py";
292+
String ruleId = "creedengo-python:GCI97";
293+
String ruleMsg = "Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value";
294+
int[] startLines = new int[]{
295+
4, 7, 19, 20, 25, 26, 31, 38
296+
};
297+
int[] endLines = new int[]{
298+
4, 7, 19, 20, 25, 26, 31, 38
299+
};
300+
301+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_1MIN);
302+
}
303+
290304
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import math
2+
3+
x = 5
4+
result1 = x**2 # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
5+
6+
z = 7
7+
result4 = math.pow(z, 2) # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
8+
9+
a = 3
10+
result5 = a*a
11+
12+
b = 4
13+
result6 = b*3
14+
result7 = 5*b
15+
result8 = math.pow(b, 3)
16+
result9 = b**3
17+
18+
c = 2.5
19+
result10 = c**2 # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
20+
result11 = math.pow(c, 2) # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
21+
22+
23+
d = 8
24+
e = 9
25+
result12 = math.pow(d+e, 2) # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
26+
result13 = (d+e)**2 # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
27+
result14 = (d+e)*(d+e)
28+
29+
30+
def square(x):
31+
return x**2 # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
32+
33+
def better_square(x):
34+
return x*x
35+
36+
37+
import math as m
38+
result15 = m.pow(d, 2) # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
39+
40+
result16 = math.sqrt(d)
41+
result17 = math.sin(d)
42+
result18 = math.pow(d, 1.5)

src/main/java/org/greencodeinitiative/creedengo/python/PythonRuleRepository.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public class PythonRuleRepository implements RulesDefinition, PythonCustomRuleRe
4141
AvoidListComprehensionInIterations.class,
4242
DetectUnoptimizedImageFormat.class,
4343
AvoidMultipleIfElseStatementCheck.class,
44-
PandasRequireUsecolsArgument.class
44+
PandasRequireUsecolsArgument.class,
45+
OptimizeSquareComputation.class
4546
);
4647

4748
public static final String LANGUAGE = "py";
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* creedengo - Python language - Provides rules to reduce the environmental footprint of your Python programs
3+
* Copyright © 2024 Green Code Initiative (https://green-code-initiative.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package org.greencodeinitiative.creedengo.python.checks;
19+
20+
import org.sonar.check.Rule;
21+
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
22+
import org.sonar.plugins.python.api.SubscriptionContext;
23+
import org.sonar.plugins.python.api.tree.BinaryExpression;
24+
import org.sonar.plugins.python.api.tree.CallExpression;
25+
import org.sonar.plugins.python.api.tree.Expression;
26+
import org.sonar.plugins.python.api.tree.NumericLiteral;
27+
import org.sonar.plugins.python.api.tree.QualifiedExpression;
28+
import org.sonar.plugins.python.api.tree.RegularArgument;
29+
30+
import static org.sonar.plugins.python.api.tree.Tree.Kind.*;
31+
32+
@Rule(key = "GCI97")
33+
public class OptimizeSquareComputation extends PythonSubscriptionCheck {
34+
35+
public static final String DESCRIPTION = "Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value";
36+
37+
@Override
38+
public void initialize(Context context) {
39+
context.registerSyntaxNodeConsumer(CALL_EXPR, this::checkMathPowCall);
40+
context.registerSyntaxNodeConsumer(POWER, this::checkPowerOf2);
41+
}
42+
43+
private boolean isNumericLiteralWithValue(Expression expr, String value) {
44+
if (expr.is(NUMERIC_LITERAL)) {
45+
NumericLiteral numericLiteral = (NumericLiteral) expr;
46+
return value.equals(numericLiteral.valueAsString());
47+
}
48+
return false;
49+
}
50+
51+
private void checkMathPowCall(SubscriptionContext context) {
52+
CallExpression callExpression = (CallExpression) context.syntaxNode();
53+
54+
if (isMathPowCall(callExpression)) {
55+
context.addIssue(callExpression, DESCRIPTION);
56+
}
57+
}
58+
59+
private boolean isMathPowCall(CallExpression callExpression) {
60+
Expression callee = callExpression.callee();
61+
62+
if (callee.is(QUALIFIED_EXPR)) {
63+
QualifiedExpression qualifiedExpr = (QualifiedExpression) callee;
64+
String name = qualifiedExpr.name().name();
65+
66+
if ("pow".equals(name)) {
67+
68+
if (callExpression.arguments().size() >= 2) {
69+
Expression secondArg = ((RegularArgument)callExpression.arguments().get(1)).expression();
70+
return isNumericLiteralWithValue(secondArg, "2");
71+
}
72+
}
73+
}
74+
75+
return false;
76+
}
77+
78+
private void checkPowerOf2(SubscriptionContext context) {
79+
BinaryExpression power = (BinaryExpression) context.syntaxNode();
80+
81+
if (isNumericLiteralWithValue(power.rightOperand(), "2")) {
82+
context.addIssue(power, DESCRIPTION);
83+
}
84+
}
85+
}

src/main/resources/org/greencodeinitiative/creedengo/python/creedengo_way_profile.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
"GCI72",
1111
"GCI74",
1212
"GCI89",
13+
<<<<<<< HEAD
1314
"GCI96",
15+
=======
16+
"GCI97",
17+
>>>>>>> upstream/main
1418
"GCI203",
1519
"GCI404"
1620
]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* creedengo - Python language - Provides rules to reduce the environmental footprint of your Python programs
3+
* Copyright © 2024 Green Code Initiative (https://green-code-initiative.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package org.greencodeinitiative.creedengo.python.checks;
19+
20+
import org.junit.Test;
21+
import org.sonar.python.checks.utils.PythonCheckVerifier;
22+
23+
public class OptimizeSquareComputationTest {
24+
25+
@Test
26+
public void test() {
27+
PythonCheckVerifier.verify("src/test/resources/checks/optimizeSquareComputation.py", new OptimizeSquareComputation());
28+
}
29+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import math
2+
3+
x = 5
4+
result1 = x**2 # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
5+
6+
z = 7
7+
result4 = math.pow(z, 2) # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
8+
9+
a = 3
10+
result5 = a*a
11+
12+
b = 4
13+
result6 = b*3
14+
result7 = 5*b
15+
result8 = math.pow(b, 3)
16+
result9 = b**3
17+
18+
c = 2.5
19+
result10 = c**2 # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
20+
result11 = math.pow(c, 2) # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
21+
22+
23+
d = 8
24+
e = 9
25+
result12 = math.pow(d+e, 2) # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
26+
result13 = (d+e)**2 # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
27+
result14 = (d+e)*(d+e)
28+
29+
30+
def square(x):
31+
return x**2 # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
32+
33+
def better_square(x):
34+
return x*x
35+
36+
37+
import math as m
38+
result15 = m.pow(d, 2) # Noncompliant {{Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value}}
39+
40+
result16 = math.sqrt(d)
41+
result17 = math.sin(d)
42+
result18 = math.pow(d, 1.5)

0 commit comments

Comments
 (0)