mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 08:15:59 +00:00
Minor relaxations in config interfaces
This commit is contained in:
1 parent
6bc03191a7
commit
4cd4ac7926
1 file changed
+30
-18
+30
-18
@@ -11,7 +11,7 @@ import traceback
|
||||
from abc import ABC
|
||||
from collections import defaultdict
|
||||
from collections.abc import Callable, Generator, Iterable
|
||||
from dataclasses import field
|
||||
from dataclasses import dataclass, field
|
||||
from logging import Logger
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any, Self, TypeVar, Union, cast
|
||||
@@ -67,10 +67,6 @@ class SerenaConfigError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class ProjectConfig(ToStringMixin):
|
||||
project_name: str
|
||||
@@ -84,6 +80,10 @@ class ProjectConfig(ToStringMixin):
|
||||
SERENA_MANAGED_DIR = ".serena"
|
||||
SERENA_DEFAULT_PROJECT_FILE = "project.yml"
|
||||
|
||||
@classmethod
|
||||
def rel_path_to_project_yml(cls):
|
||||
return os.path.join(cls.SERENA_MANAGED_DIR, cls.SERENA_DEFAULT_PROJECT_FILE)
|
||||
|
||||
@classmethod
|
||||
def from_config_dict(cls, config_dict: dict[str, Any], project_name: str, project_root: Path | None = None) -> Self:
|
||||
"""
|
||||
@@ -128,12 +128,12 @@ class ProjectConfig(ToStringMixin):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_yml(cls, yml_path: Path) -> Self:
|
||||
def _from_yml(cls, yml_path: Path) -> Self:
|
||||
"""
|
||||
Create a ProjectConfig instance from a YAML file
|
||||
"""
|
||||
log.info(f"Loading project configuration from {yml_path}")
|
||||
if not os.path.exists(yml_path):
|
||||
if not yml_path.exists():
|
||||
raise FileNotFoundError(f"Project file not found: {yml_path}")
|
||||
try:
|
||||
with open(yml_path, encoding="utf-8") as f:
|
||||
@@ -148,16 +148,30 @@ class ProjectConfig(ToStringMixin):
|
||||
except Exception as e:
|
||||
raise ValueError(f"Error loading project configuration from {yml_path}: {e}") from e
|
||||
|
||||
@classmethod
|
||||
def from_path(cls, path: Path | str) -> Self:
|
||||
"""
|
||||
Create a ProjectConfig instance from a path. Can either be a path to a yaml file or a directory
|
||||
containing `.serena/project.yml`.
|
||||
"""
|
||||
path = Path(path)
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Path not found: {path}")
|
||||
if path.is_dir():
|
||||
path = path / cls.SERENA_MANAGED_DIR / cls.SERENA_DEFAULT_PROJECT_FILE
|
||||
return cls._from_yml(path)
|
||||
|
||||
def get_serena_managed_dir(self) -> str:
|
||||
return os.path.join(self.project_root, self.SERENA_MANAGED_DIR)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SerenaConfig:
|
||||
"""
|
||||
Handles user-defined Serena configuration based on the configuration file
|
||||
"""
|
||||
|
||||
projects: dict[str, "ProjectConfig"] = field(default_factory=dict)
|
||||
projects: dict[str, ProjectConfig] = field(default_factory=dict)
|
||||
project_names: list[str] = field(default_factory=list)
|
||||
gui_log_window_enabled: bool = False
|
||||
gui_log_window_level: int = logging.INFO
|
||||
@@ -197,7 +211,7 @@ class SerenaConfig:
|
||||
if not project_config_path.is_file():
|
||||
raise FileNotFoundError(f"Project file not found: {project_config_path}")
|
||||
log.info(f"Loading project configuration from {project_config_path}")
|
||||
project_config = ProjectConfig.from_yml(project_config_path)
|
||||
project_config = ProjectConfig.from_path(project_config_path)
|
||||
projects[project_config.project_name] = project_config
|
||||
|
||||
instance.projects = projects
|
||||
@@ -233,7 +247,7 @@ class LinesRead:
|
||||
class SerenaAgent:
|
||||
def __init__(
|
||||
self,
|
||||
project_config: ProjectConfig | str | None = None,
|
||||
project_config: ProjectConfig | str | Path | None = None,
|
||||
project_activation_callback: Callable[[], None] | None = None,
|
||||
serena_config: SerenaConfig | None = None,
|
||||
) -> None:
|
||||
@@ -246,7 +260,7 @@ class SerenaAgent:
|
||||
:param serena_config: the Serena configuration or None to read the configuration from the default location.
|
||||
"""
|
||||
# obtain serena configuration
|
||||
self.serena_config = serena_config | SerenaConfig.from_config_file()
|
||||
self.serena_config = serena_config or SerenaConfig.from_config_file()
|
||||
|
||||
# open GUI log window if enabled
|
||||
self._gui_log_handler: Union["GuiLogViewerHandler", None] = None # noqa
|
||||
@@ -298,19 +312,17 @@ class SerenaAgent:
|
||||
# activate a project configuration (if provided or if there is only a single project available)
|
||||
project_config_to_load: ProjectConfig | None = None
|
||||
if project_config is not None:
|
||||
if isinstance(project_config, str):
|
||||
project_config_to_load = ProjectConfig.from_yml(Path(project_config))
|
||||
elif isinstance(project_config, ProjectConfig):
|
||||
project_config_to_load = project_config
|
||||
if isinstance(project_config, (str, Path)):
|
||||
project_config_to_load = ProjectConfig.from_path(project_config)
|
||||
else:
|
||||
raise ValueError(f"Invalid project configuration: {project_config}, (type {type(project_config)})")
|
||||
project_config_to_load = project_config
|
||||
else:
|
||||
match len(self.serena_config.projects):
|
||||
case 0:
|
||||
raise RuntimeError(f"No projects found in {SerenaConfig.CONFIG_FILE} and no project file specified.")
|
||||
case 1:
|
||||
project_config = self.serena_config.get_project_configuration(self.serena_config.project_names[0])
|
||||
if project_config is not None:
|
||||
project_config_to_load = self.serena_config.get_project_configuration(self.serena_config.project_names[0])
|
||||
if project_config_to_load is not None:
|
||||
self.activate_project(project_config_to_load)
|
||||
else:
|
||||
if not self.serena_config.enable_project_activation:
|
||||
|
||||
Reference in new issue
Block a user