rename ARGS_SPEC to MODEL_SPEC everywhere

This commit is contained in:
Emily Soth 2022-09-27 17:10:37 -07:00
parent 521f18a352
commit bffbb342f6
63 changed files with 115 additions and 120 deletions

View File

@ -228,9 +228,9 @@ invest_model_modules = {}
for _, name, _ in pkgutil.walk_packages(path=[INVEST_LIB_DIR],
prefix='natcap.'):
module = importlib.import_module(name)
# any module with an ARGS_SPEC is an invest model
if hasattr(module, 'ARGS_SPEC'):
model_title = module.ARGS_SPEC['model_name']
# any module with a MODEL_SPEC is an invest model
if hasattr(module, 'MODEL_SPEC'):
model_title = module.MODEL_SPEC['model_name']
invest_model_modules[model_title] = name
# Write sphinx autodoc function for each entrypoint

View File

@ -306,7 +306,7 @@ Using the parameter study example, this might look like:
Internationalization
====================
If you use the InVEST python API to access model names, ``ARGS_SPEC``s, or validation messages, you can translate those strings using ``gettext``:
If you use the InVEST python API to access model names, ``MODEL_SPEC``s, or validation messages, you can translate those strings using ``gettext``:
.. code-block:: python

View File

@ -1380,4 +1380,4 @@ def validate(args, limit_to=None):
"""
return validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -756,4 +756,4 @@ def validate(args, limit_to=None):
be an empty list if validation succeeds.
"""
return validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -125,7 +125,7 @@ def export_to_python(target_filepath, model, args_dict=None):
if args_dict is None:
model_module = importlib.import_module(
name=model_metadata.MODEL_METADATA[model].pyname)
spec = model_module.ARGS_SPEC
spec = model_module.MODEL_SPEC
cast_args = {key: '' for key in spec['args'].keys()}
else:
cast_args = dict((str(key), value) for (key, value)
@ -436,7 +436,7 @@ def main(user_args=None):
target_model = model_metadata.MODEL_METADATA[args.model].pyname
model_module = importlib.reload(
importlib.import_module(name=target_model))
spec = model_module.ARGS_SPEC
spec = model_module.MODEL_SPEC
if args.json:
message = json.dumps(spec)

View File

@ -567,7 +567,7 @@ def execute(args):
Required if ``args['do_economic_analysis']``.
args['biophysical_table_path'] (string): The path to the biophysical
table on disk. This table has many required columns. See
``ARGS_SPEC`` for the required columns.
``MODEL_SPEC`` for the required columns.
args['landcover_transitions_table'] (string): The path to the landcover
transitions table, indicating the behavior of carbon when the
landscape undergoes a transition.
@ -2282,7 +2282,7 @@ def validate(args, limit_to=None):
message applies to and tuple[1] is the string validation warning.
"""
validation_warnings = validation.validate(
args, ARGS_SPEC['args'])
args, MODEL_SPEC['args'])
sufficient_keys = validation.get_sufficient_keys(args)
invalid_keys = validation.get_invalid_keys(validation_warnings)

View File

@ -368,7 +368,7 @@ def _create_biophysical_table(landcover_table, target_biophysical_table_path):
``None``
"""
target_column_names = [
colname.lower() for colname in coastal_blue_carbon.ARGS_SPEC['args'][
colname.lower() for colname in coastal_blue_carbon.MODEL_SPEC['args'][
'biophysical_table_path']['columns']]
with open(target_biophysical_table_path, 'w') as bio_table:
@ -400,4 +400,4 @@ def validate(args, limit_to=None):
A list of tuples where tuple[0] is an iterable of keys that the error
message applies to and tuple[1] is the string validation warning.
"""
return validation.validate(args, ARGS_SPEC['args'])
return validation.validate(args, MODEL_SPEC['args'])

View File

@ -3355,7 +3355,7 @@ def validate(args, limit_to=None):
"""
validation_warnings = validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])
invalid_keys = validation.get_invalid_keys(validation_warnings)
sufficient_keys = validation.get_sufficient_keys(args)

View File

@ -988,4 +988,4 @@ def validate(args, limit_to=None):
be an empty list if validation succeeds.
"""
return validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -1035,4 +1035,4 @@ def validate(args, limit_to=None):
"""
return validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -212,7 +212,7 @@ def build_datastack_archive(args, model_name, datastack_path):
# For tracking existing files so we don't copy files in twice
files_found = {}
LOGGER.debug(f'Keys: {sorted(args.keys())}')
args_spec = module.ARGS_SPEC['args']
args_spec = module.MODEL_SPEC['args']
spatial_types = {'raster', 'vector'}
file_based_types = spatial_types.union({'csv', 'file', 'directory'})
@ -220,7 +220,7 @@ def build_datastack_archive(args, model_name, datastack_path):
for key in args:
# Allow the model to override specific arguments in datastack archive
# prep. This is useful for tables (like HRA) that are too complicated
# to describe in the ARGS_SPEC format, but use a common specification
# to describe in the MODEL_SPEC format, but use a common specification
# for the other args keys.
override_funcname = f'_override_datastack_archive_{key}'
if hasattr(module, override_funcname):
@ -249,7 +249,7 @@ def build_datastack_archive(args, model_name, datastack_path):
# Possible that a user might pass an args key that doesn't belong to
# this model. Skip if so.
if key not in args_spec:
LOGGER.info(f'Skipping arg {key}; not in model ARGS_SPEC')
LOGGER.info(f'Skipping arg {key}; not in model MODEL_SPEC')
input_type = args_spec[key]['type']
if input_type in file_based_types:
@ -275,7 +275,7 @@ def build_datastack_archive(args, model_name, datastack_path):
if input_type == 'csv':
# check the CSV for columns that may be spatial.
# But also, the columns specification might not be listed, so don't
# require that 'columns' exists in the ARGS_SPEC.
# require that 'columns' exists in the MODEL_SPEC.
spatial_columns = []
if 'columns' in args_spec[key]:
for col_name, col_definition in (
@ -402,7 +402,7 @@ def build_datastack_archive(args, model_name, datastack_path):
# Note that no models currently use this to the best of my
# knowledge, so better to raise a NotImplementedError
raise NotImplementedError(
'The "other" ARGS_SPEC input type is not supported')
'The "other" MODEL_SPEC input type is not supported')
else:
LOGGER.debug(
f"Type {input_type} is not filesystem-based; "

View File

@ -820,4 +820,4 @@ def validate(args, limit_to=None):
"""
return validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -1035,7 +1035,7 @@ def validate(args, limit_to=None):
"""
validation_warnings = validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])
invalid_keys = set([])
for affected_keys, error_msg in validation_warnings:

View File

@ -1226,4 +1226,4 @@ def validate(args, limit_to=None):
"""
return validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -1114,7 +1114,7 @@ def validate(args, limit_to=None):
be an empty list if validation succeeds.
"""
validation_warnings = validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])
invalid_keys = validation.get_invalid_keys(validation_warnings)

View File

@ -65,7 +65,7 @@ Then follow the "Process to update translations" instructions above, starting fr
## Which messages are translated?
* Model titles
* `ARGS_SPEC` `name` and `about` text
* `MODEL_SPEC` `name` and `about` text
* Validation messages
* Strings that appear in the UI, such as button labels and tooltip text

View File

@ -1023,7 +1023,7 @@ def validate(args, limit_to=None):
"""
validation_warnings = validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])
invalid_keys = validation.get_invalid_keys(validation_warnings)

View File

@ -1601,4 +1601,4 @@ def validate(args, limit_to=None):
# Deliberately not validating the interrelationship of the columns between
# the biophysical table and the guilds table as the model itself already
# does extensive checking for this.
return validation.validate(args, ARGS_SPEC['args'])
return validation.validate(args, MODEL_SPEC['args'])

View File

@ -1667,4 +1667,4 @@ def validate(args, limit_to=None):
be an empty list if validation succeeds.
"""
return validation.validate(args, ARGS_SPEC['args'])
return validation.validate(args, MODEL_SPEC['args'])

View File

@ -366,7 +366,7 @@ def validate(args, limit_to=None):
the error message in the second part of the tuple. This should
be an empty list if validation succeeds.
"""
validation_warnings = validation.validate(args, ARGS_SPEC['args'])
validation_warnings = validation.validate(args, MODEL_SPEC['args'])
invalid_keys = validation.get_invalid_keys(validation_warnings)
sufficient_keys = validation.get_sufficient_keys(args)

View File

@ -904,7 +904,7 @@ def validate(args, limit_to=None):
be an empty list if validation succeeds.
"""
validation_warnings = validation.validate(args, ARGS_SPEC['args'])
validation_warnings = validation.validate(args, MODEL_SPEC['args'])
invalid_keys = validation.get_invalid_keys(validation_warnings)
if ('convert_nearest_to_edge' not in invalid_keys and

View File

@ -258,7 +258,7 @@ def execute(args):
'b': float(args['b_coef']),
}
if (args['valuation_function'] not in
ARGS_SPEC['args']['valuation_function']['options']):
MODEL_SPEC['args']['valuation_function']['options']):
raise ValueError('Valuation function type %s not recognized' %
args['valuation_function'])
max_valuation_radius = float(args['max_valuation_radius'])
@ -1092,4 +1092,4 @@ def validate(args, limit_to=None):
"""
return validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -1600,7 +1600,7 @@ def validate(args, limit_to=None):
"""
validation_warnings = validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])
invalid_keys = validation.get_invalid_keys(validation_warnings)
sufficient_keys = validation.get_sufficient_keys(args)

View File

@ -1357,5 +1357,5 @@ def validate(args, limit_to=None):
the error message in the second part of the tuple. This should
be an empty list if validation succeeds.
"""
return validation.validate(args, ARGS_SPEC['args'],
ARGS_SPEC['args_with_spatial_overlap'])
return validation.validate(args, MODEL_SPEC['args'],
MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -209,10 +209,10 @@ def format_unit(unit):
def serialize_args_spec(spec):
"""Serialize an ARGS_SPEC dict to a JSON string.
"""Serialize an MODEL_SPEC dict to a JSON string.
Args:
spec (dict): An invest model's ARGS_SPEC.
spec (dict): An invest model's MODEL_SPEC.
Raises:
TypeError if any object type within the spec is not handled by
@ -506,11 +506,11 @@ def describe_arg_from_name(module_name, *arg_keys):
<arg_keys[0]>-<arg_keys[1]>...-<arg_keys[n]>
where underscores in arg keys are replaced with hyphens.
"""
# import the specified module (that should have an ARGS_SPEC attribute)
# import the specified module (that should have an MODEL_SPEC attribute)
module = importlib.import_module(module_name)
# start with the spec for all args
# narrow down to the nested spec indicated by the sequence of arg keys
spec = module.ARGS_SPEC['args']
spec = module.MODEL_SPEC['args']
for i, key in enumerate(arg_keys):
# convert raster band numbers to ints
if arg_keys[i - 1] == 'bands':
@ -521,7 +521,7 @@ def describe_arg_from_name(module_name, *arg_keys):
keys_so_far = '.'.join(arg_keys[:i + 1])
raise ValueError(
f"Could not find the key '{keys_so_far}' in the "
f"{module_name} model's ARGS_SPEC")
f"{module_name} model's MODEL_SPEC")
# format spec into an RST formatted description string
if 'name' in spec:

View File

@ -1198,5 +1198,5 @@ def validate(args, limit_to=None):
the error message in the second part of the tuple. This should
be an empty list if validation succeeds.
"""
return validation.validate(args, ARGS_SPEC['args'],
ARGS_SPEC['args_with_spatial_overlap'])
return validation.validate(args, MODEL_SPEC['args'],
MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -56,7 +56,7 @@ def get_invest_models():
@app.route(f'/{PREFIX}/getspec', methods=['POST'])
def get_invest_getspec():
"""Gets the ARGS_SPEC dict from an InVEST model.
"""Gets the MODEL_SPEC dict from an InVEST model.
Body (JSON string): "carbon"
Accepts a `language` query parameter which should be an ISO 639-1 language
@ -71,7 +71,7 @@ def get_invest_getspec():
target_module = MODEL_METADATA[target_model].pyname
model_module = importlib.reload(
importlib.import_module(name=target_module))
return spec_utils.serialize_args_spec(model_module.ARGS_SPEC)
return spec_utils.serialize_args_spec(model_module.MODEL_SPEC)
@app.route(f'/{PREFIX}/validate', methods=['POST'])

View File

@ -1059,7 +1059,7 @@ def calculate_energy_savings(
# Find the index of the 'type' column in a case-insensitive way.
# We can assume that the field exists because we're checking for it in
# validation as defined in ARGS_SPEC.
# validation as defined in MODEL_SPEC.
fieldnames = [field.GetName().lower()
for field in target_building_layer.schema]
type_field_index = fieldnames.index('type')
@ -1511,7 +1511,7 @@ def validate(args, limit_to=None):
"""
validation_warnings = validation.validate(
args, ARGS_SPEC['args'], ARGS_SPEC['args_with_spatial_overlap'])
args, MODEL_SPEC['args'], MODEL_SPEC['args_with_spatial_overlap'])
invalid_keys = validation.get_invalid_keys(validation_warnings)
if ('biophysical_table_path' not in invalid_keys and
@ -1523,7 +1523,7 @@ def validate(args, limit_to=None):
# If args['cc_method'] isn't one of these two allowed values
# ('intensity' or 'factors'), it'll be caught by
# validation.validate due to the allowed values stated in
# ARGS_SPEC.
# MODEL_SPEC.
extra_biophysical_keys = ['building_intensity']
error_msg = validation.check_csv(

View File

@ -908,5 +908,5 @@ def validate(args, limit_to=None):
be an empty list if validation succeeds.
"""
return validation.validate(args, ARGS_SPEC['args'],
ARGS_SPEC['args_with_spatial_overlap'])
return validation.validate(args, MODEL_SPEC['args'],
MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -70,7 +70,7 @@ def _calculate_args_bounding_box(args, args_spec):
Args:
args (dict): a string key and any value pair dictionary.
args_spec (dict): the model ARGS_SPEC describing args
args_spec (dict): the model MODEL_SPEC describing args
Returns:
bb_intersection, bb_union tuple that's either the lat/lng bounding
@ -216,7 +216,7 @@ def _log_model(pyname, model_args, invest_interface, session_id=None):
md5.update(json.dumps(data).encode('utf-8'))
return md5.hexdigest()
args_spec = importlib.import_module(pyname).ARGS_SPEC
args_spec = importlib.import_module(pyname).MODEL_SPEC
try:
bounding_box_intersection, bounding_box_union = (

View File

@ -904,12 +904,12 @@ def validate(args, spec, spatial_overlap_opts=None):
invalid_keys = set()
sufficient_keys = set(args.keys()).difference(insufficient_keys)
for key in sufficient_keys.difference(excluded_keys):
# Extra args that don't exist in the ARGS_SPEC are okay
# Extra args that don't exist in the MODEL_SPEC are okay
# we don't need to try to validate them
try:
parameter_spec = spec[key]
except KeyError:
LOGGER.debug(f'Provided key {key} does not exist in ARGS_SPEC')
LOGGER.debug(f'Provided key {key} does not exist in MODEL_SPEC')
continue
type_validation_func = _VALIDATION_FUNCS[parameter_spec['type']]
@ -1013,24 +1013,24 @@ def invest_validator(validate_func):
# import one another. This causes a problem in test_validation.py,
# which gets imported into itself here and fails.
# Since this decorator might not be needed in the future,
# just ignore failed imports; assume they have no ARGS_SPEC.
# just ignore failed imports; assume they have no MODEL_SPEC.
try:
model_module = importlib.import_module(validate_func.__module__)
except Exception:
LOGGER.warning('Unable to import module %s: assuming no ARGS_SPEC.',
LOGGER.warning('Unable to import module %s: assuming no MODEL_SPEC.',
validate_func.__module__)
model_module = None
# If the module has an ARGS_SPEC defined, validate against that.
if hasattr(model_module, 'ARGS_SPEC'):
# If the module has an MODEL_SPEC defined, validate against that.
if hasattr(model_module, 'MODEL_SPEC'):
LOGGER.debug('Using ARG_SPEC for validation')
args_spec = getattr(model_module, 'ARGS_SPEC')['args']
args_spec = getattr(model_module, 'MODEL_SPEC')['args']
if limit_to is None:
LOGGER.info('Starting whole-model validation with ARGS_SPEC')
LOGGER.info('Starting whole-model validation with MODEL_SPEC')
warnings_ = validate_func(args)
else:
LOGGER.info('Starting single-input validation with ARGS_SPEC')
LOGGER.info('Starting single-input validation with MODEL_SPEC')
args_key_spec = args_spec[limit_to]
args_value = args[limit_to]
@ -1061,7 +1061,7 @@ def invest_validator(validate_func):
else:
warnings_ = [([limit_to], error_msg)]
else: # args_spec is not defined for this function.
LOGGER.warning('ARGS_SPEC not defined for this model')
LOGGER.warning('MODEL_SPEC not defined for this model')
warnings_ = validate_func(args, limit_to)
LOGGER.debug('Validation warnings: %s',

View File

@ -2340,4 +2340,4 @@ def validate(args, limit_to=None):
validation warning.
"""
return validation.validate(args, ARGS_SPEC['args'])
return validation.validate(args, MODEL_SPEC['args'])

View File

@ -2703,5 +2703,5 @@ def validate(args, limit_to=None):
message applies to and tuple[1] is the str validation warning.
"""
return validation.validate(args, ARGS_SPEC['args'],
ARGS_SPEC['args_with_spatial_overlap'])
return validation.validate(args, MODEL_SPEC['args'],
MODEL_SPEC['args_with_spatial_overlap'])

View File

@ -269,7 +269,7 @@ class CarbonTests(unittest.TestCase):
class CarbonValidationTests(unittest.TestCase):
"""Tests for the Carbon Model ARGS_SPEC and validation."""
"""Tests for the Carbon Model MODEL_SPEC and validation."""
def setUp(self):
"""Create a temporary workspace."""

View File

@ -401,7 +401,7 @@ class CLIUnitTests(unittest.TestCase):
target_model = model_metadata.MODEL_METADATA[target_model].pyname
model_module = importlib.import_module(name=target_model)
spec = model_module.ARGS_SPEC
spec = model_module.MODEL_SPEC
expected_args = {key: '' for key in spec['args'].keys()}
module_name = str(uuid.uuid4()) + 'testscript'

View File

@ -1583,7 +1583,7 @@ def assert_pickled_arrays_almost_equal(
class CoastalVulnerabilityValidationTests(unittest.TestCase):
"""Tests for the CV Model ARGS_SPEC and validation."""
"""Tests for the CV Model MODEL_SPEC and validation."""
def setUp(self):
"""Create a temporary workspace."""

View File

@ -400,7 +400,7 @@ class CropProductionTests(unittest.TestCase):
class CropValidationTests(unittest.TestCase):
"""Tests for the Crop Productions' ARGS_SPEC and validation."""
"""Tests for the Crop Productions' MODEL_SPEC and validation."""
def setUp(self):
"""Create a temporary workspace."""

View File

@ -1,4 +1,4 @@
ARGS_SPEC = {
MODEL_SPEC = {
'args': {
'blank': {'type': 'freestyle_string'},
'a': {'type': 'integer'},

View File

@ -1,4 +1,4 @@
ARGS_SPEC = {
MODEL_SPEC = {
'args': {
'foo': {'type': 'file'},
'bar': {'type': 'file'},

View File

@ -1,4 +1,4 @@
ARGS_SPEC = {
MODEL_SPEC = {
'args': {
'some_file': {'type': 'file'},
'data_dir': {'type': 'directory'},

View File

@ -1,4 +1,4 @@
ARGS_SPEC = {
MODEL_SPEC = {
'args': {
'raster': {'type': 'raster'},
}

View File

@ -1,4 +1,4 @@
ARGS_SPEC = {
MODEL_SPEC = {
'args': {
'a': {'type': 'integer'},
'b': {'type': 'freestyle_string'},

View File

@ -1,4 +1,4 @@
ARGS_SPEC = {
MODEL_SPEC = {
'args': {
'foo': {'type': 'freestyle_string'},
'bar': {'type': 'freestyle_string'},

View File

@ -1,4 +1,4 @@
ARGS_SPEC = {
MODEL_SPEC = {
'args': {
'vector': {'type': 'vector'},
}

View File

@ -349,7 +349,7 @@ class ForestCarbonEdgeTests(unittest.TestCase):
class ForestCarbonEdgeValidationTests(unittest.TestCase):
"""Tests for the Forest Carbon Model ARGS_SPEC and validation."""
"""Tests for the Forest Carbon Model MODEL_SPEC and validation."""
def setUp(self):
"""Create a temporary workspace."""

View File

@ -395,7 +395,7 @@ class GLOBIOTests(unittest.TestCase):
class GlobioValidationTests(unittest.TestCase):
"""Tests for the GLOBIO Model ARGS_SPEC and validation."""
"""Tests for the GLOBIO Model MODEL_SPEC and validation."""
def setUp(self):
"""Create a temporary workspace."""

View File

@ -77,26 +77,23 @@ class ValidateModelSpecs(unittest.TestCase):
for key, spec in model.MODEL_SPEC['outputs'].items():
self.validate_output(spec, f'{model_name}.outputs.{key}')
def validate_output(self, spec, key, parent_type=None, is_pattern=False):
def validate_output(self, spec, key, parent_type=None):
"""
Recursively validate nested spec s against the arg spec standard.
Recursively validate nested output specs against the output spec standard.
Args:
spec (dict): any nested spec component of an MODEL_SPEC
name (str): name to use in error messages to identify the spec
parent_type (str): the type of this spec's parent arg (or None if
spec (dict): any nested output spec component of a MODEL_SPEC
key (str): key to identify the spec by in error messages
parent_type (str): the type of this output's parent output (or None if
no parent).
is_pattern (bool): if True, the arg is validated as a pattern (such
as for user-defined CSV headers, vector fields, or directory
paths).
Returns:
None
Raises:
AssertionError if the arg violates the standard
AssertionError if the output spec violates the standard
"""
with self.subTest(nested_arg_name=key):
with self.subTest(output=key):
# if parent_type is None: # all top-level args must have these attrs
# for attr in ['about']:
# self.assertIn(attr, spec)
@ -113,7 +110,8 @@ class ValidateModelSpecs(unittest.TestCase):
t = 'vector'
elif file_extension == 'csv':
t = 'csv'
elif file_extension in {'json', 'txt', 'pickle', 'db', 'zip', 'dat', 'idx'}:
elif file_extension in {'json', 'txt', 'pickle', 'db', 'zip',
'dat', 'idx'}:
t = 'file'
else:
raise Warning(
@ -228,7 +226,7 @@ class ValidateModelSpecs(unittest.TestCase):
'expected for its type')
def validate(self, arg, name, parent_type=None, is_pattern=False):
def validate(self, arg, name, parent_type=None):
"""
Recursively validate nested args against the arg spec standard.
@ -237,9 +235,6 @@ class ValidateModelSpecs(unittest.TestCase):
name (str): name to use in error messages to identify the arg
parent_type (str): the type of this arg's parent arg (or None if
no parent).
is_pattern (bool): if True, the arg is validated as a pattern (such
as for user-defined CSV headers, vector fields, or directory
paths).
Returns:
None

View File

@ -463,7 +463,7 @@ class PollinationTests(unittest.TestCase):
class PollinationValidationTests(unittest.TestCase):
"""Tests for the Pollination Model ARGS_SPEC and validation."""
"""Tests for the Pollination Model MODEL_SPEC and validation."""
def setUp(self):
"""Create list of always required arguments."""

View File

@ -1190,7 +1190,7 @@ class RecreationRegressionTests(unittest.TestCase):
class RecreationValidationTests(unittest.TestCase):
"""Tests for the Recreation Model ARGS_SPEC and validation."""
"""Tests for the Recreation Model MODEL_SPEC and validation."""
def setUp(self):
"""Create a temporary workspace."""

View File

@ -135,7 +135,7 @@ class ScenarioProximityTests(unittest.TestCase):
class ScenarioGenValidationTests(unittest.TestCase):
"""Tests for the Scenario Generator ARGS_SPEC and validation."""
"""Tests for the Scenario Generator MODEL_SPEC and validation."""
def setUp(self):
"""Initiate list of required keys."""

View File

@ -1065,7 +1065,7 @@ class SeasonalWaterYieldRegressionTests(unittest.TestCase):
class SWYValidationTests(unittest.TestCase):
"""Tests for the SWY Model ARGS_SPEC and validation."""
"""Tests for the SWY Model MODEL_SPEC and validation."""
def setUp(self):
"""Create a temporary workspace."""

View File

@ -242,6 +242,6 @@ class TestSpecUtils(unittest.TestCase):
expected_rst = (
'.. _carbon-pools-path-columns-lucode:\n\n' +
'**lucode** (`integer <input_types.html#integer>`__, *required*): ' +
carbon.ARGS_SPEC['args']['carbon_pools_path']['columns']['lucode']['about']
carbon.MODEL_SPEC['args']['carbon_pools_path']['columns']['lucode']['about']
)
self.assertEqual(repr(out), repr(expected_rst))

View File

@ -136,7 +136,7 @@ class TranslationTests(unittest.TestCase):
"""Translation: test that /validate endpoint is translated."""
test_client = ui_server.app.test_client()
payload = {
'model_module': carbon.ARGS_SPEC['pyname'],
'model_module': carbon.MODEL_SPEC['pyname'],
'args': json.dumps({})
}
response = test_client.post(

View File

@ -67,7 +67,7 @@ class EndpointFunctionTests(unittest.TestCase):
self.assertEqual(
set(spec),
{'model_name', 'pyname', 'userguide',
'args_with_spatial_overlap', 'args'})
'args_with_spatial_overlap', 'args', 'outputs'})
def test_get_invest_validate(self):
"""UI server: get_invest_validate endpoint."""
@ -77,7 +77,7 @@ class EndpointFunctionTests(unittest.TestCase):
'workspace_dir': 'foo'
}
payload = {
'model_module': carbon.ARGS_SPEC['pyname'],
'model_module': carbon.MODEL_SPEC['pyname'],
'args': json.dumps(args)
}
response = test_client.post(f'{ROUTE_PREFIX}/validate', json=payload)

View File

@ -1355,7 +1355,7 @@ class TestValidationFromSpec(unittest.TestCase):
self.assertEqual(set(args.keys()), set(validation_warnings[0][0]))
def test_allow_extra_keys(self):
"""Including extra keys in args that aren't in ARGS_SPEC should work"""
"""Including extra keys in args that aren't in MODEL_SPEC should work"""
from natcap.invest import validation
args = {'a': 'a', 'b': 'b'}
@ -1367,7 +1367,7 @@ class TestValidationFromSpec(unittest.TestCase):
'required': True
}
}
message = 'DEBUG:natcap.invest.validation:Provided key b does not exist in ARGS_SPEC'
message = 'DEBUG:natcap.invest.validation:Provided key b does not exist in MODEL_SPEC'
with self.assertLogs('natcap.invest.validation', level='DEBUG') as cm:
validation.validate(args, spec)

View File

@ -613,7 +613,7 @@ class WaveEnergyRegressionTests(unittest.TestCase):
class WaveEnergyValidateTests(unittest.TestCase):
"""Wave Energy Validate: tests for ARGS_SPEC and validate."""
"""Wave Energy Validate: tests for MODEL_SPEC and validate."""
def setUp(self):
"""Set up list of required keys."""

View File

@ -850,7 +850,7 @@ class WindEnergyRegressionTests(unittest.TestCase):
class WindEnergyValidationTests(unittest.TestCase):
"""Tests for the Wind Energy Model ARGS_SPEC and validation."""
"""Tests for the Wind Energy Model MODEL_SPEC and validation."""
def setUp(self):
"""Setup a list of required keys."""

View File

@ -22,7 +22,7 @@ import { ipcMainChannels } from '../../../main/ipcMainChannels';
const { ipcRenderer } = window.Workbench.electron;
const logger = window.Workbench.getLogger('InvestTab');
/** Get an invest model's ARGS_SPEC when a model button is clicked.
/** Get an invest model's spec when a model button is clicked.
*
* @param {string} modelName - as in a model name appearing in `invest list`
* @returns {object} destructures to:
@ -57,8 +57,8 @@ export default class InvestTab extends React.Component {
super(props);
this.state = {
activeTab: 'setup',
modelSpec: null, // ARGS_SPEC dict with all keys except ARGS_SPEC.args
argsSpec: null, // ARGS_SPEC.args, the immutable args stuff
modelSpec: null, // MODEL_SPEC dict with all keys except MODEL_SPEC.args
argsSpec: null, // MODEL_SPEC.args, the immutable args stuff
uiSpec: null,
userTerminated: false,
executeClicked: false,

View File

@ -32,7 +32,7 @@ const { ipcRenderer } = window.Workbench.electron;
*
* Values initialize with either a complete args dict, or with empty/default values.
*
* @param {object} argsSpec - an InVEST model's ARGS_SPEC.args
* @param {object} argsSpec - an InVEST model's MODEL_SPEC.args
* @param {object} uiSpec - the model's UI Spec.
* @param {object} argsDict - key: value pairs of InVEST model arguments, or {}.
*

View File

@ -28,7 +28,7 @@ export async function getInvestModelNames() {
}
/**
* Get the ARGS_SPEC dict from an invest model as a JSON.
* Get the MODEL_SPEC dict from an invest model as a JSON.
*
* @param {string} payload - model name as given by `invest list`
* @returns {Promise} resolves object

View File

@ -19,7 +19,7 @@ where
Args within each nested array are visually grouped together.
- `hidden` (optional) a 1D array of args that should not be displayed in a GUI.
Use this for model-specific args, no need to include 'n_workers'.
All args in ARGS_SPEC (except n_workers) must be contained in `order`+`hidden`.
All args in MODEL_SPEC (except n_workers) must be contained in `order`+`hidden`.
`hidden` is only used in tests, to catch args that should be in `order`,
but are missing.
- `modelName` as passed to `invest getspec <modelName>`
@ -28,7 +28,7 @@ where
- `f` is a function that accepts `SetupTab.state` as its one argument
- in the `enabledFunctions` section, `f` returns a boolean where true = enabled, false = disabled
- in the `dropdownFunctions` section, `f` returns a list of dropdown options.
Note: Most dropdown inputs will have a static list of options defined in the ARGS_SPEC.
Note: Most dropdown inputs will have a static list of options defined in the MODEL_SPEC.
This is only for dynamically populating a dropdown.
When the SetupTab component renders, it calls `f(this.state)` to get

View File

@ -158,10 +158,10 @@ describe('validate the UI spec', () => {
expect(spec.model_name).toBeDefined();
expect(Object.keys(UI_SPEC)).toContain(modelName);
expect(Object.keys(UI_SPEC[modelName])).toContain('order');
// expect each ARGS_SPEC arg to exist in 'order' or 'hidden' property
// expect each MODEL_SPEC arg to exist in 'order' or 'hidden' property
const orderArray = UI_SPEC[modelName].order.flat();
// 'hidden' is an optional property. It need not include 'n_workers',
// but we should insert 'n_workers' here as it is present in ARGS_SPEC.
// but we should insert 'n_workers' here as it is present in MODEL_SPEC.
const hiddenArray = UI_SPEC[modelName].hidden || [];
const allArgs = orderArray.concat(hiddenArray.concat('n_workers'));
const argsSet = new Set(allArgs);
@ -207,7 +207,7 @@ expect.extend({
},
});
describe('Build each model UI from ARGS_SPEC', () => {
describe('Build each model UI from MODEL_SPEC', () => {
const { UI_SPEC } = require('../../src/renderer/ui_config');
test.each(Object.keys(UI_SPEC))('%s', async (model) => {

View File

@ -18,7 +18,7 @@ jest.mock('../../src/renderer/server_requests');
const MODULE = 'carbon';
const VALIDATION_MESSAGE = 'invalid because';
const BASE_ARGS_SPEC = {
const BASE_MODEL_SPEC = {
args: {
arg: {
name: 'foo',
@ -37,14 +37,14 @@ const BASE_ARGS_SPEC = {
*/
function baseArgsSpec(type) {
// make a deep copy so we don't edit the original
const spec = JSON.parse(JSON.stringify(BASE_ARGS_SPEC));
const spec = JSON.parse(JSON.stringify(BASE_MODEL_SPEC));
spec.args.arg.type = type;
if (type === 'number') {
spec.args.arg.units = 'foo unit';
}
return spec;
}
const UI_SPEC = { order: [Object.keys(BASE_ARGS_SPEC.args)] };
const UI_SPEC = { order: [Object.keys(BASE_MODEL_SPEC.args)] };
/**
* Render a SetupTab component given the necessary specs.
@ -54,7 +54,7 @@ const UI_SPEC = { order: [Object.keys(BASE_ARGS_SPEC.args)] };
* @returns {object} - containing the test utility functions returned by render
*/
function renderSetupFromSpec(baseSpec, uiSpec) {
// some ARGS_SPEC boilerplate that is not under test,
// some MODEL_SPEC boilerplate that is not under test,
// but is required by PropType-checking
const spec = { ...baseSpec };
if (!spec.modelName) { spec.modelName = 'Eco Model'; }
@ -82,7 +82,7 @@ function renderSetupFromSpec(baseSpec, uiSpec) {
describe('Arguments form input types', () => {
beforeEach(() => {
fetchValidation.mockResolvedValue(
[[Object.keys(BASE_ARGS_SPEC.args), VALIDATION_MESSAGE]]
[[Object.keys(BASE_MODEL_SPEC.args), VALIDATION_MESSAGE]]
);
});
@ -157,7 +157,7 @@ describe('Arguments form input types', () => {
describe('Arguments form interactions', () => {
beforeEach(() => {
fetchValidation.mockResolvedValue(
[[Object.keys(BASE_ARGS_SPEC.args), VALIDATION_MESSAGE]]
[[Object.keys(BASE_MODEL_SPEC.args), VALIDATION_MESSAGE]]
);
setupOpenExternalUrl();
});