Skip to content

Commit 02ea926

Browse files
authored
Merge branch 'main' into GCI104-python
2 parents 2528979 + e9c432b commit 02ea926

File tree

44 files changed

+3181
-20
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+3181
-20
lines changed

CHANGELOG.md

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

1010
### Added
1111

12-
- Add rule GCI 104 AvoidCreatingTensorUsingNumpyOrNativePython, a rule specific to AI/ML code
12+
- [#77](https://github.com/green-code-initiative/creedengo-python/pull/77) Add rule GCI 104 AvoidCreatingTensorUsingNumpyOrNativePython, a rule specific to AI/ML code
13+
- [#78](https://github.com/green-code-initiative/creedengo-python/pull/78) Add rule GCI105 on String Concatenation. This rule may also apply to other rules
14+
- [#74](https://github.com/green-code-initiative/creedengo-python/pull/74) Add rule GCI101 Avoid Conv Bias Before Batch Normalization, a rule specific to Deeplearning
15+
- [#75](https://github.com/green-code-initiative/creedengo-python/pull/75) Add rule GCI102 avoid non pinned memory for dataloader. This rule is specific to PyTorch and so AI
16+
- [#68](https://github.com/green-code-initiative/creedengo-python/pull/68) Data : Add rule GCI107 Avoid Iterative Matrix Operations. Use vectorization by the usage of the built-in functions of TensorFlow, NumPy or Pandas
17+
18+
### Changed
19+
20+
### Deleted
21+
22+
## [2.1.0] - 2025-08-02
23+
24+
### Added
25+
26+
- [#69](https://github.com/green-code-initiative/creedengo-python/pull/69) Data : Add rule GCI99 Avoid CSV Format
27+
- [#76](https://github.com/green-code-initiative/creedengo-python/pull/76) Add rule GCI103 Dictionary Items Unused. A rule specifying that dictionary iteration should consider the pertinence of the element used.
28+
- [#79](https://github.com/green-code-initiative/creedengo-python/pull/79) Add rule GCI106 Avoid SQRT in a loop
29+
- [#71](https://github.com/green-code-initiative/creedengo-python/pull/71) Data / AI : Add rule GCI96 Require Usecols Argument in Pandas Read Functions
30+
- [#72](https://github.com/green-code-initiative/creedengo-python/pull/72) Add rule GCI97 Optimize square computation (scalar vs vectorized method)
1331

1432
### Changed
1533

1634
- compatibility updates for SonarQube 25.5.0
1735
- upgrade libraries versions
1836
- correction of technical problem with Integration tests (because of Maven format in technical answer to "sonar-orchestrator-junit5" library)
19-
20-
### Deleted
37+
- update from jdk 11 to 17
38+
- Add Lombok annotation processing inside `maven-compiler` plugin, to fix compile error on Arm64 architecture
2139

2240
## [2.0.1] - 2025-03-14
2341

@@ -120,7 +138,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
120138

121139
## Comparison list
122140

123-
[unreleased](https://github.com/green-code-initiative/creedengo-python/compare/2.0.1...HEAD)
141+
[unreleased](https://github.com/green-code-initiative/creedengo-python/compare/2.1.0...HEAD)
142+
[2.1.0](https://github.com/green-code-initiative/creedengo-python/compare/2.0.1...2.1.0)
124143
[2.0.1](https://github.com/green-code-initiative/creedengo-python/compare/2.0.0...2.0.1)
125144
[2.0.0](https://github.com/green-code-initiative/creedengo-python/compare/1.4.4...2.0.0)
126145
[1.5.0](https://github.com/green-code-initiative/creedengo-python/compare/1.4.4...1.5.0)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Ready to use binaries are available [from GitHub](https://github.com/green-code-
6565
|----------------|---------------------|--------------|
6666
| 1.4.+ | 9.4.+ LTS to 10.4.1 | 11 / 17 |
6767
| 1.5.+ | 9.9.+ LTS to 10.7.0 | 11 / 17 |
68-
| 2.0.+ | 9.9.+ LTS to 25.5.0 | 11 / 17 |
68+
| 2.+ | 9.9.+ LTS to 25.5.0 | 17 |
6969

7070
> Compatibility table of versions lower than 1.4.+ are available from the
7171
> main [creedengo repository](https://github.com/green-code-initiative/creedengo-rules-specifications#-plugins-version-compatibility).

pom.xml

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>org.green-code-initiative</groupId>
66
<artifactId>creedengo-python-plugin</artifactId>
7-
<version>2.0.2-SNAPSHOT</version>
7+
<version>2.1.1-SNAPSHOT</version>
88
<packaging>sonar-plugin</packaging>
99

1010
<name>creedengo - Python language</name>
@@ -36,7 +36,7 @@
3636

3737
<properties>
3838

39-
<java.version>11</java.version>
39+
<java.version>17</java.version>
4040
<maven.compiler.source>${java.version}</maven.compiler.source>
4141
<maven.compiler.target>${java.version}</maven.compiler.target>
4242
<!-- to prevent message: system modules path not set in conjunction with -source 11 -->
@@ -50,12 +50,12 @@
5050
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
5151

5252
<!-- Minimal version of the SonarQube APIs for `creedengo-python-plugin` -->
53-
<sonarqube-plugin-api-min.version>9.9.0.65466</sonarqube-plugin-api-min.version>
53+
<sonarqube-plugin-api-min.version>9.9.0.65466</sonarqube-plugin-api-min.version>
5454

5555
<!-- Version of the SonarQube APIs used by `creedengo-java-plugin` -->
56-
<sonar.plugin.api.version>11.4.0.2922</sonar.plugin.api.version>
56+
<sonar.plugin.api.version>11.4.0.2922</sonar.plugin.api.version>
5757

58-
<sonar-analyzer-commons.version>2.17.0.3322</sonar-analyzer-commons.version>
58+
<sonar-analyzer-commons.version>2.17.0.3322</sonar-analyzer-commons.version>
5959

6060
<!-- last version that all is OK -->
6161
<sonarpython.version>4.6.0.12071</sonarpython.version>
@@ -66,18 +66,19 @@
6666
<!-- <sonarpython.version>4.22.0.16914</sonarpython.version>-->
6767
<!-- <sonarpython.version>5.4.0.22255</sonarpython.version>-->
6868

69-
<mockito.version>5.17.0</mockito.version>
69+
<mockito.version>5.17.0</mockito.version>
70+
<lombok.version>1.18.38</lombok.version>
7071

7172
<!-- temporary version waiting for a real automatic release in creedengo repository -->
72-
<creedengo-rules-specifications.version>2.2.2</creedengo-rules-specifications.version>
73+
<creedengo-rules-specifications.version>2.5.0</creedengo-rules-specifications.version>
7374

7475
<!-- URL of the Maven repository where sonarqube will be downloaded -->
7576
<test-it.orchestrator.artifactory.url>https://repo1.maven.org/maven2</test-it.orchestrator.artifactory.url>
7677
<!-- You can override this property to keep SonarQube instance running and to manually use it -->
7778
<test-it.sonarqube.keepRunning>false</test-it.sonarqube.keepRunning>
7879

7980
<!-- Version of `sonarqube` used by integration tests (you can override this value to perform matrix compatibility tests) -->
80-
<test-it.sonarqube.version>25.5.0.107428</test-it.sonarqube.version>
81+
<test-it.sonarqube.version>25.5.0.107428</test-it.sonarqube.version>
8182

8283
<!-- Version of `sonar-python-plugin` used by integration tests (you can override this value to perform matrix compatibility tests) -->
8384
<test-it.sonarpython.version>${sonarpython.version}</test-it.sonarpython.version>
@@ -176,7 +177,7 @@
176177
<dependency>
177178
<groupId>org.projectlombok</groupId>
178179
<artifactId>lombok</artifactId>
179-
<version>1.18.38</version>
180+
<version>${lombok.version}</version>
180181
<scope>test</scope>
181182
</dependency>
182183

@@ -189,6 +190,15 @@
189190
<groupId>org.apache.maven.plugins</groupId>
190191
<artifactId>maven-compiler-plugin</artifactId>
191192
<version>3.14.0</version>
193+
<configuration>
194+
<annotationProcessorPaths>
195+
<path>
196+
<groupId>org.projectlombok</groupId>
197+
<artifactId>lombok</artifactId>
198+
<version>${lombok.version}</version>
199+
</path>
200+
</annotationProcessorPaths>
201+
</configuration>
192202
</plugin>
193203
<plugin>
194204
<groupId>org.apache.maven.plugins</groupId>

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

Lines changed: 146 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717
*/
1818
package org.greencodeinitiative.creedengo.python.integration.tests;
1919

20-
import org.junit.jupiter.api.Test;
21-
import org.sonarqube.ws.Issues;
22-
import org.sonarqube.ws.Measures;
20+
import static java.util.Optional.ofNullable;
21+
import static org.assertj.core.api.Assertions.assertThat;
2322

2423
import java.util.List;
2524
import java.util.Map;
2625

27-
import static java.util.Optional.ofNullable;
28-
import static org.assertj.core.api.Assertions.assertThat;
26+
import org.junit.jupiter.api.Test;
27+
import org.sonarqube.ws.Issues;
28+
import org.sonarqube.ws.Measures;
2929

3030
class GCIRulesIT extends GCIRulesBase {
3131

@@ -273,4 +273,145 @@ void testGCI203_compliant() {
273273

274274
}
275275

276+
@Test
277+
void testGCI96() {
278+
String filePath = "src/pandasRequireUsecols.py";
279+
String ruleId = "creedengo-python:GCI96";
280+
String ruleMsg = "Specify 'usecols' or 'columns' when reading a DataFrame using Pandas to load only necessary columns";
281+
int[] startLines = new int[]{
282+
3, 4, 5, 6, 7, 16, 19
283+
};
284+
int[] endLines = new int[]{
285+
3, 4, 5, 6, 7, 16, 19
286+
};
287+
288+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
289+
}
290+
291+
@Test
292+
void testGCI97(){
293+
String filePath = "src/optimizeSquareComputation.py";
294+
String ruleId = "creedengo-python:GCI97";
295+
String ruleMsg = "Use x*x instead of x**2 or math.pow(x,2) to calculate the square of a value";
296+
int[] startLines = new int[]{
297+
4, 7, 19, 20, 25, 26, 31, 38
298+
};
299+
int[] endLines = new int[]{
300+
4, 7, 19, 20, 25, 26, 31, 38
301+
};
302+
303+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_1MIN);
304+
}
305+
306+
@Test
307+
void testGCI99(){
308+
String filePath = "src/avoidCSVFormat.py";
309+
String ruleId = "creedengo-python:GCI99";
310+
String ruleMsg = "Use Parquet or Feather format instead of CSV";
311+
int[] startLines = new int[]{
312+
// FIXME DDC : check why line 17 is not detected TI but detected in UT !!!
313+
// 4, 6, 10, 12, 14, 15, 17, 18, 23, 39, 47, 48
314+
4, 6, 10, 12, 14, 15, 18, 23, 39, 47, 48
315+
};
316+
int[] endLines = new int[]{
317+
// 4, 6, 10, 12, 14, 15, 17, 18, 23, 39, 47, 48
318+
4, 6, 10, 12, 14, 15, 18, 23, 39, 47, 48
319+
};
320+
321+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_50MIN);
322+
}
323+
324+
@Test
325+
void testGCI101(){
326+
String filePath = "src/avoidConvBiasBeforeBatchNorm.py";
327+
String ruleId = "creedengo-python:GCI101";
328+
String ruleMsg = "Remove bias for convolutions before batch norm layers to save time and memory.";
329+
int[] startLines = new int[]{
330+
49, 71, 115, 136, 156, 178
331+
};
332+
int[] endLines = new int[]{
333+
49, 71, 115, 136, 156, 178
334+
};
335+
336+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
337+
}
338+
339+
@Test
340+
void testGCI102(){
341+
String filePath = "src/avoidNonPinnedMemoryForDataloaders.py";
342+
String ruleId = "creedengo-python:GCI102";
343+
String ruleMsg = "Use pinned memory to reduce data transfer in RAM.";
344+
int[] startLines = new int[]{
345+
7, 8, 9, 10, 11, 12, 13, 14
346+
};
347+
int[] endLines = new int[]{
348+
7, 8, 9, 10, 11, 12, 13, 14
349+
};
350+
351+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
352+
}
353+
354+
@Test
355+
void testGCI103(){
356+
357+
String filePath = "src/dictionaryItemsUnused.py";
358+
String ruleId = "creedengo-python:GCI103";
359+
String ruleMsg = "Use dict.keys() or dict.values() instead of dict.items() when only one part of the key-value pair is used";
360+
int[] startLines = new int[]{
361+
5, 8, 24, 27, 36
362+
};
363+
int[] endLines = new int[]{
364+
5, 8, 24, 27, 36
365+
};
366+
367+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_1MIN);
368+
}
369+
370+
@Test
371+
void testGCI105() {
372+
373+
String filePath = "src/stringConcatenation.py";
374+
String ruleId = "creedengo-python:GCI105";
375+
String ruleMsg = "Concatenation of strings should be done using f-strings or str.join()";
376+
int[] startLines = new int[]{
377+
5, 8, 10, 32, 38
378+
};
379+
int[] endLines = new int[]{
380+
5, 8, 10, 32, 38
381+
};
382+
383+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_1MIN);
384+
}
385+
386+
@Test
387+
void testGCI106() {
388+
String filePath = "src/avoidSqrtInLoop.py";
389+
String ruleId = "creedengo-python:GCI106";
390+
String ruleMsg = "Avoid using scalar sqrt functions in loops. Apply vectorized sqrt operations on arrays directly.";
391+
int[] startLines = new int[]{
392+
7, 11, 16, 21, 45, 52, 60
393+
};
394+
int[] endLines = new int[]{
395+
7, 11, 16, 21, 45, 52, 60
396+
};
397+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_5MIN);
398+
399+
}
400+
401+
@Test
402+
void testGCI107(){
403+
404+
String filePath = "src/avoidIterativeMatrixOperations.py";
405+
String ruleId = "creedengo-python:GCI107";
406+
String ruleMsg = "Avoid iterative matrix operations, use numpy dot or outer function instead";
407+
int[] startLines = new int[]{
408+
8, 20, 36, 46, 75, 83, 91, 106, 115
409+
};
410+
int[] endLines = new int[]{
411+
8, 20, 36, 46, 75, 83, 91, 106, 115
412+
};
413+
414+
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines, SEVERITY, TYPE, EFFORT_10MIN);
415+
}
416+
276417
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import pandas as pd
2+
import pandas as pandas_alias
3+
4+
df = pd.read_csv('data.csv') # Noncompliant {{Use Parquet or Feather format instead of CSV}}
5+
6+
df.to_csv('output.csv') # Noncompliant {{Use Parquet or Feather format instead of CSV}}
7+
8+
df = pd.read_parquet('data.parquet')
9+
10+
path_to_file = 'MNIST.csv' # Noncompliant {{Use Parquet or Feather format instead of CSV}}
11+
12+
df2 = pandas_alias.read_csv('another_data.csv') # Noncompliant {{Use Parquet or Feather format instead of CSV}}
13+
14+
with open('data.csv') as f: # Noncompliant {{Use Parquet or Feather format instead of CSV}}
15+
df3 = pd.read_csv(f) # Noncompliant {{Use Parquet or Feather format instead of CSV}}
16+
17+
df4 = pd.read_csv(
18+
'complex_data.csv', # Noncompliant {{Use Parquet or Feather format instead of CSV}}
19+
sep=',',
20+
header=0
21+
)
22+
23+
df4.to_csv("output.csv") # Noncompliant {{Use Parquet or Feather format instead of CSV}}
24+
25+
df5 = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]})
26+
27+
other_path = 'data.json'
28+
29+
df6 = pd.read_json(other_path)
30+
31+
df7 = pd.read_feather('features.feather')
32+
33+
df8 = pd.read_parquet("file.parquet")
34+
35+
df9 = pandas_alias.read_feather("something.feather")
36+
37+
df10 = pandas_alias.read_parquet("nested/dir/file.parquet")
38+
39+
result = pd.read_csv("log.csv", encoding='utf-8') # Noncompliant {{Use Parquet or Feather format instead of CSV}}
40+
41+
df11 = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
42+
df11.to_parquet("output.parquet")
43+
44+
df12 = pd.DataFrame({'x': [5, 6]})
45+
df12.to_feather("output.feather")
46+
47+
filename = "report.csv" # Noncompliant {{Use Parquet or Feather format instead of CSV}}
48+
data = pd.read_csv(filename) # Noncompliant {{Use Parquet or Feather format instead of CSV}}
49+
50+
log_file = "logfile.log"
51+
df13 = pd.read_table(log_file, delimiter='|')

0 commit comments

Comments
 (0)