Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ludwiktrammer committed Oct 9, 2024
1 parent 7042460 commit 0a21ce3
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/ragbits-core/src/ragbits/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ class CoreConfig(BaseModel):
prompt_path_pattern: str = "**/prompt_*.py"


core_config = get_config_instance(CoreConfig)
core_config = get_config_instance(CoreConfig, subproject="core")
23 changes: 17 additions & 6 deletions packages/ragbits-core/src/ragbits/core/utils/_pyproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
from pydantic import BaseModel


def find_pyproject() -> Path:
def find_pyproject(current_dir: Path = Path.cwd()) -> Path:
"""
Find the pyproject.toml file in the current directory or any of its parents.
Args:
current_dir (Path, optional): The directory to start searching from. Defaults to the
current working directory.
Returns:
Path: The path to the found pyproject.toml file.
Raises:
FileNotFoundError: If the pyproject.toml file is not found.
"""
current_dir = Path.cwd()
possible_dirs = [current_dir, *current_dir.parents]
for possible_dir in possible_dirs:
pyproject = possible_dir / "pyproject.toml"
Expand All @@ -24,18 +27,22 @@ def find_pyproject() -> Path:
raise FileNotFoundError("pyproject.toml not found")


def get_ragbits_config() -> dict[str, Any]:
def get_ragbits_config(current_dir: Path = Path.cwd()) -> dict[str, Any]:
"""
Get the ragbits configuration from the project's pyproject.toml file.
Only configuration from the [tool.ragbits] section is returned.
If the project doesn't include any ragbits configuration, an empty dictionary is returned.
Args:
current_dir (Path, optional): The directory to start searching for the pyproject.toml file. Defaults to the
current working directory.
Returns:
dict: The ragbits configuration.
"""
try:
pyproject = find_pyproject()
pyproject = find_pyproject(current_dir)
except FileNotFoundError:
# Projects are not required to use pyproject.toml
# No file just means no configuration
Expand All @@ -49,19 +56,23 @@ def get_ragbits_config() -> dict[str, Any]:
ConfigModelT = TypeVar("ConfigModelT", bound=BaseModel)


def get_config_instance(model: type[ConfigModelT], subproject: str | None = None) -> ConfigModelT:
def get_config_instance(
model: type[ConfigModelT], subproject: str | None = None, current_dir: Path = Path.cwd()
) -> ConfigModelT:
"""
Creates an instace of pydantic model loaded with the configuration from pyproject.toml.
Args:
model (Type[BaseModel]): The pydantic model to instantiate.
subproject (str, optional): The subproject to get the configuration for, defaults to giving entire
ragbits configuration.
current_dir (Path, optional): The directory to start searching for the pyproject.toml file. Defaults to the
current working directory
Returns:
ConfigModelT: The model instance loaded with the configuration
"""
config = get_ragbits_config()
config = get_ragbits_config(current_dir)
print(config)
if subproject:
config = config.get(subproject, {})
Expand Down
25 changes: 25 additions & 0 deletions packages/ragbits-core/tests/unit/utils/pyproject/test_find.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from pathlib import Path

import pytest

from ragbits.core.utils._pyproject import find_pyproject

projects_dir = Path(__file__).parent / "testprojects"


def test_find_in_current_dir():
"""Test finding a pyproject.toml file in the current directory."""
found = find_pyproject(projects_dir / "happy_project")
assert found == projects_dir / "happy_project" / "pyproject.toml"


def test_find_in_parent_dir():
"""Test finding a pyproject.toml file in a parent directory."""
found = find_pyproject(projects_dir / "happy_project" / "subdirectory")
assert found == projects_dir / "happy_project" / "pyproject.toml"


def test_find_not_found():
"""Test that it raises FileNotFoundError if the file is not found."""
with pytest.raises(FileNotFoundError):
find_pyproject(Path("/"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from pathlib import Path

from ragbits.core.utils._pyproject import get_ragbits_config

projects_dir = Path(__file__).parent / "testprojects"


def test_get_config():
"""Test getting config from pyproject.toml file."""
config = get_ragbits_config(projects_dir / "happy_project")

assert config == {
"lorem": "ipsum",
"happy-project": {
"foo": "bar",
"is_happy": True,
"happiness_level": 100,
},
}


def test_get_config_no_file():
"""Test getting config when the pyproject.toml file is not found."""
config = get_ragbits_config(Path("/"))

assert config == {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from pathlib import Path

from pydantic import BaseModel

from ragbits.core.utils._pyproject import get_config_instance

projects_dir = Path(__file__).parent / "testprojects"


class HappyProjectConfig(BaseModel):
foo: str
is_happy: bool
happiness_level: int


class PartialHappyProjectConfig(BaseModel):
foo: str
is_happy: bool


class OptionalHappyProjectConfig(BaseModel):
foo: str = "bar"
is_happy: bool = True
happiness_level: int = 100


def test_get_config_instance():
"""Test getting Pydantic model instance from pyproject.toml file."""
config = get_config_instance(
HappyProjectConfig,
subproject="happy-project",
current_dir=projects_dir / "happy_project",
)

assert config == HappyProjectConfig(foo="bar", is_happy=True, happiness_level=100)


def test_get_config_instance_additional_fields():
"""Test that unknown fields are ignored."""
config = get_config_instance(
PartialHappyProjectConfig,
subproject="happy-project",
current_dir=projects_dir / "happy_project",
)

assert config == PartialHappyProjectConfig(foo="bar", is_happy=True)


def test_get_config_instance_optional_fields():
"""Test that optional fields are filled with default values if not present in the file."""
config = get_config_instance(
OptionalHappyProjectConfig,
subproject="happy-project",
current_dir=projects_dir / "happy_project",
)

assert config == OptionalHappyProjectConfig(foo="bar", is_happy=True, happiness_level=100)


def test_get_config_instance_no_file():
"""Test getting config when the pyproject.toml file is not found (wich no required fields)."""
config = get_config_instance(
OptionalHappyProjectConfig,
subproject="happy-project",
current_dir=Path("/"),
)

assert config == OptionalHappyProjectConfig()
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[project]
name = "happy-project"

[tool.ragbits]
lorem = "ipsum"

[tool.ragbits.happy-project]
foo = "bar"
is_happy = true
happiness_level = 100

0 comments on commit 0a21ce3

Please sign in to comment.