From 546cdd5493899c2d3c90d4c92b3e3038571d2d85 Mon Sep 17 00:00:00 2001 From: Ryan Wehrle Date: Thu, 25 May 2023 11:44:08 -0400 Subject: [PATCH 1/6] Adjust schemas to match jms and evaluator --- ansys/rep/client/common/__init__.py | 1 + ansys/rep/client/common/any_value.py | 26 +++++++++++++++++ ansys/rep/client/jms/schema/evaluator.py | 28 +++++++++++++++++-- .../rep/client/jms/schema/task_definition.py | 14 +++++++--- 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 ansys/rep/client/common/any_value.py diff --git a/ansys/rep/client/common/__init__.py b/ansys/rep/client/common/__init__.py index b90611d6f..4af347d60 100644 --- a/ansys/rep/client/common/__init__.py +++ b/ansys/rep/client/common/__init__.py @@ -1,2 +1,3 @@ +from .any_value import AnyValue from .base_resource import Object from .base_schema import BaseSchema, ObjectSchema diff --git a/ansys/rep/client/common/any_value.py b/ansys/rep/client/common/any_value.py new file mode 100644 index 000000000..16716b4e2 --- /dev/null +++ b/ansys/rep/client/common/any_value.py @@ -0,0 +1,26 @@ +from marshmallow import fields +from marshmallow.exceptions import ValidationError + + +class AnyValue(fields.Field): + any_fields = [ + fields.Int(strict=True), + fields.Bool(truthy=[True], falsy=[False]), + fields.Str(), + fields.Float(allow_nan=False), + ] + + def __init__(self): + super().__init__(allow_none=True) + + def _deserialize(self, value, attr, obj, **kwargs): + for field in self.any_fields: + try: + return field._deserialize(value, attr, obj, **kwargs) + except: + pass + + self.raise_validation_error() + + def raise_validation_error(): + raise ValidationError("Value must be of type float, integer, boolean, or string") diff --git a/ansys/rep/client/jms/schema/evaluator.py b/ansys/rep/client/jms/schema/evaluator.py index c8724680f..c5ecb5234 100644 --- a/ansys/rep/client/jms/schema/evaluator.py +++ b/ansys/rep/client/jms/schema/evaluator.py @@ -6,10 +6,11 @@ # Author(s): F.Negri # ---------------------------------------------------------- +import marshmallow from marshmallow import fields from marshmallow.validate import OneOf -from ansys.rep.client.common import ObjectSchema +from ansys.rep.client.common import AnyValue, ObjectSchema project_assignment_modes = ["disabled", "all_active", "project_list"] @@ -31,6 +32,28 @@ class Meta: custom_resource_properties = fields.Dict(allow_none=True) +class EvaluatorRegistrationConfigurationContextSchema(marshmallow.Schema): + class Meta: + unknown = marshmallow.INCLUDE + + custom = fields.Dict(allow_none=True, keys=fields.Str(), values=AnyValue()) + + +class EvaluatorRegistrationConfigurationResourcesSchema(marshmallow.Schema): + class Meta: + unknown = marshmallow.INCLUDE + + custom = fields.Dict(allow_none=True, keys=fields.Str(), values=AnyValue()) + + +class EvaluatorRegistrationConfigurationSchema(marshmallow.Schema): + class Meta: + unknown = marshmallow.INCLUDE + + context = fields.Nested(EvaluatorRegistrationConfigurationContextSchema, allow_none=True) + resources = fields.Nested(EvaluatorRegistrationConfigurationResourcesSchema, allow_none=True) + + class EvaluatorSchema(ObjectSchema): class Meta: ordered = True @@ -92,7 +115,8 @@ class Meta: fields.String, metadata={"description": "List of projects on which this evaluator should be working."}, ) - configuration = fields.Dict( + configuration = fields.Nested( + EvaluatorRegistrationConfigurationSchema, allow_none=True, metadata={ "description": "Details of the evaluator configuration, " diff --git a/ansys/rep/client/jms/schema/task_definition.py b/ansys/rep/client/jms/schema/task_definition.py index 0c48a234d..807d08690 100644 --- a/ansys/rep/client/jms/schema/task_definition.py +++ b/ansys/rep/client/jms/schema/task_definition.py @@ -8,7 +8,7 @@ from marshmallow import fields -from ansys.rep.client.common import BaseSchema, ObjectSchema +from ansys.rep.client.common import AnyValue, BaseSchema, ObjectSchema from .object_reference import IdReference, IdReferenceList @@ -31,7 +31,7 @@ class Meta(BaseSchema.Meta): disk_space = fields.Int(allow_none=True) distributed = fields.Bool(allow_none=True) - custom = fields.Dict(allow_none=True) + custom = fields.Dict(allow_none=True, keys=fields.Str(), values=AnyValue()) class SuccessCriteriaSchema(BaseSchema): @@ -98,10 +98,16 @@ class Meta(ObjectSchema.Meta): execution_level = fields.Int(description="Define execution level for this task.") execution_context = fields.Dict( - allow_none=True, description="Additional arguments to pass to the executing command" + allow_none=True, + description="Additional arguments to pass to the executing command", + keys=fields.Str(), + values=AnyValue(), ) environment = fields.Dict( - allow_none=True, description="Environment variables to set for the executed process" + allow_none=True, + description="Environment variables to set for the executed process", + keys=fields.Str(), + values=fields.Str(), ) max_execution_time = fields.Float( allow_none=True, description="Maximum time in seconds for executing the task." From 0725fefe625100ce8c5de97114c714b3754811d0 Mon Sep 17 00:00:00 2001 From: Ryan Wehrle Date: Thu, 25 May 2023 13:08:11 -0400 Subject: [PATCH 2/6] Regenerate resources --- ansys/rep/client/jms/resource/evaluator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansys/rep/client/jms/resource/evaluator.py b/ansys/rep/client/jms/resource/evaluator.py index ba056d0af..c88d24e8e 100644 --- a/ansys/rep/client/jms/resource/evaluator.py +++ b/ansys/rep/client/jms/resource/evaluator.py @@ -85,7 +85,7 @@ class Evaluator(Object): Which strategy to use for selecting projects to work on. project_list : list List of projects on which this evaluator should be working. - configuration : dict, optional + configuration : object, optional Details of the evaluator configuration, including hardware info and available applications. configuration_updates : EvaluatorConfigurationUpdate, optional Changes to the evaluator configurations. From 534d74f9938a7f0af553a5d7874e1c87d82caeea Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Tue, 30 May 2023 14:42:03 +0200 Subject: [PATCH 3/6] Update resource code auto-gen script --- ansys/rep/client/jms/resource/job.py | 4 +- .../client/jms/resource/task_definition.py | 6 +- .../jms/resource/task_definition_template.py | 6 +- generate_resources.py | 88 +++++++++++++------ 4 files changed, 67 insertions(+), 37 deletions(-) diff --git a/ansys/rep/client/jms/resource/job.py b/ansys/rep/client/jms/resource/job.py index 275446797..47cc0feaf 100644 --- a/ansys/rep/client/jms/resource/job.py +++ b/ansys/rep/client/jms/resource/job.py @@ -18,11 +18,11 @@ class Job(Object): ID of the linked job definition, see :class:`JobDefinition`. priority : int, optional Priority with which jobs are evaluated. The default is 0, which is the highest priority. Assigning a higher value to a design point makes it a lower priority. - values : dict, optional + values : dict[str, any], optional Dictionary with (name,value) pairs for all parameters defined in the linked job definition. fitness : float, optional Fitness value computed. - fitness_term_values : dict, optional + fitness_term_values : dict[str, float], optional Dictionary with (name,value) pairs for all fitness terms computed. note : str, optional Optional note for this job. diff --git a/ansys/rep/client/jms/resource/task_definition.py b/ansys/rep/client/jms/resource/task_definition.py index ee2b3dd93..329f13eac 100644 --- a/ansys/rep/client/jms/resource/task_definition.py +++ b/ansys/rep/client/jms/resource/task_definition.py @@ -17,7 +17,7 @@ class ResourceRequirements(Object): cpu_core_usage : float, optional disk_space : int, optional distributed : bool, optional - custom : dict, optional + custom : dict[str, int | float | str | bool], optional """ @@ -154,9 +154,9 @@ class TaskDefinition(Object): Script to execute (command or execution script is required). execution_level : int Define execution level for this task. - execution_context : dict, optional + execution_context : dict[str, int | float | str | bool], optional Additional arguments to pass to the executing command - environment : dict, optional + environment : dict[str, str], optional Environment variables to set for the executed process max_execution_time : float, optional Maximum time in seconds for executing the task. diff --git a/ansys/rep/client/jms/resource/task_definition_template.py b/ansys/rep/client/jms/resource/task_definition_template.py index 4bf892f17..cc94ed4bc 100644 --- a/ansys/rep/client/jms/resource/task_definition_template.py +++ b/ansys/rep/client/jms/resource/task_definition_template.py @@ -52,7 +52,7 @@ class TemplateResourceRequirements(Object): cpu_core_usage : TemplateProperty, optional disk_space : TemplateProperty, optional distributed : TemplateProperty, optional - custom : dict, optional + custom : dict[str, TemplateProperty], optional """ @@ -186,9 +186,9 @@ class TaskDefinitionTemplate(Object): A list of required software. resource_requirements : TemplateResourceRequirements, optional Includes hardware requirements such as number of cores, memory and disk space. - execution_context : dict, optional + execution_context : dict[str, TemplateProperty], optional Additional arguments to pass to the executing command. - environment : dict, optional + environment : dict[str, TemplateProperty], optional Environment variables to set for the executed process. execution_command : str, optional Command to execute (command or execution script is required). diff --git a/generate_resources.py b/generate_resources.py index 7be3545a2..4d2e404d5 100644 --- a/generate_resources.py +++ b/generate_resources.py @@ -9,6 +9,7 @@ import marshmallow +from ansys.rep.client.common.any_value import AnyValue from ansys.rep.client.jms.schema.object_reference import IdReference, IdReferenceList # we define here which resources to auto-generate @@ -287,9 +288,64 @@ marshmallow.fields.Nested: "object", IdReferenceList: "list[str]", IdReference: "str", + AnyValue: "int | float | str | bool", } +def extract_field_info(name: str, field_object: marshmallow.fields, resources): + + field = name + v = field_object + + # Ensure that we use the attribute name if defined + if getattr(v, "attribute", None) is not None: + field = v.attribute + + # build attribute doc + field_doc = f"{field}" + + field_type = _extract_field_type(v, resources) + if field_type: + field_doc += f" : {field_type}" + if v.allow_none: + field_doc += ", optional" + field_doc += "\n" + elif v.allow_none: + field_doc += " : any, optional\n" + desc = v.metadata.get("description", None) + if desc: + field_doc += f" {desc}\n" + + return field, field_doc + + +def _extract_field_type(v, resources) -> str: + + if v.__class__ == marshmallow.fields.Constant: + field_type = type(v.constant).__name__ + elif v.__class__ == marshmallow.fields.Nested: + field_type_schema = v.nested.__name__ + field_type = next( + (r["class"] for r in resources if r["schema"] == field_type_schema), + "object", + ) + else: + field_type = FIELD_MAPPING.get(v.__class__, None) + if field_type: + if v.__class__ == marshmallow.fields.Dict: + if v.key_field: + key_field_type = _extract_field_type(v.key_field, resources) + if v.value_field: + value_field_type = _extract_field_type(v.value_field, resources) + else: + value_field_type = "any" + field_type += f"[{key_field_type}, {value_field_type}]" + if hasattr(v, "many") and v.many == True: + field_type = f"list[{field_type}]" + + return field_type + + def declared_fields(schema, resources): """ Helper function to retrieve the fields that will be defined as class members for an object @@ -297,37 +353,11 @@ def declared_fields(schema, resources): fields = [] fields_doc = [] for k, v in schema._declared_fields.items(): - field = k - # Ensure that we use the attribute name if defined - if getattr(v, "attribute", None) is not None: - field = v.attribute - fields.append(field) - # build attribute doc - field_doc = f"{field}" - if v.__class__ == marshmallow.fields.Constant: - field_type = type(v.constant).__name__ - elif v.__class__ == marshmallow.fields.Nested: - field_type_schema = v.nested.__name__ - field_type = next( - (r["class"] for r in resources if r["schema"] == field_type_schema), - "object", - ) - else: - field_type = FIELD_MAPPING.get(v.__class__, None) - if field_type: - if hasattr(v, "many") and v.many == True: - field_type = f"list[{field_type}]" - field_doc += f" : {field_type}" - if v.allow_none: - field_doc += ", optional" - field_doc += "\n" - elif v.allow_none: - field_doc += " : any, optional\n" - desc = v.metadata.get("description", None) - if desc: - field_doc += f" {desc}\n" + field, field_doc = extract_field_info(k, v, resources) + fields.append(field) fields_doc.append(field_doc) + return fields, fields_doc From 618cbd9ec01d2326ae8620b91b4475aeb379bf56 Mon Sep 17 00:00:00 2001 From: Ryan Wehrle Date: Wed, 31 May 2023 11:57:57 -0400 Subject: [PATCH 4/6] Rename AnyValue to RestrictedValue --- ansys/rep/client/common/__init__.py | 2 +- .../rep/client/common/{any_value.py => restricted_value.py} | 6 +++--- ansys/rep/client/jms/schema/evaluator.py | 6 +++--- ansys/rep/client/jms/schema/task_definition.py | 6 +++--- generate_resources.py | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) rename ansys/rep/client/common/{any_value.py => restricted_value.py} (85%) diff --git a/ansys/rep/client/common/__init__.py b/ansys/rep/client/common/__init__.py index 4af347d60..f145cb6d5 100644 --- a/ansys/rep/client/common/__init__.py +++ b/ansys/rep/client/common/__init__.py @@ -1,3 +1,3 @@ -from .any_value import AnyValue from .base_resource import Object from .base_schema import BaseSchema, ObjectSchema +from .restricted_value import RestrictedValue diff --git a/ansys/rep/client/common/any_value.py b/ansys/rep/client/common/restricted_value.py similarity index 85% rename from ansys/rep/client/common/any_value.py rename to ansys/rep/client/common/restricted_value.py index 16716b4e2..0e9d0c697 100644 --- a/ansys/rep/client/common/any_value.py +++ b/ansys/rep/client/common/restricted_value.py @@ -2,8 +2,8 @@ from marshmallow.exceptions import ValidationError -class AnyValue(fields.Field): - any_fields = [ +class RestrictedValue(fields.Field): + restricted_fields = [ fields.Int(strict=True), fields.Bool(truthy=[True], falsy=[False]), fields.Str(), @@ -14,7 +14,7 @@ def __init__(self): super().__init__(allow_none=True) def _deserialize(self, value, attr, obj, **kwargs): - for field in self.any_fields: + for field in self.restricted_fields: try: return field._deserialize(value, attr, obj, **kwargs) except: diff --git a/ansys/rep/client/jms/schema/evaluator.py b/ansys/rep/client/jms/schema/evaluator.py index c5ecb5234..80f7c74f2 100644 --- a/ansys/rep/client/jms/schema/evaluator.py +++ b/ansys/rep/client/jms/schema/evaluator.py @@ -10,7 +10,7 @@ from marshmallow import fields from marshmallow.validate import OneOf -from ansys.rep.client.common import AnyValue, ObjectSchema +from ansys.rep.client.common import ObjectSchema, RestrictedValue project_assignment_modes = ["disabled", "all_active", "project_list"] @@ -36,14 +36,14 @@ class EvaluatorRegistrationConfigurationContextSchema(marshmallow.Schema): class Meta: unknown = marshmallow.INCLUDE - custom = fields.Dict(allow_none=True, keys=fields.Str(), values=AnyValue()) + custom = fields.Dict(allow_none=True, keys=fields.Str(), values=RestrictedValue()) class EvaluatorRegistrationConfigurationResourcesSchema(marshmallow.Schema): class Meta: unknown = marshmallow.INCLUDE - custom = fields.Dict(allow_none=True, keys=fields.Str(), values=AnyValue()) + custom = fields.Dict(allow_none=True, keys=fields.Str(), values=RestrictedValue()) class EvaluatorRegistrationConfigurationSchema(marshmallow.Schema): diff --git a/ansys/rep/client/jms/schema/task_definition.py b/ansys/rep/client/jms/schema/task_definition.py index 807d08690..f54ef1f07 100644 --- a/ansys/rep/client/jms/schema/task_definition.py +++ b/ansys/rep/client/jms/schema/task_definition.py @@ -8,7 +8,7 @@ from marshmallow import fields -from ansys.rep.client.common import AnyValue, BaseSchema, ObjectSchema +from ansys.rep.client.common import BaseSchema, ObjectSchema, RestrictedValue from .object_reference import IdReference, IdReferenceList @@ -31,7 +31,7 @@ class Meta(BaseSchema.Meta): disk_space = fields.Int(allow_none=True) distributed = fields.Bool(allow_none=True) - custom = fields.Dict(allow_none=True, keys=fields.Str(), values=AnyValue()) + custom = fields.Dict(allow_none=True, keys=fields.Str(), values=RestrictedValue()) class SuccessCriteriaSchema(BaseSchema): @@ -101,7 +101,7 @@ class Meta(ObjectSchema.Meta): allow_none=True, description="Additional arguments to pass to the executing command", keys=fields.Str(), - values=AnyValue(), + values=RestrictedValue(), ) environment = fields.Dict( allow_none=True, diff --git a/generate_resources.py b/generate_resources.py index 4d2e404d5..08154739d 100644 --- a/generate_resources.py +++ b/generate_resources.py @@ -9,7 +9,7 @@ import marshmallow -from ansys.rep.client.common.any_value import AnyValue +from ansys.rep.client.common.restricted_value import RestrictedValue from ansys.rep.client.jms.schema.object_reference import IdReference, IdReferenceList # we define here which resources to auto-generate @@ -288,7 +288,7 @@ marshmallow.fields.Nested: "object", IdReferenceList: "list[str]", IdReference: "str", - AnyValue: "int | float | str | bool", + RestrictedValue: "int | float | str | bool", } From 84751bae97d4e69b8bcef3064ed75e1ea21c74bb Mon Sep 17 00:00:00 2001 From: Ryan Wehrle Date: Wed, 31 May 2023 16:17:08 -0400 Subject: [PATCH 5/6] Created de/serialization tests for task definition --- tests/jms/test_task_definition.py | 237 ++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 tests/jms/test_task_definition.py diff --git a/tests/jms/test_task_definition.py b/tests/jms/test_task_definition.py new file mode 100644 index 000000000..ffc96b96d --- /dev/null +++ b/tests/jms/test_task_definition.py @@ -0,0 +1,237 @@ +from collections import OrderedDict +import unittest + +from ansys.rep.client.jms.resource import TaskDefinition +from ansys.rep.client.jms.resource.task_definition import ( + Licensing, + ResourceRequirements, + SuccessCriteria, +) +from ansys.rep.client.jms.schema.task_definition import TaskDefinitionSchema +from tests.rep_test import REPTestCase + + +class TaskDefinitionTest(REPTestCase): + def test_task_definition_deserialization(self): + + task_def_dict = { + "environment": {"test_env": "test_env_value"}, + "execution_command": "echo 'hello world'", + "execution_context": { + "test_str": "5", + "test_int": 1, + "test_int2": 0, + "test_float": 7.7, + "test_bool": True, + "test_bool2": False, + }, + "execution_level": 0, + "execution_script_id": None, + "id": "1", + "licensing": {"enable_shared_licensing": False}, + "max_execution_time": 50, + "name": "test_task_def", + "num_trials": 1, + "input_file_ids": ["FAKE_FILE_ID"], + "output_file_ids": [ + "FAKE_FILE_ID", + "FAKE_FILE_ID", + "FAKE_FILE_ID", + ], + "resource_requirements": { + "cpu_core_usage": 1, + "disk_space": 5, + "memory": 250, + "custom": { + "test_str": "5", + "test_int": 1, + "test_int2": 0, + "test_float": 7.7, + "test_bool": True, + "test_bool2": False, + }, + }, + "software_requirements": [], + "store_output": True, + "success_criteria": { + "expressions": [], + "require_all_output_files": False, + "require_all_output_parameters": True, + "return_code": 0, + }, + "use_execution_script": False, + } + + task_def = TaskDefinitionSchema().load(task_def_dict) + + self.assertEqual(task_def.name, "test_task_def") + self.assertEqual(task_def.execution_command, "echo 'hello world'") + + self.assertEqual(task_def.use_execution_script, False) + self.assertEqual(task_def.execution_script_id, None) + self.assertEqual(task_def.execution_level, 0) + self.assertEqual( + task_def.execution_context, + { + "test_str": "5", + "test_int": 1, + "test_int2": 0, + "test_float": 7.7, + "test_bool": True, + "test_bool2": False, + }, + ) + self.assertEqual(task_def.environment, {"test_env": "test_env_value"}) + self.assertEqual(task_def.max_execution_time, 50) + self.assertEqual(task_def.num_trials, 1) + self.assertEqual(task_def.store_output, True) + self.assertEqual(task_def.input_file_ids, ["FAKE_FILE_ID"]) + self.assertEqual( + task_def.output_file_ids, + [ + "FAKE_FILE_ID", + "FAKE_FILE_ID", + "FAKE_FILE_ID", + ], + ) + self.assertEqual( + task_def.success_criteria, + SuccessCriteria( + return_code=0, + require_all_output_files=False, + require_all_output_parameters=True, + expressions=[], + ), + ) + self.assertEqual(task_def.licensing, Licensing(enable_shared_licensing=False)) + self.assertEqual(task_def.software_requirements, []) + self.assertEqual( + task_def.resource_requirements, + ResourceRequirements( + cpu_core_usage=1, + disk_space=5, + memory=250, + custom={ + "test_str": "5", + "test_int": 1, + "test_int2": 0, + "test_float": 7.7, + "test_bool": True, + "test_bool2": False, + }, + ), + ) + + def test_task_definition_serialization(self): + + task_def = TaskDefinition( + name="test_task_def", + environment={"test_env": "test_env_value"}, + execution_command="echo 'hello world'", + execution_context={ + "test_str": "5", + "test_int": 1, + "test_int2": 0, + "test_float": 7.7, + "test_bool": True, + "test_bool2": False, + }, + execution_level=0, + id=1, + licensing=Licensing(enable_shared_licensing=False), + max_execution_time=50, + num_trials=1, + input_file_ids=["FAKE_FILE_ID"], + output_file_ids=["FAKE_FILE_ID", "FAKE_FILE_ID", "FAKE_FILE_ID"], + resource_requirements=ResourceRequirements( + cpu_core_usage=1, + disk_space=5, + memory=250, + custom={ + "test_str": "5", + "test_int": 1, + "test_int2": 0, + "test_float": 7.7, + "test_bool": True, + "test_bool2": False, + }, + ), + software_requirements=[], + store_output=True, + success_criteria=SuccessCriteria( + expressions=[], + require_all_output_files=False, + require_all_output_parameters=True, + return_code=0, + ), + use_execution_script=False, + ) + + serialized_task_def = TaskDefinitionSchema().dump(task_def) + + self.assertEqual(serialized_task_def["name"], "test_task_def") + self.assertEqual(serialized_task_def["execution_command"], "echo 'hello world'") + + self.assertEqual(serialized_task_def["use_execution_script"], False) + self.assertEqual(serialized_task_def["execution_level"], 0) + self.assertEqual( + serialized_task_def["execution_context"], + { + "test_str": "5", + "test_int": 1, + "test_int2": 0, + "test_float": 7.7, + "test_bool": True, + "test_bool2": False, + }, + ) + self.assertEqual(serialized_task_def["environment"], {"test_env": "test_env_value"}) + self.assertEqual(serialized_task_def["max_execution_time"], 50) + self.assertEqual(serialized_task_def["num_trials"], 1) + self.assertEqual(serialized_task_def["store_output"], True) + self.assertEqual(serialized_task_def["input_file_ids"], ["FAKE_FILE_ID"]) + self.assertEqual( + serialized_task_def["output_file_ids"], + [ + "FAKE_FILE_ID", + "FAKE_FILE_ID", + "FAKE_FILE_ID", + ], + ) + self.assertEqual( + serialized_task_def["success_criteria"], + OrderedDict( + { + "return_code": 0, + "expressions": [], + "require_all_output_files": False, + "require_all_output_parameters": True, + } + ), + ) + self.assertEqual( + serialized_task_def["licensing"], OrderedDict({"enable_shared_licensing": False}) + ) + self.assertEqual(serialized_task_def["software_requirements"], []) + self.assertEqual( + serialized_task_def["resource_requirements"], + OrderedDict( + { + "memory": 250, + "cpu_core_usage": 1, + "disk_space": 5, + "custom": { + "test_str": "5", + "test_int": 1, + "test_int2": 0, + "test_float": 7.7, + "test_bool": True, + "test_bool2": False, + }, + } + ), + ) + + +if __name__ == "__main__": + unittest.main() From d1f52fcadf5f3caf23acec22b90507c259f3ef53 Mon Sep 17 00:00:00 2001 From: Ryan Wehrle Date: Thu, 1 Jun 2023 09:07:08 -0400 Subject: [PATCH 6/6] Add test cases for none --- tests/jms/test_task_definition.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/jms/test_task_definition.py b/tests/jms/test_task_definition.py index ffc96b96d..7eab9e0d2 100644 --- a/tests/jms/test_task_definition.py +++ b/tests/jms/test_task_definition.py @@ -24,6 +24,7 @@ def test_task_definition_deserialization(self): "test_float": 7.7, "test_bool": True, "test_bool2": False, + "test_none": None, }, "execution_level": 0, "execution_script_id": None, @@ -49,6 +50,7 @@ def test_task_definition_deserialization(self): "test_float": 7.7, "test_bool": True, "test_bool2": False, + "test_none": None, }, }, "software_requirements": [], @@ -79,6 +81,7 @@ def test_task_definition_deserialization(self): "test_float": 7.7, "test_bool": True, "test_bool2": False, + "test_none": None, }, ) self.assertEqual(task_def.environment, {"test_env": "test_env_value"}) @@ -118,6 +121,7 @@ def test_task_definition_deserialization(self): "test_float": 7.7, "test_bool": True, "test_bool2": False, + "test_none": None, }, ), ) @@ -135,6 +139,7 @@ def test_task_definition_serialization(self): "test_float": 7.7, "test_bool": True, "test_bool2": False, + "test_none": None, }, execution_level=0, id=1, @@ -154,6 +159,7 @@ def test_task_definition_serialization(self): "test_float": 7.7, "test_bool": True, "test_bool2": False, + "test_none": None, }, ), software_requirements=[], @@ -183,6 +189,7 @@ def test_task_definition_serialization(self): "test_float": 7.7, "test_bool": True, "test_bool2": False, + "test_none": None, }, ) self.assertEqual(serialized_task_def["environment"], {"test_env": "test_env_value"}) @@ -227,6 +234,7 @@ def test_task_definition_serialization(self): "test_float": 7.7, "test_bool": True, "test_bool2": False, + "test_none": None, }, } ),