Skip to content

Commit 0f36310

Browse files
331 support setupcfg and other ini files (#411)
* Add a setup.cfg file manager * Support setup.cfg and ini files for codespell * Maint/bump bitbucket schema (#410) (#412) * Fix commentary in schema.py for Bitbucket * Bump the bitbucket schema to match schema store
1 parent d6cd10b commit 0f36310

8 files changed

Lines changed: 266 additions & 61 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ exhaustive = true
198198
name = "File Integrations Modular Design"
199199
type = "layers"
200200
layers = [
201-
"pyproject_toml",
201+
"pyproject_toml | setup_cfg",
202202
"ini | toml | yaml",
203203
]
204204
containers = [ "usethis._integrations.file" ]

src/usethis/_config_file.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
from pathlib import Path
55
from typing import TYPE_CHECKING
66

7+
from usethis._integrations.file.ini.io_ import INIFileManager
78
from usethis._integrations.file.pyproject_toml.io_ import PyprojectTOMLManager
9+
from usethis._integrations.file.setup_cfg.io_ import SetupCFGManager
810
from usethis._integrations.file.toml.io_ import TOMLFileManager
911

1012
if TYPE_CHECKING:
@@ -15,8 +17,10 @@
1517
def files_manager() -> Iterator[None]:
1618
with (
1719
PyprojectTOMLManager(),
20+
SetupCFGManager(),
1821
DotRuffTOMLManager(),
1922
RuffTOMLManager(),
23+
CodespellRCManager(),
2024
):
2125
yield
2226

@@ -35,3 +39,11 @@ class RuffTOMLManager(TOMLFileManager):
3539
@property
3640
def relative_path(self) -> Path:
3741
return Path("ruff.toml")
42+
43+
44+
class CodespellRCManager(INIFileManager):
45+
"""Class to manage the .codespellrc file."""
46+
47+
@property
48+
def relative_path(self) -> Path:
49+
return Path(".codespellrc")

src/usethis/_integrations/file/setup_cfg/__init__.py

Whitespace-only changes.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from __future__ import annotations
2+
3+
from usethis._integrations.file.ini.errors import (
4+
INIError,
5+
ININotFoundError,
6+
INIValueAlreadySetError,
7+
INIValueMissingError,
8+
UnexpectedINIIOError,
9+
UnexpectedINIOpenError,
10+
)
11+
12+
13+
class SetupCFGError(INIError):
14+
"""Raised when aspects of 'setup.cfg' are missing, invalid, or unexpected."""
15+
16+
17+
class SetupCFGNotFoundError(SetupCFGError, ININotFoundError):
18+
"""Raised when a setup.cfg file is not found."""
19+
20+
21+
class SetupCFGDecodeError(SetupCFGError):
22+
"""Raised when a setup.cfg file cannot be decoded."""
23+
24+
25+
class UnexpectedSetupCFGOpenError(SetupCFGError, UnexpectedINIOpenError):
26+
"""Raised when the setup.cfg file is unexpectedly opened."""
27+
28+
29+
class UnexpectedSetupCFGIOError(SetupCFGError, UnexpectedINIIOError):
30+
"""Raised when an unexpected attempt is made to read or write the setup.cfg file."""
31+
32+
33+
class SetupCFGValueAlreadySetError(SetupCFGError, INIValueAlreadySetError):
34+
"""Raised when a value is unexpectedly already set in the 'setup.cfg' file."""
35+
36+
37+
class SetupCFGValueMissingError(SetupCFGError, INIValueMissingError):
38+
"""Raised when a value is unexpectedly missing from the 'setup.cfg' file."""
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
from typing import TYPE_CHECKING
5+
6+
from usethis._integrations.file.ini.errors import (
7+
INIDecodeError,
8+
ININotFoundError,
9+
INIValueAlreadySetError,
10+
INIValueMissingError,
11+
UnexpectedINIIOError,
12+
UnexpectedINIOpenError,
13+
)
14+
from usethis._integrations.file.ini.io_ import INIFileManager
15+
from usethis._integrations.file.setup_cfg.errors import (
16+
SetupCFGDecodeError,
17+
SetupCFGNotFoundError,
18+
SetupCFGValueAlreadySetError,
19+
SetupCFGValueMissingError,
20+
UnexpectedSetupCFGIOError,
21+
UnexpectedSetupCFGOpenError,
22+
)
23+
24+
if TYPE_CHECKING:
25+
from typing import Any
26+
27+
from typing_extensions import Self
28+
29+
30+
class SetupCFGManager(INIFileManager):
31+
"""Manages the setup.cfg file."""
32+
33+
@property
34+
def relative_path(self) -> Path:
35+
return Path("setup.cfg")
36+
37+
def __enter__(self) -> Self:
38+
try:
39+
return super().__enter__()
40+
except UnexpectedINIOpenError as err:
41+
raise UnexpectedSetupCFGOpenError(err) from None
42+
43+
def read_file(self) -> None:
44+
try:
45+
super().read_file()
46+
except ININotFoundError as err:
47+
raise SetupCFGNotFoundError(err) from None
48+
except UnexpectedINIIOError as err:
49+
raise UnexpectedSetupCFGIOError(err) from None
50+
except INIDecodeError as err:
51+
raise SetupCFGDecodeError(err) from None
52+
53+
def _validate_lock(self) -> None:
54+
try:
55+
super()._validate_lock()
56+
except UnexpectedINIIOError as err:
57+
raise UnexpectedSetupCFGIOError(err) from None
58+
59+
def set_value(
60+
self, *, keys: list[str], value: Any, exists_ok: bool = False
61+
) -> None:
62+
"""Set a value in the pyproject.toml configuration file."""
63+
try:
64+
super().set_value(keys=keys, value=value, exists_ok=exists_ok)
65+
except INIValueAlreadySetError as err:
66+
raise SetupCFGValueAlreadySetError(err) from None
67+
68+
def __delitem__(self, keys: list[str]) -> None:
69+
"""Remove a value from the pyproject.toml configuration file."""
70+
try:
71+
super().__delitem__(keys)
72+
except INIValueMissingError as err:
73+
raise SetupCFGValueMissingError(err) from None

0 commit comments

Comments
 (0)