Skip to content

Commit 4823341

Browse files
author
Trong Nhan Mai
committed
fix: preserve the order of elements of the list extract from defaults.ini
1 parent 8ba2e38 commit 4823341

File tree

4 files changed

+171
-79
lines changed

4 files changed

+171
-79
lines changed

src/macaron/config/defaults.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ class ConfigParser(configparser.ConfigParser):
1818
def get_list(
1919
self,
2020
section: str,
21-
item: str,
21+
option: str,
2222
delimiter: str | None = "\n",
2323
fallback: list[str] | None = None,
24-
duplicated_ok: bool = False,
2524
strip: bool = True,
2625
) -> list[str]:
27-
r"""Parse and return a list of strings from an item in ``defaults.ini``.
26+
r"""Parse and return a list of strings from an ``option`` for ``section`` in ``defaults.ini``.
2827
2928
This method uses str.split() to split the value into list of strings.
3029
References: https://docs.python.org/3/library/stdtypes.html#str.split.
@@ -37,22 +36,19 @@ def get_list(
3736
If ``strip`` is True (default: True), strings are whitespace-stripped and empty strings
3837
are removed from the final result.
3938
40-
If ``duplicated_ok`` is True (default: False), duplicated values are not removed from the final list.
41-
39+
The order of non-empty elements in the list is preserved.
4240
The content of each string in the list is not validated and should be handled separately.
4341
4442
Parameters
4543
----------
4644
section : str
4745
The section in ``defaults.ini``.
48-
item : str
49-
The item to parse the list.
46+
option : str
47+
The option whose value will be split into the return list of strings.
5048
delimiter : str | None
5149
The delimiter used to split the strings.
5250
fallback : list | None
5351
The fallback value in case of errors.
54-
duplicated_ok : bool
55-
If True allow duplicate values.
5652
strip: bool
5753
If True, strings are whitespace-stripped and any empty strings are removed.
5854
@@ -79,20 +75,15 @@ def get_list(
7975
allowed_hosts == ["github.com", "boo.com gitlab.com", "host com"]
8076
"""
8177
try:
82-
value = self.get(section, item)
78+
value = self.get(section, option)
8379
if isinstance(value, str):
8480
content = value.split(sep=delimiter)
8581

8682
if strip:
8783
content = [x.strip() for x in content if x.strip()]
8884

89-
if duplicated_ok:
90-
return content
91-
92-
distinct_values = set()
93-
distinct_values.update(content)
94-
return list(distinct_values)
95-
except configparser.NoOptionError as error:
85+
return content
86+
except (configparser.NoOptionError, configparser.NoSectionError) as error:
9687
logger.error(error)
9788

9889
return fallback or []

src/macaron/repo_finder/repo_finder_java.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ def _create_urls(self, group: str, artifact: str, version: str) -> list[str]:
119119
"repofinder.java",
120120
"artifact_repositories",
121121
fallback=["https://repo.maven.apache.org/maven2"],
122-
duplicated_ok=True,
123122
)
124123
urls = []
125124
for repo in repositories:
@@ -163,7 +162,7 @@ def _read_pom(self, pom: str) -> list[str]:
163162
The extracted contents as a list of strings.
164163
"""
165164
# Retrieve tags
166-
tags = defaults.get_list("repofinder.java", "repo_pom_paths", duplicated_ok=True)
165+
tags = defaults.get_list("repofinder.java", "repo_pom_paths")
167166
if not any(tags):
168167
logger.debug("No POM tags found for URL discovery.")
169168
return []

src/macaron/slsa_analyzer/registry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,8 +680,8 @@ def prepare(self) -> bool:
680680
logger.error("Found circular dependencies in registered checks: %s", str(error))
681681
return False
682682

683-
ex_pats = defaults.get_list(section="analysis.checks", item="exclude", fallback=[])
684-
in_pats = defaults.get_list(section="analysis.checks", item="include", fallback=["*"])
683+
ex_pats = defaults.get_list(section="analysis.checks", option="exclude", fallback=[])
684+
in_pats = defaults.get_list(section="analysis.checks", option="include", fallback=["*"])
685685
try:
686686
checks_to_run = self.get_final_checks(ex_pats, in_pats)
687687
except CheckRegistryError as error:

tests/config/test_defaults.py

Lines changed: 160 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
# Copyright (c) 2022 - 2023, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2022 - 2024, Oracle and/or its affiliates. All rights reserved.
22
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.
33

44
"""This module tests the defaults module."""
55

66
import os
7+
from pathlib import Path
78

89
import pytest
910

10-
from macaron.config.defaults import ConfigParser, create_defaults, defaults, load_defaults
11+
from macaron.config.defaults import create_defaults, defaults, load_defaults
1112
from macaron.config.global_config import global_config
1213

1314

@@ -41,93 +42,194 @@ def test_create_defaults_without_permission() -> None:
4142

4243

4344
@pytest.mark.parametrize(
44-
("section", "item", "delimiter", "strip", "duplicated_ok", "expect"),
45+
("user_config_input", "delimiter", "strip", "expect"),
4546
[
4647
(
47-
"test.list",
48-
"commas_string",
48+
"""
49+
[test.list]
50+
list = ,github.com, gitlab.com, space string, space string
51+
""",
4952
",",
5053
False,
54+
["", "github.com", " gitlab.com", " space string", " space string"],
55+
),
56+
(
57+
"""
58+
[test.list]
59+
list = ,github.com, gitlab.com, space string, space string
60+
""",
61+
",",
5162
True,
52-
["", " gitlab.com", " space string", " space string", "github.com"],
63+
["github.com", "gitlab.com", "space string", "space string"],
5364
),
54-
("test.list", "commas_string", ",", False, False, ["", " gitlab.com", " space string", "github.com"]),
55-
("test.list", "commas_string", ",", True, True, ["github.com", "gitlab.com", "space string", "space string"]),
56-
("test.list", "commas_string", ",", True, False, ["github.com", "gitlab.com", "space string"]),
57-
# Using None as the delimiter parameter will ignore cleanup
58-
("test.list", "default", None, True, False, ["comma_ended,", "github.com", "space", "string"]),
59-
("test.list", "default", None, False, False, ["comma_ended,", "github.com", "space", "string"]),
65+
# Using None as the `delimiter` will also remove leading and trailing spaces of elements. Therefore,
66+
# the results must be the same whether `strip` is set to True or False.
6067
(
61-
"test.list",
62-
"default",
68+
"""
69+
[test.list]
70+
list =
71+
github.com
72+
comma_ended,
73+
space string
74+
space string
75+
""",
6376
None,
64-
False,
6577
True,
66-
["comma_ended,", "github.com", "space", "space", "string", "string"],
78+
["github.com", "comma_ended,", "space", "string", "space", "string"],
6779
),
68-
("test.list", "one_line", None, True, False, ["comma_ended,", "github.com", "space", "string"]),
6980
(
70-
"test.list",
71-
"one_line",
81+
"""
82+
[test.list]
83+
list =
84+
github.com
85+
comma_ended,
86+
space string
87+
space string
88+
""",
89+
None,
90+
False,
91+
["github.com", "comma_ended,", "space", "string", "space", "string"],
92+
),
93+
(
94+
"""
95+
[test.list]
96+
list = github.com comma_ended, space string space string
97+
""",
7298
None,
7399
True,
74-
True,
75-
["comma_ended,", "github.com", "space", "space", "string", "string"],
100+
["github.com", "comma_ended,", "space", "string", "space", "string"],
76101
),
77102
],
78103
)
79104
def test_get_str_list_with_custom_delimiter(
80-
section: str, item: str, delimiter: str, strip: bool, duplicated_ok: bool, expect: list[str]
105+
user_config_input: str,
106+
delimiter: str,
107+
strip: bool,
108+
expect: list[str],
109+
tmp_path: Path,
81110
) -> None:
82111
"""Test getting a list of strings from defaults.ini using a custom delimiter."""
83-
content = """
84-
[test.list]
85-
default =
86-
github.com
87-
comma_ended,
88-
space string
89-
space string
90-
empty =
91-
one_line = github.com comma_ended, space string space string
92-
commas_string = ,github.com, gitlab.com, space string, space string
93-
"""
94-
custom_defaults = ConfigParser()
95-
custom_defaults.read_string(content)
112+
user_config_path = os.path.join(tmp_path, "config.ini")
113+
with open(user_config_path, "w", encoding="utf-8") as user_config_file:
114+
user_config_file.write(user_config_input)
115+
load_defaults(user_config_path)
96116

97-
results = custom_defaults.get_list(section, item, delimiter=delimiter, strip=strip, duplicated_ok=duplicated_ok)
98-
results.sort()
117+
results = defaults.get_list(section="test.list", option="list", delimiter=delimiter, strip=strip)
99118
assert results == expect
100119

101120

102121
@pytest.mark.parametrize(
103-
("section", "item", "strip", "duplicated_ok", "fallback", "expect"),
122+
("user_config_input", "expect"),
104123
[
105-
("test.list", "default", True, False, [], ["comma_ended,", "github.com", "space string"]),
106-
("test.list", "default", True, True, [], ["comma_ended,", "github.com", "space string", "space string"]),
107-
("test.list", "empty", False, True, [], [""]),
108-
("test.list", "empty", True, True, [], []),
109-
# Test for an item that does not exist in defaults.ini
110-
("test.list", "item_not_exist", True, True, [], []),
111-
# Test value for fallback. The fallback value must be returned as is and shouldn't be modified by the method.
112-
("test.list", "item_not_exist", True, True, ["", "fallback_val"], ["", "fallback_val"]),
124+
(
125+
"""
126+
[test.list]
127+
list = ,github.com, gitlab.com, space string, space string
128+
""",
129+
[",github.com, gitlab.com, space string, space string"],
130+
),
131+
(
132+
"""
133+
[test.list]
134+
list =
135+
github.com
136+
comma_ended,
137+
space string
138+
space string
139+
""",
140+
["github.com", "comma_ended,", "space string", "space string"],
141+
),
142+
(
143+
"""
144+
[test.list]
145+
list =
146+
""",
147+
[],
148+
),
113149
],
114150
)
115-
def test_get_str_list_with_default_delimiter(
116-
section: str, item: str, strip: bool, duplicated_ok: bool, fallback: list[str], expect: list[str]
151+
def test_get_str_list_default(
152+
user_config_input: str,
153+
expect: list[str],
154+
tmp_path: Path,
117155
) -> None:
118-
"""Test getting a list of strings from defaults.ini using the default delimiter."""
156+
"""Test default behavior of getting a list of strings from an option in defaults.ini."""
157+
user_config_path = os.path.join(tmp_path, "config.ini")
158+
with open(user_config_path, "w", encoding="utf-8") as user_config_file:
159+
user_config_file.write(user_config_input)
160+
load_defaults(user_config_path)
161+
162+
results = defaults.get_list(section="test.list", option="list")
163+
assert results == expect
164+
165+
166+
@pytest.mark.parametrize(
167+
("section", "option", "fallback", "expect"),
168+
[
169+
(
170+
"section",
171+
"non-existing",
172+
None,
173+
[],
174+
),
175+
(
176+
"non-existing",
177+
"option",
178+
None,
179+
[],
180+
),
181+
(
182+
"non-existing",
183+
"non-existing",
184+
None,
185+
[],
186+
),
187+
(
188+
"section",
189+
"non-existing",
190+
["some", "fallback", "value"],
191+
["some", "fallback", "value"],
192+
),
193+
(
194+
"non-existing",
195+
"option",
196+
["some", "fallback", "value"],
197+
["some", "fallback", "value"],
198+
),
199+
(
200+
"non-existing",
201+
"non-existing",
202+
["some", "fallback", "value"],
203+
["some", "fallback", "value"],
204+
),
205+
],
206+
)
207+
def test_get_str_list_default_with_errors(
208+
section: str,
209+
option: str,
210+
fallback: list[str] | None,
211+
expect: list[str],
212+
tmp_path: Path,
213+
) -> None:
214+
"""Test default behavior of getting a list of strings with errors from defaults.ini."""
119215
content = """
120-
[test.list]
121-
default =
216+
[section]
217+
option =
122218
github.com
123219
comma_ended,
124220
space string
125221
space string
126-
empty =
127222
"""
128-
custom_defaults = ConfigParser()
129-
custom_defaults.read_string(content)
130-
131-
results = custom_defaults.get_list(section, item, strip=strip, fallback=fallback, duplicated_ok=duplicated_ok)
132-
results.sort()
133-
assert results == expect
223+
user_config_path = os.path.join(tmp_path, "config.ini")
224+
with open(user_config_path, "w", encoding="utf-8") as user_config_file:
225+
user_config_file.write(content)
226+
load_defaults(user_config_path)
227+
228+
assert (
229+
defaults.get_list(
230+
section=section,
231+
option=option,
232+
fallback=fallback,
233+
)
234+
== expect
235+
)

0 commit comments

Comments
 (0)