Skip to content

Commit

Permalink
Merge pull request #203 from clamsproject/197-map-typed-param
Browse files Browse the repository at this point in the history
default values for `mutlivalued=True` params now must be lists
  • Loading branch information
keighrim authored Mar 28, 2024
2 parents 371c413 + 906c486 commit 0edf198
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 8 deletions.
16 changes: 11 additions & 5 deletions clams/appmetadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,13 @@ class RuntimeParameter(_BaseModel):
None,
description="(optional) List of string values that can be accepted."
)
default: Union[real_valued_primitives, List[real_valued_primitives], Dict[str, str]] = pydantic.Field(
default: Union[real_valued_primitives, List[real_valued_primitives]] = pydantic.Field(
None,
description="(optional) Default value for the parameter. Only valid for optional parameters. Namely, setting "
"a default value makes a parameter `optional`."
description="(optional) Default value for the parameter.\n\n"
"Notes for developers: \n\n"
"Setting a default value makes a parameter `optional`. \n\n"
"When ``multivalued=True``, the default value should be a list of values. \n\n"
"When ``type=map``, the default value should be a list of colon-separated strings. \n\n"
)
multivalued: bool = pydantic.Field(
...,
Expand All @@ -193,6 +196,9 @@ def __init__(self, **kwargs):
self.multivalued = True
if self.multivalued is None:
self.multivalued = False
if self.multivalued:
if not isinstance(self.default, list):
self.default = [self.default]

class Config:
title = 'CLAMS App Runtime Parameter'
Expand Down Expand Up @@ -402,8 +408,8 @@ def add_parameter(self, name: str, description: str, type: param_value_types,
"""
Helper method to add an element to the ``parameters`` list.
"""
# casting default values (when the value is not nothing) makes sure
# the values are correctly casted by the pydantic
# casting default values (when the value is not nothing) to str
# will make sure the values are correctly handled by the pydantic
# see https://docs.pydantic.dev/1.10/usage/types/#unions
# e.g. casting 0.1 using the `primitives` dict will result in 0 (int)
# while casting "0.1" using the `primitives` dict will result in 0.1 (float)
Expand Down
27 changes: 24 additions & 3 deletions tests/test_clamsapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,18 +165,39 @@ def test_metadata_inputoutput(self):

def test_metadata_runtimeparams(self):
# now parameters
num_params = 1 # starts with `raise_error` in metadata.py
# using a custom class
# this should conflict with existing parameter
with self.assertRaises(ValueError):
self.app.metadata.add_parameter(
name='raise_error', description='force raise a ValueError',
type='boolean', default='false')
# using python dict
num_params += 0

# some random multiple choice parameters
self.app.metadata.add_parameter(
name='single_choice', description='meaningless choice for a single value',
type='integer', choices=[1, 2, 3, 4, 5], default='3', multivalued=False)
num_params += 1

self.app.metadata.add_parameter(
name='multiple_choice', description='meaningless multiple choice option',
name='multiple_choice', description='meaningless choice for any number of values',
type='integer', choices=[1, 2, 3, 4, 5], default=3, multivalued=True)
num_params += 1

metadata = json.loads(self.app.appmetadata())
self.assertEqual(len(metadata['parameters']), 2 + len(self.app.universal_parameters))
self.assertEqual(len(metadata['parameters']), num_params + len(self.app.universal_parameters))

for p in metadata['parameters']:
# default value must match the data type
if p['name'] == 'single_choice':
self.assertFalse(p['multivalued'])
self.assertTrue(isinstance(p['default'], int))
# default for multivalued para must be a list
if p['name'] == 'multiple_choice':
self.assertTrue(p['multivalued'])
self.assertTrue(isinstance(p['default'], list))
self.assertEqual(len(p['default']), 1)
# now more additional metadata
self.app.metadata.add_more('one', 'more')
self.assertEqual(self.app.metadata.more['one'], 'more')
Expand Down

0 comments on commit 0edf198

Please sign in to comment.