Skip to content

Commit e8ae9d9

Browse files
author
Daniel Sanz
committed
chore(elementsinteractive#153): Use FileHandler in ConfigHandler
1 parent 8a411a1 commit e8ae9d9

File tree

3 files changed

+35
-40
lines changed

3 files changed

+35
-40
lines changed

src/twyn/config/config_handler.py

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import logging
22
from dataclasses import asdict, dataclass
33
from enum import Enum
4-
from os import getcwd
5-
from pathlib import Path
64
from typing import Optional
75

86
from tomlkit import TOMLDocument, dumps, parse, table
@@ -18,6 +16,8 @@
1816
AllowlistPackageDoesNotExistError,
1917
TOMLError,
2018
)
19+
from twyn.file_handler.exceptions import PathNotFoundError
20+
from twyn.file_handler.file_handler import FileHandlerPathlib
2121

2222
logger = logging.getLogger("twyn")
2323

@@ -47,8 +47,9 @@ class ReadTwynConfiguration:
4747
class ConfigHandler:
4848
"""Manage reading and writing configurations for Twyn."""
4949

50-
def __init__(self, file_path: Optional[str] = None, enforce_file: bool = True):
51-
self._file_path = file_path or DEFAULT_PROJECT_TOML_FILE
50+
def __init__(self, file_path: Optional[str] = None, enforce_file: bool = True) -> None:
51+
file_path = file_path or DEFAULT_PROJECT_TOML_FILE
52+
self.file_handler = FileHandlerPathlib(file_path)
5253
self._enforce_file = enforce_file
5354

5455
def resolve_config(
@@ -119,36 +120,19 @@ def _write_config(self, toml: TOMLDocument, config: ReadTwynConfiguration) -> No
119120
if "twyn" not in toml["tool"]: # type: ignore[operator]
120121
toml["tool"]["twyn"] = {} # type: ignore[index]
121122
toml["tool"]["twyn"] = twyn_toml_data # type: ignore[index]
123+
122124
self._write_toml(toml)
123125

126+
def _write_toml(self, toml: TOMLDocument) -> None:
127+
self.file_handler.write(dumps(toml))
128+
124129
def _read_toml(self) -> TOMLDocument:
125130
try:
126-
fp = self._get_toml_file_pointer()
127-
except FileNotFoundError:
128-
if not self._enforce_file and self._file_path == DEFAULT_PROJECT_TOML_FILE:
131+
return parse(self.file_handler.read())
132+
except PathNotFoundError:
133+
if not self._enforce_file and self.file_handler.is_handler_of_file(DEFAULT_PROJECT_TOML_FILE):
129134
return TOMLDocument()
130-
raise TOMLError(f"Error reading toml from {self._file_path}") from None
131-
132-
with open(fp, "r") as f:
133-
content = parse(f.read())
134-
return content
135-
136-
def _get_toml_file_pointer(self) -> Path:
137-
"""Create a path for the toml file with the format <current working directory>/self.file_path."""
138-
fp = Path(getcwd()) / Path(self._file_path)
139-
140-
if not fp.is_file():
141-
raise FileNotFoundError(f"File not found at path '{fp}'.")
142-
143-
return fp
144-
145-
def _write_toml(self, toml: TOMLDocument) -> None:
146-
with open(self._get_toml_file_pointer(), "w") as f:
147-
try:
148-
f.write(dumps(toml))
149-
except Exception:
150-
logger.exception("Error writing toml file")
151-
raise TOMLError(f"Error writing toml to {self._file_path}") from None
135+
raise TOMLError(f"Error reading toml from {self.file_handler.file_path}") from None
152136

153137

154138
def _get_logging_level(

src/twyn/file_handler/file_handler.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,20 @@
1010

1111

1212
class BaseFileHandler(Protocol):
13-
def __init__(self, file_path: str) -> None: ...
1413
def read(self) -> str: ...
1514
def file_exists(self) -> bool: ...
15+
def write(self, data: str) -> None: ...
1616

1717

1818
class FileHandlerPathlib(BaseFileHandler):
1919
def __init__(self, file_path: str) -> None:
20-
self.file_path = Path(os.path.abspath(os.path.join(os.getcwd(), file_path)))
20+
self.file_path = self._get_file_path(file_path)
21+
22+
def _get_file_path(self, file_path: str) -> Path:
23+
return Path(os.path.abspath(os.path.join(os.getcwd(), file_path)))
24+
25+
def is_handler_of_file(self, name: str) -> bool:
26+
return self._get_file_path(name) == self.file_path
2127

2228
def read(self) -> str:
2329
self._raise_for_file_exists()
@@ -40,3 +46,7 @@ def _raise_for_file_exists(self) -> None:
4046

4147
if not self.file_path.is_file():
4248
raise PathIsNotFileError
49+
50+
def write(self, data: str) -> None:
51+
self._raise_for_file_exists()
52+
self.file_path.write_text(data)

tests/core/test_config_handler.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@
1111
AllowlistPackageDoesNotExistError,
1212
TOMLError,
1313
)
14+
from twyn.file_handler.exceptions import PathNotFoundError
1415

1516

1617
class TestConfig:
1718
def throw_exception(self):
18-
raise FileNotFoundError
19+
raise PathNotFoundError
1920

20-
@patch("twyn.config.config_handler.ConfigHandler._get_toml_file_pointer")
21+
@patch("twyn.file_handler.file_handler.FileHandlerPathlib.read")
2122
def test_enforce_file_error(self, mock_is_file):
2223
mock_is_file.side_effect = self.throw_exception
2324
with pytest.raises(TOMLError):
2425
ConfigHandler(enforce_file=True).resolve_config()
2526

26-
@patch("twyn.config.config_handler.ConfigHandler._get_toml_file_pointer")
27+
@patch("twyn.file_handler.file_handler.FileHandlerPathlib.read")
2728
def test_no_enforce_file_on_non_existent_file(self, mock_is_file):
2829
"""Resolving the config without enforcing the file to be present gives you defaults."""
2930
mock_is_file.side_effect = self.throw_exception
@@ -42,17 +43,17 @@ def test_config_raises_for_unknown_file(self):
4243
ConfigHandler(file_path="non-existent-file.toml").resolve_config()
4344

4445
def test_read_config_values(self, pyproject_toml_file):
45-
config = ConfigHandler(file_path=pyproject_toml_file).resolve_config()
46+
config = ConfigHandler(file_path=str(pyproject_toml_file)).resolve_config()
4647
assert config.dependency_file == "my_file.txt"
4748
assert config.selector_method == "my_selector"
4849
assert config.logging_level == AvailableLoggingLevels.debug
4950
assert config.allowlist == {"boto4", "boto2"}
5051

5152
def test_get_twyn_data_from_file(self, pyproject_toml_file):
52-
handler = ConfigHandler(file_path=pyproject_toml_file)
53+
handler = ConfigHandler(str(pyproject_toml_file))
5354

5455
toml = handler._read_toml()
55-
twyn_data = ConfigHandler(file_path=pyproject_toml_file)._get_read_config(toml)
56+
twyn_data = ConfigHandler(pyproject_toml_file)._get_read_config(toml)
5657
assert twyn_data == ReadTwynConfiguration(
5758
dependency_file="my_file.txt",
5859
selector_method="my_selector",
@@ -62,7 +63,7 @@ def test_get_twyn_data_from_file(self, pyproject_toml_file):
6263
)
6364

6465
def test_write_toml(self, pyproject_toml_file):
65-
handler = ConfigHandler(file_path=pyproject_toml_file)
66+
handler = ConfigHandler(pyproject_toml_file)
6667
toml = handler._read_toml()
6768

6869
initial_config = handler.resolve_config()
@@ -103,12 +104,12 @@ def test_write_toml(self, pyproject_toml_file):
103104

104105

105106
class TestAllowlistConfigHandler:
106-
@patch("twyn.config.config_handler.ConfigHandler._write_toml")
107+
@patch("twyn.file_handler.file_handler.FileHandlerPathlib.write")
107108
@patch("twyn.config.config_handler.ConfigHandler._read_toml")
108109
def test_allowlist_add(self, mock_toml, mock_write_toml):
109110
mock_toml.return_value = TOMLDocument()
110111

111-
config = ConfigHandler()
112+
config = ConfigHandler("some-file")
112113

113114
config.add_package_to_allowlist("mypackage")
114115

0 commit comments

Comments
 (0)