-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(prompts): Load prompt pattern config from pyproject.toml (#77)
- Loading branch information
1 parent
a774147
commit d73e9d0
Showing
11 changed files
with
235 additions
and
7 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
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,15 @@ | ||
from pydantic import BaseModel | ||
|
||
from ragbits.core.utils._pyproject import get_config_instance | ||
|
||
|
||
class CoreConfig(BaseModel): | ||
""" | ||
Configuration for the ragbits-core package, loaded from downstream projects' pyproject.toml files. | ||
""" | ||
|
||
# Pattern used to search for prompt files | ||
prompt_path_pattern: str = "**/prompt_*.py" | ||
|
||
|
||
core_config = get_config_instance(CoreConfig, subproject="core") |
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
79 changes: 79 additions & 0 deletions
79
packages/ragbits-core/src/ragbits/core/utils/_pyproject.py
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,79 @@ | ||
from pathlib import Path | ||
from typing import Any, TypeVar | ||
|
||
import tomli | ||
from pydantic import BaseModel | ||
|
||
|
||
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. | ||
""" | ||
possible_dirs = [current_dir, *current_dir.parents] | ||
for possible_dir in possible_dirs: | ||
pyproject = possible_dir / "pyproject.toml" | ||
if pyproject.exists(): | ||
return pyproject | ||
raise FileNotFoundError("pyproject.toml not found") | ||
|
||
|
||
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(current_dir) | ||
except FileNotFoundError: | ||
# Projects are not required to use pyproject.toml | ||
# No file just means no configuration | ||
return {} | ||
|
||
with pyproject.open("rb") as f: | ||
pyproject_data = tomli.load(f) | ||
return pyproject_data.get("tool", {}).get("ragbits", {}) | ||
|
||
|
||
ConfigModelT = TypeVar("ConfigModelT", bound=BaseModel) | ||
|
||
|
||
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(current_dir) | ||
print(config) | ||
if subproject: | ||
config = config.get(subproject, {}) | ||
return model(**config) |
25 changes: 25 additions & 0 deletions
25
packages/ragbits-core/tests/unit/utils/pyproject/test_find.py
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,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("/")) |
26 changes: 26 additions & 0 deletions
26
packages/ragbits-core/tests/unit/utils/pyproject/test_get_config.py
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,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 == {} |
68 changes: 68 additions & 0 deletions
68
packages/ragbits-core/tests/unit/utils/pyproject/test_get_instace.py
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,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() |
10 changes: 10 additions & 0 deletions
10
packages/ragbits-core/tests/unit/utils/pyproject/testprojects/happy_project/pyproject.toml
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,10 @@ | ||
[project] | ||
name = "happy-project" | ||
|
||
[tool.ragbits] | ||
lorem = "ipsum" | ||
|
||
[tool.ragbits.happy-project] | ||
foo = "bar" | ||
is_happy = true | ||
happiness_level = 100 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.