-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #71 from slevis-lmwg/mksurdat_iss36
This merge includes the - jupyter notebook tool for generating SLIM surdat files (#71) - python tool for modifying SLIM surdat files (#69)
- Loading branch information
Showing
16 changed files
with
2,216 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,162 @@ | ||
""" | ||
General-purpose utilities and functions for handling command-line | ||
config files in slim python codes. | ||
""" | ||
|
||
import logging | ||
import configparser | ||
|
||
from slim.utils import abort | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
# This string is used in the out-of-the-box slim.cfg and modify.cfg files | ||
# to denote a value that needs to be filled in | ||
_CONFIG_PLACEHOLDER = "FILL_THIS_IN" | ||
# This string is used in the out-of-the-box slim.cfg and modify.cfg files | ||
# to denote a value that can be filled in, but doesn't absolutely need to be | ||
_CONFIG_UNSET = "UNSET" | ||
|
||
|
||
def lon_range_0_to_360(lon_in): | ||
""" | ||
Description | ||
----------- | ||
Restrict longitude to 0 to 360 when given as -180 to 180. | ||
""" | ||
if -180 <= lon_in < 0: | ||
lon_out = lon_in % 360 | ||
logger.info( | ||
"Resetting longitude from %s to %s to keep in the range " " 0 to 360", | ||
str(lon_in), | ||
str(lon_out), | ||
) | ||
elif 0 <= lon_in <= 360 or lon_in is None: | ||
lon_out = lon_in | ||
else: | ||
errmsg = "lon_in needs to be in the range 0 to 360" | ||
abort(errmsg) | ||
|
||
return lon_out | ||
|
||
|
||
def get_config_value( | ||
config, | ||
section, | ||
item, | ||
file_path, | ||
allowed_values=None, | ||
default=None, | ||
is_list=False, | ||
convert_to_type=None, | ||
can_be_unset=False, | ||
): | ||
"""Get a given item from a given section of the config object | ||
Give a helpful error message if we can't find the given section or item | ||
Note that the file_path argument is only used for the sake of the error message | ||
If allowed_values is present, it should be a list of strings giving allowed values | ||
The function _handle_config_value determines what to do if we read: | ||
- a list or | ||
- a str that needs to be converted to int / float / bool | ||
- _CONFIG_UNSET: anything with the value "UNSET" will become "None" | ||
""" | ||
try: | ||
val = config.get(section, item) | ||
except configparser.NoSectionError: | ||
abort("ERROR: Config file {} must contain section '{}'".format(file_path, section)) | ||
except configparser.NoOptionError: | ||
abort( | ||
"ERROR: Config file {} must contain item '{}' in section '{}'".format( | ||
file_path, item, section | ||
) | ||
) | ||
|
||
if val == _CONFIG_PLACEHOLDER: | ||
abort("Error: {} needs to be specified in config file {}".format(item, file_path)) | ||
|
||
val = _handle_config_value( | ||
var=val, | ||
default=default, | ||
item=item, | ||
is_list=is_list, | ||
convert_to_type=convert_to_type, | ||
can_be_unset=can_be_unset, | ||
allowed_values=allowed_values, | ||
) | ||
return val | ||
|
||
|
||
def _handle_config_value( | ||
var, default, item, is_list, convert_to_type, can_be_unset, allowed_values | ||
): | ||
""" | ||
Description | ||
----------- | ||
Assign the default value or the user-specified one to var. | ||
Convert from default type (str) to reqested type (int or float). | ||
If is_list is True, then default should be a list | ||
""" | ||
if var == _CONFIG_UNSET: | ||
if can_be_unset: | ||
return default # default may be None | ||
abort("Must set a value for .cfg file variable: {}".format(item)) | ||
|
||
# convert string to list of strings; if there is just one element, | ||
# we will get a list of size one, which we will convert back to a | ||
# scalar later if needed | ||
var = var.split() | ||
|
||
if convert_to_type is bool: | ||
try: | ||
var = [_convert_to_bool(v) for v in var] | ||
except ValueError: | ||
abort("Non-boolean value found for .cfg file variable: {}".format(item)) | ||
elif convert_to_type is not None: | ||
try: | ||
var = [convert_to_type(v) for v in var] | ||
except ValueError: | ||
abort("Wrong type for .cfg file variable: {}".format(item)) | ||
|
||
if allowed_values is not None: | ||
for val in var: | ||
if val not in allowed_values: | ||
print("val = ", val, " in var not in allowed_values") | ||
errmsg = ( | ||
"{} is not an allowed value for {} in .cfg file. " | ||
"Check allowed_values".format(val, item) | ||
) | ||
abort(errmsg) | ||
|
||
if not is_list: | ||
if len(var) > 1: | ||
abort("More than 1 element found for .cfg file variable: {}".format(item)) | ||
var = var[0] | ||
|
||
return var | ||
|
||
|
||
def _convert_to_bool(var): | ||
""" | ||
Function for converting different forms of | ||
boolean strings to boolean value. | ||
Args: | ||
var (str): String bool input | ||
Raises: | ||
if the argument is not an acceptable boolean string | ||
(such as yes or no ; true or false ; y or n ; t or f ; 0 or 1). | ||
ValueError: The string should be one of the mentioned values. | ||
Returns: | ||
var_out (bool): Boolean value corresponding to the input. | ||
""" | ||
if var.lower() in ("yes", "true", "t", "y", "1", "on"): | ||
var_out = True | ||
elif var.lower() in ("no", "false", "f", "n", "0", "off"): | ||
var_out = False | ||
else: | ||
raise ValueError("Boolean value expected. [true or false] or [y or n]") | ||
|
||
return var_out |
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,61 @@ | ||
"""General-purpose git utility functions""" | ||
|
||
import logging | ||
import subprocess | ||
|
||
from slim.path_utils import path_to_slim_root | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def get_slim_git_short_hash(): | ||
""" | ||
Returns Git short SHA for the SLIM repository. | ||
Args: | ||
Raises: | ||
Returns: | ||
sha (str) : git short hash for slim repository | ||
""" | ||
sha = ( | ||
subprocess.check_output(["git", "-C", path_to_slim_root(), "rev-parse", "--short", "HEAD"]) | ||
.strip() | ||
.decode() | ||
) | ||
return sha | ||
|
||
|
||
def get_slim_git_long_hash(): | ||
""" | ||
Returns Git long SHA for the SLIM repository. | ||
Args: | ||
Raises: | ||
Returns: | ||
sha (str) : git long hash for slim repository | ||
""" | ||
sha = ( | ||
subprocess.check_output(["git", "-C", path_to_slim_root(), "rev-parse", "HEAD"]) | ||
.strip() | ||
.decode() | ||
) | ||
return sha | ||
|
||
|
||
def get_slim_git_describe(): | ||
""" | ||
Function for giving the recent tag of the SLIM repository | ||
Args: | ||
Raises: | ||
Returns: | ||
label (str) : ouput of running 'git describe' for the SLIM repository | ||
""" | ||
label = subprocess.check_output(["git", "-C", path_to_slim_root(), "describe"]).strip().decode() | ||
return label |
Empty file.
Oops, something went wrong.