-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support user specific configuration files
- Loading branch information
Showing
8 changed files
with
175 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,31 @@ | ||
# {octicon}`tools;1.5em;sd-mr-1` Configuration | ||
|
||
The project configuration is defined as `.yaml` files. YANGA parses all `yanga.yaml` files in the project. Some directories are excluded while searching for the configuration files (e.g., `.venv`, `.git`, etc.) to avoid unnecessary parsing of files. | ||
The project configuration is defined as `.yaml` files. | ||
YANGA parses all `yanga.yaml` files in the project. | ||
Some directories are excluded while searching for the configuration files (e.g., `.venv`, `.git`, etc.) to avoid unnecessary parsing of files. | ||
|
||
One can override the default configuration by providing a custom configuration file. Either by providing a `yanga.ini` file or adding the configuration in the `pyproject.toml` file. | ||
|
||
Ini file example: | ||
|
||
```{code-block} ini | ||
:linenos: | ||
:name: yanga.ini | ||
[default] | ||
configuration_file_name = my_yanga.txt | ||
exclude_dirs = .git, build, .venv | ||
``` | ||
|
||
TOML file example: | ||
|
||
```{code-block} toml | ||
:linenos: | ||
:name: pyproject.toml | ||
[tool.yanga] | ||
configuration_file_name = "my_yanga.txt" | ||
exclude_dirs = [".git", "build", ".venv"] | ||
``` | ||
|
||
With the example above, YANGA will look for the `my_yanga.txt` file in the project root directory and exclude the `.git`, `build`, and `.venv` directories while searching for the configuration files. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import configparser | ||
from dataclasses import dataclass, field | ||
from pathlib import Path | ||
from typing import Any, Dict, List, Optional | ||
|
||
from mashumaro import DataClassDictMixin | ||
|
||
try: | ||
# For Python 3.11 and later | ||
import tomllib | ||
except ModuleNotFoundError: | ||
import tomli as tomllib | ||
|
||
|
||
@dataclass | ||
class YangaIni(DataClassDictMixin): | ||
#: Custom name for the YANGA configuration files. Default is 'yanga.yaml' | ||
configuration_file_name: Optional[str] = None | ||
#: Exclude directories from parsing | ||
exclude_dirs: List[str] = field(default_factory=list) | ||
|
||
@classmethod | ||
def from_toml_or_ini(cls, ini_file: Optional[Path], pyproject_toml: Optional[Path]) -> "YangaIni": | ||
# Initialize an empty dictionary to hold configurations | ||
config_data: Dict[str, Any] = {} | ||
|
||
# Load configurations from the INI file if provided | ||
if ini_file and ini_file.is_file(): | ||
ini_config = cls.load_ini_config(ini_file) | ||
config_data.update(ini_config) | ||
|
||
# Load configurations from the TOML file if provided | ||
if pyproject_toml and pyproject_toml.is_file(): | ||
toml_config = cls.load_toml_config(pyproject_toml) | ||
# TOML configurations take precedence over INI configurations | ||
config_data.update(toml_config) | ||
return cls.from_dict(config_data) | ||
|
||
@staticmethod | ||
def load_ini_config(ini_file: Path) -> Dict[str, Any]: | ||
"""Read the ini file and return the configuration as a dictionary.""" | ||
config: Dict[str, Any] = {} | ||
parser = configparser.ConfigParser() | ||
parser.read(ini_file) | ||
for section in parser.sections(): | ||
for key, value in parser.items(section): | ||
if key == "exclude_dirs": | ||
config[key] = [x.strip() for x in value.split(",")] | ||
else: | ||
config[key] = value | ||
return config | ||
|
||
@staticmethod | ||
def load_toml_config(pyproject_toml: Path) -> Dict[str, Any]: | ||
"""Read the pyproject.toml file and return the configuration as a dictionary.""" | ||
config = {} | ||
with pyproject_toml.open("rb") as f: | ||
data = tomllib.load(f) | ||
|
||
# Access the [tool.yanga] section | ||
yanga_config = data.get("tool", {}).get("yanga", {}) | ||
config.update(yanga_config) | ||
return config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# test_yanga_ini.py | ||
|
||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
from yanga.ini import YangaIni | ||
|
||
|
||
@pytest.fixture | ||
def ini_file(tmp_path: Path) -> Path: | ||
"""Create a temporary INI file for testing.""" | ||
ini_content = """ | ||
[default] | ||
configuration_file_name = yanga_from_ini.yaml | ||
exclude_dirs = .git, .github, .vscode, build, .venv | ||
""" | ||
ini_file_path = tmp_path / "yanga.ini" | ||
ini_file_path.write_text(ini_content) | ||
return ini_file_path | ||
|
||
|
||
@pytest.fixture | ||
def toml_file(tmp_path: Path) -> Path: | ||
"""Create a temporary pyproject.toml file for testing.""" | ||
toml_content = """ | ||
[tool.yanga] | ||
configuration_file_name = "yanga_from_toml.yaml" | ||
exclude_dirs = [".git", ".github", ".vscode", "build", ".venv"] | ||
""" | ||
toml_file_path = tmp_path / "pyproject.toml" | ||
toml_file_path.write_text(toml_content) | ||
return toml_file_path | ||
|
||
|
||
def test_load_ini_config(ini_file: Path) -> None: | ||
"""Test loading configuration from an INI file.""" | ||
config = YangaIni.load_ini_config(ini_file) | ||
expected_config = {"configuration_file_name": "yanga_from_ini.yaml", "exclude_dirs": [".git", ".github", ".vscode", "build", ".venv"]} | ||
assert config == expected_config | ||
|
||
|
||
def test_load_toml_config(toml_file: Path) -> None: | ||
"""Test loading configuration from a TOML file.""" | ||
config = YangaIni.load_toml_config(toml_file) | ||
expected_config = {"configuration_file_name": "yanga_from_toml.yaml", "exclude_dirs": [".git", ".github", ".vscode", "build", ".venv"]} | ||
assert config == expected_config | ||
|
||
|
||
def test_from_toml_or_ini_only_ini(ini_file: Path, toml_file: Path) -> None: | ||
"""Test instantiating YangaIni from only an INI file.""" | ||
config = YangaIni.from_toml_or_ini(ini_file=ini_file, pyproject_toml=toml_file) | ||
assert config.configuration_file_name == "yanga_from_toml.yaml" | ||
|
||
|
||
def test_from_toml_without_yanga_info(tmp_path: Path) -> None: | ||
toml_content = """ | ||
[tool.pytest] | ||
configuration_file_name = "yanga_from_toml.yaml" | ||
""" | ||
toml_file_path = tmp_path / "pyproject.toml" | ||
toml_file_path.write_text(toml_content) | ||
config = YangaIni.from_toml_or_ini(ini_file=None, pyproject_toml=toml_file_path) | ||
assert config.configuration_file_name is None |