Skip to content

Commit d0b14b3

Browse files
Merge pull request #53 from codacy/pylint-config-parser
feature: parse apiv2 patterns jsonData into pylintrc type file - PLUTO-1358
2 parents 47cfc56 + c4a521f commit d0b14b3

File tree

7 files changed

+565
-0
lines changed

7 files changed

+565
-0
lines changed

cmd/init.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"codacy/cli-v2/config"
55
"codacy/cli-v2/domain"
66
"codacy/cli-v2/tools"
7+
"codacy/cli-v2/tools/pylint"
78
"codacy/cli-v2/utils"
89
"encoding/json"
910
"errors"
@@ -307,6 +308,19 @@ func createToolFileConfigurations(tool tools.Tool, patternConfiguration []domain
307308
}
308309
}
309310
fmt.Println("PMD configuration created based on Codacy settings")
311+
case PyLint:
312+
if len(patternConfiguration) > 0 {
313+
err := createPylintConfigFile(patternConfiguration, toolsConfigDir)
314+
if err != nil {
315+
return fmt.Errorf("failed to create Pylint config: %v", err)
316+
}
317+
} else {
318+
err := createDefaultPylintConfigFile(toolsConfigDir)
319+
if err != nil {
320+
return fmt.Errorf("failed to create default Pylint config: %v", err)
321+
}
322+
}
323+
fmt.Println("Pylint configuration created based on Codacy settings")
310324
}
311325
return nil
312326
}
@@ -319,6 +333,17 @@ func createPMDConfigFile(config []domain.PatternConfiguration, toolsConfigDir st
319333
func createDefaultPMDConfigFile(toolsConfigDir string) error {
320334
content := tools.CreatePmdConfig([]domain.PatternConfiguration{})
321335
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(content), utils.DefaultFilePerms)
336+
337+
}
338+
339+
func createPylintConfigFile(config []domain.PatternConfiguration, toolsConfigDir string) error {
340+
pylintConfigurationString := pylint.GeneratePylintRC(config)
341+
return os.WriteFile(filepath.Join(toolsConfigDir, "pylint.rc"), []byte(pylintConfigurationString), utils.DefaultFilePerms)
342+
}
343+
344+
func createDefaultPylintConfigFile(toolsConfigDir string) error {
345+
pylintConfigurationString := pylint.GeneratePylintRCDefault()
346+
return os.WriteFile(filepath.Join(toolsConfigDir, "pylint.rc"), []byte(pylintConfigurationString), utils.DefaultFilePerms)
322347
}
323348

324349
// createTrivyConfigFile creates a trivy.yaml configuration file based on the API configuration

tools/pylint/pylintConfigParser.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package pylint
2+
3+
import (
4+
"codacy/cli-v2/domain"
5+
"fmt"
6+
"log"
7+
"strings"
8+
)
9+
10+
// getDefaultParametersForPatterns returns a map of pattern IDs to their default parameters
11+
func getDefaultParametersForPatterns(patternIDs []string) map[string][]domain.ParameterConfiguration {
12+
defaultParams := make(map[string][]domain.ParameterConfiguration)
13+
14+
for _, patternID := range patternIDs {
15+
if params, exists := PatternDefaultParameters[patternID]; exists {
16+
defaultParams[patternID] = params
17+
}
18+
}
19+
20+
return defaultParams
21+
}
22+
23+
// writePylintRCHeader writes the common header sections to the RC content
24+
func writePylintRCHeader(rcContent *strings.Builder) {
25+
rcContent.WriteString("[MASTER]\n")
26+
rcContent.WriteString("ignore=CVS\n")
27+
rcContent.WriteString("persistent=yes\n")
28+
rcContent.WriteString("load-plugins=\n\n")
29+
rcContent.WriteString("[MESSAGES CONTROL]\n")
30+
rcContent.WriteString("disable=all\n")
31+
}
32+
33+
// writeEnabledPatterns writes the enabled patterns section to the RC content
34+
func writeEnabledPatterns(rcContent *strings.Builder, patternIDs []string) {
35+
if len(patternIDs) > 0 {
36+
rcContent.WriteString(fmt.Sprintf("enable=%s\n", strings.Join(patternIDs, ",")))
37+
}
38+
rcContent.WriteString("\n")
39+
}
40+
41+
// writeParametersBySection writes the parameters grouped by section to the RC content
42+
func writeParametersBySection(rcContent *strings.Builder, groupedParams map[string][]domain.ParameterConfiguration) {
43+
for sectionName, params := range groupedParams {
44+
rcContent.WriteString(fmt.Sprintf("[%s]\n", sectionName))
45+
for _, param := range params {
46+
rcContent.WriteString(fmt.Sprintf("%s=%s\n", param.Name, param.Value))
47+
}
48+
rcContent.WriteString("\n")
49+
}
50+
}
51+
52+
// groupParametersByPatterns groups parameters from patterns into sections
53+
func groupParametersByPatterns(patterns []domain.PatternConfiguration) map[string][]domain.ParameterConfiguration {
54+
groupedParams := make(map[string][]domain.ParameterConfiguration)
55+
56+
for _, pattern := range patterns {
57+
patternID := extractPatternId(pattern.PatternDefinition.Id)
58+
params := pattern.Parameters
59+
60+
// If no parameters, check defaults
61+
if len(params) == 0 {
62+
if defaultParams, exists := PatternDefaultParameters[patternID]; exists {
63+
params = defaultParams
64+
}
65+
}
66+
67+
// Add parameters to their respective sections
68+
for _, param := range params {
69+
sectionName := GetParameterSection(param.Name)
70+
if sectionName == nil {
71+
log.Printf("Parameter %s has no section name", param.Name)
72+
continue
73+
}
74+
75+
// Check if parameter already exists in section
76+
exists := false
77+
for _, existingParam := range groupedParams[*sectionName] {
78+
if existingParam.Name == param.Name {
79+
exists = true
80+
break
81+
}
82+
}
83+
84+
// Only add if not already present
85+
if !exists {
86+
groupedParams[*sectionName] = append(groupedParams[*sectionName], param)
87+
}
88+
}
89+
}
90+
91+
return groupedParams
92+
}
93+
94+
func GeneratePylintRCDefault() string {
95+
var rcContent strings.Builder
96+
97+
writePylintRCHeader(&rcContent)
98+
writeEnabledPatterns(&rcContent, DefaultPatterns)
99+
100+
// Get default parameters for enabled patterns
101+
defaultParams := getDefaultParametersForPatterns(DefaultPatterns)
102+
103+
// Convert default parameters to pattern configurations
104+
var patterns []domain.PatternConfiguration
105+
for patternID, params := range defaultParams {
106+
patterns = append(patterns, domain.PatternConfiguration{
107+
PatternDefinition: domain.PatternDefinition{
108+
Id: "PyLintPython3_" + patternID,
109+
},
110+
Parameters: params,
111+
})
112+
}
113+
114+
// Group and write parameters
115+
groupedParams := groupParametersByPatterns(patterns)
116+
writeParametersBySection(&rcContent, groupedParams)
117+
118+
return rcContent.String()
119+
}
120+
121+
// GeneratePylintRC generates a pylintrc file content with the specified patterns enabled
122+
func GeneratePylintRC(config []domain.PatternConfiguration) string {
123+
var rcContent strings.Builder
124+
125+
writePylintRCHeader(&rcContent)
126+
127+
// Collect enabled pattern IDs
128+
var enabledPatternsIds []string
129+
130+
for _, pattern := range config {
131+
patternID := extractPatternId(pattern.PatternDefinition.Id)
132+
enabledPatternsIds = append(enabledPatternsIds, patternID)
133+
}
134+
135+
writeEnabledPatterns(&rcContent, enabledPatternsIds)
136+
137+
// Group and write parameters
138+
groupedParams := groupParametersByPatterns(config)
139+
writeParametersBySection(&rcContent, groupedParams)
140+
141+
return rcContent.String()
142+
}
143+
144+
// extractPatternId returns the part of the pattern ID after the underscore
145+
// For example: "PyLintPython3_C0301" -> "C0301"
146+
func extractPatternId(fullID string) string {
147+
parts := strings.Split(fullID, "_")
148+
if len(parts) > 1 {
149+
return parts[1]
150+
}
151+
return fullID
152+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package pylint
2+
3+
// DefaultPatterns contains the list of default Pylint patterns
4+
var DefaultPatterns = []string{
5+
"C0123",
6+
"C0200",
7+
"C0303",
8+
"E0100",
9+
"E0101",
10+
"E0102",
11+
"E0103",
12+
"E0104",
13+
"E0105",
14+
"E0106",
15+
"E0107",
16+
"E0108",
17+
"E0110",
18+
"E0112",
19+
"E0113",
20+
"E0114",
21+
"E0115",
22+
"E0116",
23+
"E0117",
24+
"E0202",
25+
"E0203",
26+
"E0211",
27+
"E0236",
28+
"E0238",
29+
"E0239",
30+
"E0240",
31+
"E0241",
32+
"E0301",
33+
"E0302",
34+
"E0601",
35+
"E0603",
36+
"E0604",
37+
"E0701",
38+
"E0702",
39+
"E0703",
40+
"E0704",
41+
"E0710",
42+
"E0711",
43+
"E0712",
44+
"E1003",
45+
"E1102",
46+
"E1111",
47+
"E1120",
48+
"E1121",
49+
"E1123",
50+
"E1124",
51+
"E1125",
52+
"E1126",
53+
"E1127",
54+
"E1132",
55+
"E1200",
56+
"E1201",
57+
"E1205",
58+
"E1206",
59+
"E1300",
60+
"E1301",
61+
"E1302",
62+
"E1303",
63+
"E1304",
64+
"E1305",
65+
"E1306",
66+
"R0201",
67+
"R0202",
68+
"R0203",
69+
"W0101",
70+
"W0102",
71+
"W0104",
72+
"W0105",
73+
"W0106",
74+
"W0107",
75+
"W0108",
76+
"W0109",
77+
"W0120",
78+
"W0122",
79+
"W0124",
80+
"W0150",
81+
"W0199",
82+
"W0221",
83+
"W0222",
84+
"W0233",
85+
"W0404",
86+
"W0410",
87+
"W0601",
88+
"W0602",
89+
"W0604",
90+
"W0611",
91+
"W0612",
92+
"W0622",
93+
"W0623",
94+
"W0702",
95+
"W0705",
96+
"W0711",
97+
"W1300",
98+
"W1301",
99+
"W1302",
100+
"W1303",
101+
"W1305",
102+
"W1306",
103+
"W1307",
104+
}

tools/pylint/pylintDefaults.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package pylint
2+
3+
import "codacy/cli-v2/domain"
4+
5+
// PatternDefaultParameters contains the default parameters for Pylint patterns
6+
var PatternDefaultParameters = map[string][]domain.ParameterConfiguration{
7+
"R0914": {
8+
{
9+
Name: "max-locals",
10+
Value: "15",
11+
},
12+
},
13+
"C0301": {
14+
{
15+
Name: "max-line-length",
16+
Value: "120",
17+
},
18+
},
19+
"C0102": {
20+
{
21+
Name: "bad-names",
22+
Value: "foo,bar,baz,toto,tutu,tata",
23+
},
24+
},
25+
"C0103": {
26+
{
27+
Name: "argument-rgx",
28+
Value: "[a-z_][a-z0-9_]{2,30}$",
29+
},
30+
{
31+
Name: "attr-rgx",
32+
Value: "[a-z_][a-z0-9_]{2,30}$",
33+
},
34+
{
35+
Name: "class-rgx",
36+
Value: "[A-Z_][a-zA-Z0-9]+$",
37+
},
38+
{
39+
Name: "const-rgx",
40+
Value: "(([A-Z_][A-Z0-9_]*)|(__.*__))$",
41+
},
42+
{
43+
Name: "function-rgx",
44+
Value: "[a-z_][a-z0-9_]{2,30}$",
45+
},
46+
{
47+
Name: "method-rgx",
48+
Value: "[a-z_][a-z0-9_]{2,30}$",
49+
},
50+
{
51+
Name: "module-rgx",
52+
Value: "(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$",
53+
},
54+
{
55+
Name: "variable-rgx",
56+
Value: "[a-z_][a-z0-9_]{2,30}$",
57+
},
58+
{
59+
Name: "inlinevar-rgx",
60+
Value: "[A-Za-z_][A-Za-z0-9_]*$",
61+
},
62+
{
63+
Name: "class-attribute-rgx",
64+
Value: "([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$",
65+
},
66+
},
67+
}

0 commit comments

Comments
 (0)