-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve config handler, large restructuring and start of testing and …
…type annotations (#11) * move tests into ldndc2nc folder * parse_config requires a section arg * add test for find_config and new dev requirement pyfakefs for fs mocking * update default conf to new multi-var syntax * update gitignore * remove superfluous update_docs.sh * add some special folders/ files to gitignore * add some special folders/ files to gitignore (2) * add some special folders/ files to gitignore (3) * change tests from xfail to raises * add new config_handler and variable classes and associated tests * move to config_handler (incomplete) * make sure we do not drop cols prematurely in case of aggregate cols * allow nan and 0 as non-id values in reffile * new id_mapper and various changes to variable and unit handling * small fix * disable test for confighandler.file_path momentarily * add setuptools to gh actions ci * fix test_find_path for config_handler * small fix * disbale config_handler test to see if this makes it pass the github actions ci test step
- Loading branch information
Showing
12 changed files
with
538 additions
and
86 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,14 @@ | ||
*.py[cod] | ||
|
||
*.nc | ||
|
||
__pycache__ | ||
pip-wheel-metadata | ||
_version.py | ||
.pytest_cache | ||
.DS_Store | ||
.vscode | ||
|
||
# C extensions | ||
*.so | ||
|
||
|
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,143 @@ | ||
# -*- coding: utf-8 -*- | ||
"""ldndc2nc.config_handler: read the configuration settings for this ldndc2nc run.""" | ||
|
||
import logging | ||
import os | ||
from pathlib import Path | ||
|
||
import yaml | ||
|
||
from .variable import Variable | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
def find_config(local_file=None): | ||
""" look for config file in the default locations """ | ||
env_var = os.environ.get("LDNDC2NC_CONF", "__NOTSET__") | ||
locations = [ | ||
x / "ldndc2nc.conf" for x in [Path("."), Path.home(), Path("/etc/ldndc2nc")] | ||
] | ||
locations.append(Path(env_var)) | ||
|
||
if local_file: | ||
locations.insert(0, Path(local_file)) | ||
|
||
for cfg_file in locations: | ||
if cfg_file.is_file(): | ||
return cfg_file | ||
return None | ||
|
||
|
||
def read_config(file_path) -> None: | ||
""" read yaml config file and modify special properties""" | ||
|
||
print(f"read_config: {file_path}") | ||
with open(file_path, "r") as ymlfile: | ||
cfg = yaml.load(ymlfile, Loader=yaml.FullLoader) | ||
|
||
return cfg | ||
|
||
|
||
def write_config(self, dest=Path.home()): | ||
""" write cfg file to user dir """ | ||
|
||
if self.cfg: | ||
self._decode() | ||
fname = Path(dest) / "ldndc2nc.conf" | ||
with open(fname, "w") as f: | ||
f.write(yaml.dump(self._decode(self.cfg), default_flow_style=False)) | ||
|
||
|
||
def get_section(self, section): | ||
""" parse config data structure, return data of required section """ | ||
|
||
if self.cfg: | ||
self.cfg = self._encode(self.cfg) | ||
|
||
section_data = None | ||
|
||
def is_valid_section(s): | ||
valid_sections = ["info", "project", "variables", "refdata"] | ||
return s in valid_sections | ||
|
||
if is_valid_section(section.lower()): | ||
try: | ||
section_data = self.cfg.get(section, self.cfg.get(section.lower())) | ||
except KeyError: | ||
log.critical( | ||
f"Section <{section.lower()}> not found in cfg file {self.file_path}" | ||
) | ||
log.critical( | ||
f"The following sections are present: {list(self.cfg.keys())}." | ||
) | ||
else: | ||
log.critical(f"Section {section.lower()} is not a valid section") | ||
raise RuntimeError | ||
return section_data | ||
|
||
|
||
class ConfigHandler: | ||
|
||
_write_config = write_config | ||
_get_section = get_section | ||
|
||
def __init__(self, local_file=None): | ||
self.cfg_file = find_config(local_file=local_file) | ||
raw = read_config(self.cfg_file) | ||
self.cfg = self._encode(raw) | ||
|
||
@staticmethod | ||
def _decode(cfg): | ||
if "variables" in cfg: | ||
for file, variables in cfg["variables"].items(): | ||
cfg["variables"][file] = [v.text_full for v in variables] | ||
return cfg | ||
|
||
@staticmethod | ||
def _encode(cfg): | ||
if "variables" in cfg: | ||
for file, variables in cfg["variables"].items(): | ||
cfg["variables"][file] = [ | ||
Variable(v) if isinstance(v, str) else v for v in variables | ||
] | ||
return cfg | ||
|
||
@property | ||
def file_path(self): | ||
if not self.cfg_file: | ||
self.cfg_file = find_config() | ||
return self.cfg_file | ||
|
||
@property | ||
def variables(self): | ||
vars = [] | ||
if "variables" in self.cfg: | ||
for file, variables in self.cfg["variables"].items(): | ||
vars += [Variable(v) if isinstance(v, str) else v for v in variables] | ||
return vars | ||
|
||
@property | ||
def text(self): | ||
clean = self._decode(self.cfg) | ||
return yaml.dump(clean, default_style=False) if self.cfg else None | ||
|
||
@property | ||
def global_info(self): | ||
global_info = {} | ||
for section_name in ["info", "project"]: | ||
section = self.section(section_name) | ||
if section: | ||
global_info.update(section) | ||
else: | ||
log.warn(f"No <{section_name}> data found in config") | ||
return global_info | ||
|
||
def section(self, section): | ||
return self._get_section(section) | ||
|
||
def write(self, *args, **kwargs): | ||
self._write_config(*args, **kwargs) | ||
|
||
def __repr__(self): | ||
return f"<cfg: {self.file_path}>" |
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
Oops, something went wrong.