Skip to content

Commit ab72bd8

Browse files
committed
refactor: simplify config a bit more
1 parent 3e7b4e7 commit ab72bd8

File tree

8 files changed

+40
-59
lines changed

8 files changed

+40
-59
lines changed

src/twyn/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
SELECTOR_METHOD_MAPPING,
1010
AvailableLoggingLevels,
1111
)
12-
from twyn.core.config_handler import ConfigHandler
12+
from twyn.config.config_handler import ConfigHandler
1313
from twyn.main import check_dependencies
1414

1515

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from enum import Enum
44
from os import getcwd
55
from pathlib import Path
6-
from typing import Any, Optional
6+
from typing import Optional
77

88
from tomlkit import TOMLDocument, dumps, parse, table
99

@@ -13,7 +13,7 @@
1313
DEFAULT_TOP_PYPI_PACKAGES,
1414
AvailableLoggingLevels,
1515
)
16-
from twyn.core.exceptions import (
16+
from twyn.config.exceptions import (
1717
AllowlistPackageAlreadyExistsError,
1818
AllowlistPackageDoesNotExistError,
1919
TOMLError,
@@ -33,7 +33,7 @@ class TwynConfiguration:
3333
pypi_reference: str
3434

3535

36-
@dataclass(frozen=True)
36+
@dataclass
3737
class ReadTwynConfiguration:
3838
"""Configuration for twyn as set by the user. It may have None values."""
3939

@@ -65,16 +65,14 @@ def resolve_config(
6565
It will also handle default values, when appropriate.
6666
"""
6767
toml = self._read_toml()
68-
twyn_config_data = self._get_twyn_data_from_toml(toml)
68+
read_config = self._get_read_config(toml)
6969

70-
# Resolve the configuration so that it is ready to be used by Twyn,
71-
# handling defaults etc
7270
return TwynConfiguration(
73-
dependency_file=dependency_file or twyn_config_data.get("dependency_file"),
74-
selector_method=selector_method or twyn_config_data.get("selector_method", DEFAULT_SELECTOR_METHOD),
75-
logging_level=_get_logging_level(verbosity, twyn_config_data.get("logging_level")),
76-
allowlist=set(twyn_config_data.get("allowlist", set())),
77-
pypi_reference=twyn_config_data.get("pypi_reference", DEFAULT_TOP_PYPI_PACKAGES),
71+
dependency_file=dependency_file or read_config.dependency_file,
72+
selector_method=selector_method or read_config.selector_method or DEFAULT_SELECTOR_METHOD,
73+
logging_level=_get_logging_level(verbosity, read_config.logging_level),
74+
allowlist=read_config.allowlist,
75+
pypi_reference=read_config.pypi_reference or DEFAULT_TOP_PYPI_PACKAGES,
7876
)
7977

8078
def add_package_to_allowlist(self, package_name: str) -> None:
@@ -84,14 +82,8 @@ def add_package_to_allowlist(self, package_name: str) -> None:
8482
if package_name in config.allowlist:
8583
raise AllowlistPackageAlreadyExistsError(package_name)
8684

87-
new_config = ReadTwynConfiguration(
88-
dependency_file=config.dependency_file,
89-
selector_method=config.selector_method,
90-
logging_level=config.logging_level,
91-
allowlist=config.allowlist | {package_name},
92-
pypi_reference=config.pypi_reference,
93-
)
94-
self._write_config(toml, new_config)
85+
config.allowlist.add(package_name)
86+
self._write_config(toml, config)
9587
logger.info(f"Package '{package_name}' successfully added to allowlist")
9688

9789
def remove_package_from_allowlist(self, package_name: str) -> None:
@@ -101,19 +93,13 @@ def remove_package_from_allowlist(self, package_name: str) -> None:
10193
if package_name not in config.allowlist:
10294
raise AllowlistPackageDoesNotExistError(package_name)
10395

104-
new_config = ReadTwynConfiguration(
105-
dependency_file=config.dependency_file,
106-
selector_method=config.selector_method,
107-
logging_level=config.logging_level,
108-
allowlist=config.allowlist - {package_name},
109-
pypi_reference=config.pypi_reference,
110-
)
111-
self._write_config(toml, new_config)
96+
config.allowlist.remove(package_name)
97+
self._write_config(toml, config)
11298
logger.info(f"Package '{package_name}' successfully removed from allowlist")
11399

114100
def _get_read_config(self, toml: TOMLDocument) -> ReadTwynConfiguration:
115101
"""Read the twyn configuration from a provided toml document."""
116-
twyn_config_data = self._get_twyn_data_from_toml(toml)
102+
twyn_config_data = toml.get("tool", {}).get("twyn", {})
117103
return ReadTwynConfiguration(
118104
dependency_file=twyn_config_data.get("dependency_file"),
119105
selector_method=twyn_config_data.get("selector_method"),
@@ -145,10 +131,7 @@ def _read_toml(self) -> TOMLDocument:
145131

146132
with open(fp, "r") as f:
147133
content = parse(f.read())
148-
return parse(dumps(content))
149-
150-
def _get_twyn_data_from_toml(self, toml: TOMLDocument) -> dict[str, Any]:
151-
return toml.get("tool", {}).get("twyn", {})
134+
return content
152135

153136
def _get_toml_file_pointer(self) -> Path:
154137
"""Create a path for the toml file with the format <current working directory>/self.file_path."""

src/twyn/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
SELECTOR_METHOD_MAPPING,
1010
AvailableLoggingLevels,
1111
)
12-
from twyn.core.config_handler import ConfigHandler
12+
from twyn.config.config_handler import ConfigHandler
1313
from twyn.dependency_parser.dependency_selector import DependencySelector
1414
from twyn.similarity.algorithm import EditDistance, SimilarityThreshold
1515
from twyn.trusted_packages import TopPyPiReference

tests/core/test_config_handler.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
import pytest
66
from tomlkit import TOMLDocument, dumps, parse
77
from twyn.base.constants import DEFAULT_TOP_PYPI_PACKAGES, AvailableLoggingLevels
8-
from twyn.core.config_handler import ConfigHandler, ReadTwynConfiguration, TwynConfiguration
9-
from twyn.core.exceptions import (
8+
from twyn.config.config_handler import ConfigHandler, ReadTwynConfiguration, TwynConfiguration
9+
from twyn.config.exceptions import (
1010
AllowlistPackageAlreadyExistsError,
1111
AllowlistPackageDoesNotExistError,
1212
TOMLError,
@@ -17,13 +17,13 @@ class TestConfig:
1717
def throw_exception(self):
1818
raise FileNotFoundError
1919

20-
@patch("twyn.core.config_handler.ConfigHandler._get_toml_file_pointer")
20+
@patch("twyn.config.config_handler.ConfigHandler._get_toml_file_pointer")
2121
def test_enforce_file_error(self, mock_is_file):
2222
mock_is_file.side_effect = self.throw_exception
2323
with pytest.raises(TOMLError):
2424
ConfigHandler(enforce_file=True).resolve_config()
2525

26-
@patch("twyn.core.config_handler.ConfigHandler._get_toml_file_pointer")
26+
@patch("twyn.config.config_handler.ConfigHandler._get_toml_file_pointer")
2727
def test_no_enforce_file_on_non_existent_file(self, mock_is_file):
2828
"""Resolving the config without enforcing the file to be present gives you defaults."""
2929
mock_is_file.side_effect = self.throw_exception
@@ -103,8 +103,8 @@ def test_write_toml(self, pyproject_toml_file):
103103

104104

105105
class TestAllowlistConfigHandler:
106-
@patch("twyn.core.config_handler.ConfigHandler._write_toml")
107-
@patch("twyn.core.config_handler.ConfigHandler._read_toml")
106+
@patch("twyn.config.config_handler.ConfigHandler._write_toml")
107+
@patch("twyn.config.config_handler.ConfigHandler._read_toml")
108108
def test_allowlist_add(self, mock_toml, mock_write_toml):
109109
mock_toml.return_value = TOMLDocument()
110110

@@ -117,8 +117,8 @@ def test_allowlist_add(self, mock_toml, mock_write_toml):
117117
assert final_toml == {"tool": {"twyn": {"allowlist": ["mypackage"]}}}
118118
assert mock_write_toml.called
119119

120-
@patch("twyn.core.config_handler.ConfigHandler._write_toml")
121-
@patch("twyn.core.config_handler.ConfigHandler._read_toml")
120+
@patch("twyn.config.config_handler.ConfigHandler._write_toml")
121+
@patch("twyn.config.config_handler.ConfigHandler._read_toml")
122122
def test_allowlist_add_duplicate_error(self, mock_toml, mock_write_toml):
123123
mock_toml.return_value = parse(dumps({"tool": {"twyn": {"allowlist": ["mypackage"]}}}))
124124

@@ -131,8 +131,8 @@ def test_allowlist_add_duplicate_error(self, mock_toml, mock_write_toml):
131131

132132
assert not mock_write_toml.called
133133

134-
@patch("twyn.core.config_handler.ConfigHandler._write_toml")
135-
@patch("twyn.core.config_handler.ConfigHandler._read_toml")
134+
@patch("twyn.config.config_handler.ConfigHandler._write_toml")
135+
@patch("twyn.config.config_handler.ConfigHandler._read_toml")
136136
def test_allowlist_remove_completely(self, mock_toml, mock_write_toml):
137137
mock_toml.return_value = parse(dumps({"tool": {"twyn": {"allowlist": ["mypackage"]}}}))
138138

@@ -141,8 +141,8 @@ def test_allowlist_remove_completely(self, mock_toml, mock_write_toml):
141141
config.remove_package_from_allowlist("mypackage")
142142
assert config._read_toml() == {"tool": {"twyn": {}}}
143143

144-
@patch("twyn.core.config_handler.ConfigHandler._write_toml")
145-
@patch("twyn.core.config_handler.ConfigHandler._read_toml")
144+
@patch("twyn.config.config_handler.ConfigHandler._write_toml")
145+
@patch("twyn.config.config_handler.ConfigHandler._read_toml")
146146
def test_allowlist_remove(self, mock_toml, mock_write_toml):
147147
mock_toml.return_value = parse(dumps({"tool": {"twyn": {"allowlist": ["mypackage", "another-package"]}}}))
148148

@@ -151,8 +151,8 @@ def test_allowlist_remove(self, mock_toml, mock_write_toml):
151151
config.remove_package_from_allowlist("mypackage")
152152
assert config._read_toml() == {"tool": {"twyn": {"allowlist": ["another-package"]}}}
153153

154-
@patch("twyn.core.config_handler.ConfigHandler._write_toml")
155-
@patch("twyn.core.config_handler.ConfigHandler._read_toml")
154+
@patch("twyn.config.config_handler.ConfigHandler._write_toml")
155+
@patch("twyn.config.config_handler.ConfigHandler._read_toml")
156156
def test_allowlist_remove_non_existent_package_error(self, mock_toml, mock_write_toml):
157157
mock_toml.return_value = parse(dumps({"tool": {"twyn": {"allowlist": ["mypackage"]}}}))
158158

tests/main/test_cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88

99
class TestCli:
10-
@patch("twyn.core.config_handler.ConfigHandler.add_package_to_allowlist")
10+
@patch("twyn.config.config_handler.ConfigHandler.add_package_to_allowlist")
1111
def test_allowlist_add_package_to_allowlist(self, mock_allowlist_add):
1212
runner = CliRunner()
1313
runner.invoke(
@@ -17,7 +17,7 @@ def test_allowlist_add_package_to_allowlist(self, mock_allowlist_add):
1717

1818
assert mock_allowlist_add.call_args == call("requests")
1919

20-
@patch("twyn.core.config_handler.ConfigHandler.remove_package_from_allowlist")
20+
@patch("twyn.config.config_handler.ConfigHandler.remove_package_from_allowlist")
2121
def test_allowlist_remove(self, mock_allowlist_add):
2222
runner = CliRunner()
2323
runner.invoke(

tests/main/test_main.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from unittest.mock import patch
22

33
import pytest
4+
from tomlkit import dumps, parse
45
from twyn.base.constants import DEFAULT_TOP_PYPI_PACKAGES, AvailableLoggingLevels
5-
from twyn.core.config_handler import ConfigHandler, TwynConfiguration, _get_logging_level
6+
from twyn.config.config_handler import ConfigHandler, TwynConfiguration, _get_logging_level
67
from twyn.dependency_parser import RequirementsTxtParser
78
from twyn.main import (
89
check_dependencies,
@@ -27,7 +28,7 @@ class TestCheckDependencies:
2728
"logging_level": "WARNING",
2829
"selector_method": "nearby-letter",
2930
"dependency_file": "poetry.lock",
30-
"allowlist": {"boto4", "boto2"},
31+
"allowlist": ["boto4", "boto2"],
3132
},
3233
TwynConfiguration(
3334
dependency_file="requirements.txt",
@@ -45,7 +46,7 @@ class TestCheckDependencies:
4546
"logging_level": "debug",
4647
"selector_method": "nearby-letter",
4748
"dependency_file": "poetry.lock",
48-
"allowlist": {"boto4", "boto2"},
49+
"allowlist": ["boto4", "boto2"],
4950
},
5051
TwynConfiguration(
5152
dependency_file="poetry.lock",
@@ -75,13 +76,12 @@ class TestCheckDependencies:
7576
},
7677
{
7778
"logging_level": "INFO",
78-
"selector_method": None,
7979
"dependency_file": "poetry.lock",
80-
"allowlist": set(),
80+
"allowlist": [],
8181
},
8282
TwynConfiguration(
8383
dependency_file="requirements.txt",
84-
selector_method=None,
84+
selector_method="all",
8585
logging_level=AvailableLoggingLevels.debug,
8686
allowlist=set(),
8787
pypi_reference=DEFAULT_TOP_PYPI_PACKAGES,
@@ -106,7 +106,7 @@ def test_options_priorities_assignation(
106106
"""
107107
handler = ConfigHandler(file_path=None, enforce_file=False)
108108

109-
with patch.object(handler, "_get_twyn_data_from_toml", return_value=file_config):
109+
with patch.object(handler, "_read_toml", return_value=parse(dumps({"tool": {"twyn": file_config}}))):
110110
resolved = handler.resolve_config(
111111
selector_method=cli_config.get("selector_method"),
112112
dependency_file=cli_config.get("dependency_file"),
@@ -118,8 +118,6 @@ def test_options_priorities_assignation(
118118
assert resolved.logging_level == expected_resolved_config.logging_level
119119
assert resolved.allowlist == expected_resolved_config.allowlist
120120

121-
# assert mock_logging_level.call_args == call(log_level)
122-
123121
@pytest.mark.parametrize(
124122
"passed_logging_level, config, logging_level",
125123
[

0 commit comments

Comments
 (0)