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: Addresses an issue where badger was resetting some config settings #112

Merged
merged 3 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 8 additions & 2 deletions src/badger/actions/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,14 @@ def config_settings(args):

def _config_path_var(var_name):
config_singleton = init_settings()
display_name = config_singleton[var_name]['display name']
desc = config_singleton[var_name]['description']

is_path = config_singleton.read_is_path(var_name)

if not is_path:
raise KeyError

display_name = config_singleton.read_display_name(var_name)
desc = config_singleton.read_description(var_name)

print(f'=== Configure {display_name} ===')
print(f'*** {desc} ***\n')
Expand Down
8 changes: 2 additions & 6 deletions src/badger/actions/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@


def self_check(args):

config = init_settings()
# Reset Badger
if args.reset:
Expand Down Expand Up @@ -37,17 +36,14 @@ def check_n_config_paths():
issue_list = []

for pname in config._config.dict(by_alias=True):
if not config.read_value(pname):
if config.read_value(pname) == None:
good = False
# dname = BADGER_PATH_DICT[pname]['display name']
# print(f'\n{dname} needs to be configured!')

issue_list.append(pname)

if not good:
# Initial setup
init = True
while False:
while True:
_res = input(
'If this is your first time launching Badger, you should initialize it now.\n'
'Proceed ([y]/n)? ')
Expand Down
97 changes: 93 additions & 4 deletions src/badger/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Setting(BaseModel):
display_name: str
description: str
value: Optional[Union[str, int, bool, None]] = Field(None, description="The value of the setting which can be of different types.")
is_path: bool

class BadgerConfig(BaseModel):
"""
Expand All @@ -50,41 +51,49 @@ class BadgerConfig(BaseModel):
display_name="plugin root",
description="This setting (BADGER_PLUGIN_ROOT) tells Badger where to look for the plugins",
value=None,
is_path=True
)
BADGER_DB_ROOT: Setting = Setting(
display_name="database root",
description="This setting (BADGER_DB_ROOT) tells Badger where to store the routine database",
value=None,
is_path=True
)
BADGER_LOGBOOK_ROOT: Setting = Setting(
display_name="logbook root",
description="This setting (BADGER_LOGBOOK_ROOT) tells Badger where to send the logs (GUI mode)",
value=None,
is_path=True
)
BADGER_ARCHIVE_ROOT: Setting = Setting(
display_name="archive root",
description="This setting (BADGER_ARCHIVE_ROOT) tells Badger where to archive the historical optimization runs",
value=None,
is_path=True
)
BADGER_DATA_DUMP_PERIOD: Setting = Setting(
display_name="data dump period",
description="Minimum time interval between data dumps, unit is second",
value=1,
is_path=False
)
BADGER_THEME: Setting = Setting(
display_name="theme",
description="Theme for the Badger GUI",
value="dark",
is_path=False
)
BADGER_ENABLE_ADVANCED: Setting = Setting(
display_name="enable advanced features",
description="Enable advanced features on the GUI",
value=False,
is_path=False
)
AUTO_REFRESH: Setting = Setting(
display_name="Auto-refresh",
description="Permits each run to start from the initial points calculated based on the current values and the rules",
value=False
value=False,
is_path=False
)

class ConfigSingleton:
Expand Down Expand Up @@ -120,19 +129,21 @@ def load_or_create_config(config_path: str) -> BadgerConfig:

# Convert each entry in config_data to an instance of Setting
for key, value in config_data.items():
if isinstance(value, dict) and 'value' in value:
if isinstance(value, dict) and 'value' in value:
# Convert to Setting instance
config_data[key] = Setting(
display_name=value.get('display_name', key),
description=value.get('description', f"Setting for {key.replace('_', ' ').lower()}"),
value=value['value']
value=value['value'],
is_path=value.get('is_path', key)
)
else:
# If it's a direct value, wrap it in a Setting
config_data[key] = Setting(
display_name=key,
description=f"Setting for {key.replace('_', ' ').lower()}",
value=value
value=value,
is_path=False
)

try:
Expand Down Expand Up @@ -216,6 +227,84 @@ def read_value(self, key: str, return_value_field: bool = True) -> Any:
return data[key]['value'] if return_value_field else data[key]
raise KeyError(f"Key '{key}' not found in the configuration.")

def read_description(self, key: str, return_description_field: bool = True) -> Any:
"""
Searches for the key in all sections of the configuration.

Parameters
----------
key: str
The key to search for.
return_description_field: bool
If True, returns the 'description' field of the setting; otherwise, returns the entire setting.

Returns
-------
str
The description associated with the provided key.

Raises
------
KeyError
If the key is not found in the configuration.
"""
data = self._config.dict(by_alias=True)
if key in data:
return data[key]['description'] if return_description_field else data[key]
raise KeyError(f"Key '{key}' not found in the configuration.")

def read_display_name(self, key: str, return_display_name_field: bool = True) -> Any:
"""
Searches for the key in all sections of the configuration.

Parameters
----------
key: str
The key to search for.
return_display_name_field: bool
If True, returns the 'display_name' field of the setting; otherwise, returns the entire setting.

Returns
-------
str
The display_name associated with the provided key.

Raises
------
KeyError
If the key is not found in the configuration.
"""
data = self._config.dict(by_alias=True)
if key in data:
return data[key]['display_name'] if return_display_name_field else data[key]
raise KeyError(f"Key '{key}' not found in the configuration.")

def read_is_path(self, key: str, return_is_path_field: bool = True) -> Any:
"""
Searches for the key in all sections of the configuration.

Parameters
----------
key: str
The key to search for.
return_is_path_field: bool
If True, returns the 'is_path' field of the setting; otherwise, returns the entire setting.

Returns
-------
bool
The is_path associated with the provided key.

Raises
------
KeyError
If the key is not found in the configuration.
"""
data = self._config.dict(by_alias=True)
if key in data:
return data[key]['is_path'] if return_is_path_field else data[key]
raise KeyError(f"Key '{key}' not found in the configuration.")

def write_value(self, key: str, value: Any) -> None:
"""A method for setting a new value to the config.

Expand Down
35 changes: 28 additions & 7 deletions src/badger/tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ class TestBadgerConfig:

def setup_method(self, method):
self.mock_badger_config = BadgerConfig(
BADGER_PLUGIN_ROOT=Setting(display_name="plugin root", description="Mock plugin root", value="/mock/plugin/root"),
BADGER_DB_ROOT=Setting(display_name="database root", description="Mock database root", value="/mock/db/root"),
BADGER_LOGBOOK_ROOT=Setting(display_name="logbook root", description="Mock logbook root", value="/mock/logbook/root"),
BADGER_ARCHIVE_ROOT=Setting(display_name="archive root", description="Mock archive root", value="/mock/archive/root"),
BADGER_DATA_DUMP_PERIOD=Setting(display_name="data dump period", description="Mock data dump period", value=5),
BADGER_THEME=Setting(display_name="theme", description="Mock theme", value="light"),
BADGER_ENABLE_ADVANCED=Setting(display_name="enable advanced", description="Mock enable advanced", value=True),
BADGER_PLUGIN_ROOT=Setting(display_name="plugin root", description="Mock plugin root", value="/mock/plugin/root", is_path=True),
BADGER_DB_ROOT=Setting(display_name="database root", description="Mock database root", value="/mock/db/root", is_path=True),
BADGER_LOGBOOK_ROOT=Setting(display_name="logbook root", description="Mock logbook root", value="/mock/logbook/root", is_path=True),
BADGER_ARCHIVE_ROOT=Setting(display_name="archive root", description="Mock archive root", value="/mock/archive/root", is_path=True),
BADGER_DATA_DUMP_PERIOD=Setting(display_name="data dump period", description="Mock data dump period", value=5, is_path=False),
BADGER_THEME=Setting(display_name="theme", description="Mock theme", value="light", is_path=False),
BADGER_ENABLE_ADVANCED=Setting(display_name="enable advanced", description="Mock enable advanced", value=True, is_path=False),
)

def teardown_method(self, method):
Expand Down Expand Up @@ -98,6 +98,27 @@ def test_read_value(self):
value = config_singleton.read_value('BADGER_PLUGIN_ROOT')
assert value == '/mock/plugin/root'

def test_read_display_name(self):
with patch('os.path.exists', return_value=True):
with patch("builtins.open", mock_open(read_data=yaml.dump(self.mock_badger_config.dict(by_alias=True)))):
config_singleton = ConfigSingleton(self.config_file)
display_name = config_singleton.read_display_name('BADGER_PLUGIN_ROOT')
assert display_name == 'plugin root'

def test_read_description(self):
with patch('os.path.exists', return_value=True):
with patch("builtins.open", mock_open(read_data=yaml.dump(self.mock_badger_config.dict(by_alias=True)))):
config_singleton = ConfigSingleton(self.config_file)
description = config_singleton.read_description('BADGER_PLUGIN_ROOT')
assert description == 'Mock plugin root'

def test_read_is_path(self):
with patch('os.path.exists', return_value=True):
with patch("builtins.open", mock_open(read_data=yaml.dump(self.mock_badger_config.dict(by_alias=True)))):
config_singleton = ConfigSingleton(self.config_file)
is_path = config_singleton.read_is_path('BADGER_PLUGIN_ROOT')
assert is_path == True

def test_write_value(self):
with patch('os.path.exists', return_value=True):
with patch("builtins.open", mock_open(read_data=yaml.dump(self.mock_badger_config.dict(by_alias=True)))):
Expand Down