Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle invalid profiles, improve CLI output #141

Merged
merged 2 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ dmypy.json
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
pyvenv.cfg
.env
*.env
.venv
env/
venv/
Expand Down
7 changes: 6 additions & 1 deletion deepsearch/core/cli/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
)
from deepsearch.core.cli.utils import cli_handler
from deepsearch.core.client.settings import ProfileSettings
from deepsearch.core.client.settings_manager import settings_mgr
from deepsearch.core.client.settings_manager import SettingsManager

app = typer.Typer(no_args_is_help=True)

Expand All @@ -35,6 +35,7 @@ def add_profile(
),
activate_profile: bool = typer.Option(default=True),
):
settings_mgr = SettingsManager()
prfl_name = (
profile_name if profile_name else settings_mgr.get_profile_name_suggestion()
)
Expand Down Expand Up @@ -63,6 +64,7 @@ def list_profiles() -> None:
"active",
"profile",
)
settings_mgr = SettingsManager()
profiles = settings_mgr.get_all_profile_settings()
active_profile = settings_mgr.get_active_profile()

Expand Down Expand Up @@ -98,6 +100,7 @@ def show_profile(
"profile",
"config",
)
settings_mgr = SettingsManager()
prfl_name = profile_name or settings_mgr.get_active_profile()
profile = settings_mgr.get_profile_settings(profile_name=prfl_name)

Expand All @@ -117,6 +120,7 @@ def show_profile(
def set_default_profile(
profile_name: str,
) -> None:
settings_mgr = SettingsManager()
settings_mgr.activate_profile(profile_name=profile_name)


Expand All @@ -129,4 +133,5 @@ def set_default_profile(
def remove_profile(
profile_name: str,
) -> None:
settings_mgr = SettingsManager()
settings_mgr.remove_profile(profile_name=profile_name)
5 changes: 3 additions & 2 deletions deepsearch/core/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import typer

from deepsearch.core.client.settings_manager import settings_mgr
from deepsearch.core.client.settings import CLISettings


def cli_handler():
Expand All @@ -14,7 +14,8 @@ def wrap(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
if settings_mgr.get_show_cli_stack_traces():
settings = CLISettings()
if settings.show_cli_stack_traces:
raise e
else:
typer.secho(str(e), fg=typer.colors.RED)
Expand Down
7 changes: 6 additions & 1 deletion deepsearch/core/client/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,13 @@ def from_cli_prompt(cls) -> ProfileSettings:


class MainSettings(DumpableSettings):
profile: Optional[str] = None

profile: Optional[str] = None # None only when profiles not yet iniitialized
class Config:
env_prefix = "DEEPSEARCH_"


class CLISettings(DumpableSettings):
show_cli_stack_traces: bool = False

class Config:
Expand Down
33 changes: 20 additions & 13 deletions deepsearch/core/client/settings_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from dataclasses import dataclass
from enum import Enum
from pathlib import Path
from typing import Dict, Optional
from typing import Dict, List, Optional

import platformdirs
from pydantic import ValidationError
Expand All @@ -23,13 +23,13 @@

class KnownProfile(str, Enum):
SDS = "sds"
# DS_EXPERIENCE = "ds-experience" # TODO: uncomment once applicable
DS_EXPERIENCE = "ds-experience"
DS_INTERNAL = "ds-internal"


HOST_BY_PROFILE = {
KnownProfile.SDS.value: "https://sds.app.accelerate.science",
# KnownProfile.DS_EXPERIENCE.value: "https://deepsearch-experience.res.ibm.com", # TODO: uncomment once applicable
KnownProfile.DS_EXPERIENCE.value: "https://deepsearch-experience.res.ibm.com",
KnownProfile.DS_INTERNAL.value: "https://cps.foc-deepsearch.zurich.ibm.com",
}

Expand Down Expand Up @@ -61,15 +61,21 @@ def __init__(self) -> None:

# initialize internal profile cache from Pydantic Settings based on dotenv
self._profile_cache: Dict[str, ProfileSettingsEntry] = {}
paths_to_remove: List[Path] = []
for f in os.listdir(self._profile_root_path):
file_path = self._profile_root_path / f
if file_path.suffix == ".env":
profile_name = file_path.stem
self._profile_cache[profile_name] = ProfileSettingsEntry(
path=file_path,
settings=ProfileSettings(_env_file=file_path), # type: ignore
try:
profile_settings = ProfileSettings(_env_file=file_path) # type: ignore
# suppressing due to known Pydantic bug https://github.com/pydantic/pydantic/issues/3072
)

self._profile_cache[profile_name] = ProfileSettingsEntry(
path=file_path,
settings=profile_settings,
)
except ValidationError:
paths_to_remove.append(file_path)

# reset any stale active profile config
if (
Expand All @@ -93,6 +99,13 @@ def __init__(self) -> None:

self._migrate_legacy_config()

if paths_to_remove:
for path_to_rem in paths_to_remove:
path_to_rem.unlink()
profile_names = ", ".join([f'"{p.stem}"' for p in paths_to_remove])
err_msg = f"Following profiles were invalid and have been removed: {profile_names}; if needed please re-add"
raise RuntimeError(err_msg)

def _migrate_legacy_config(self) -> None:
if self._main_settings.profile is None:
legacy_cfg_path = self.config_root_path / LEGACY_CFG_FILENAME
Expand Down Expand Up @@ -197,9 +210,3 @@ def remove_profile(self, profile_name: str) -> None:

prfl_settgs_entry = self._profile_cache.pop(profile_name) # update cache
prfl_settgs_entry.path.unlink() # remove file

def get_show_cli_stack_traces(self) -> bool:
return self._main_settings.show_cli_stack_traces


settings_mgr = SettingsManager()
3 changes: 2 additions & 1 deletion deepsearch/cps/client/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
DeepSearchKeyAuth,
)
from deepsearch.core.client.settings import ProfileSettings
from deepsearch.core.client.settings_manager import settings_mgr
from deepsearch.core.client.settings_manager import SettingsManager
from deepsearch.cps.apis import public as sw_client
from deepsearch.cps.client.components import (
CpsApiDataCatalogs,
Expand Down Expand Up @@ -164,6 +164,7 @@ def from_env(cls, profile_name: Optional[str] = None) -> CpsApi:
try:
settings = ProfileSettings()
except ValidationError:
settings_mgr = SettingsManager()
settings = settings_mgr.get_profile_settings(profile_name=profile_name)
return cls.from_settings(settings=settings)

Expand Down