From bc2322f743bb0276e4397b3be4bbccd3f60b57a3 Mon Sep 17 00:00:00 2001 From: Evan Tung Date: Fri, 22 Mar 2024 21:53:59 -0400 Subject: [PATCH 1/6] Update config file specification format --- .gitignore | 1 + onair/config/default_config.ini | 34 +- onair/config/redis_example.ini | 15 +- onair/config/reporter_config.ini | 19 +- onair/src/run_scripts/execution_engine.py | 54 +- .../src/run_scripts/test_execution_engine.py | 464 ++++++++++++------ 6 files changed, 373 insertions(+), 214 deletions(-) diff --git a/.gitignore b/.gitignore index 4850dd31..3d0969cd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .DS_Store __pycache__/ .coverage +.vscode/ \ No newline at end of file diff --git a/onair/config/default_config.ini b/onair/config/default_config.ini index 81a4f518..c107ab0c 100644 --- a/onair/config/default_config.ini +++ b/onair/config/default_config.ini @@ -1,18 +1,22 @@ -# Required Section: DEFAULT section is the basic required elements for running OnAIR -[DEFAULT] -# Required Key: TelemetryDataFilePath is the path for TelemetryFile -TelemetryDataFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors -# Required Key: TelemetryDataFile is a file used by the selected parser -# NOTE: TelemetryDataFile is required even when selected parser does not use it +# Required Section: FILES section contains the paths of required files for running OnAIR +[FILES] +# Required Key: TelemetryFilePath is the directory of TelemetryFile +TelemetryFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors +# Required Key: TelemetryFile is the file read by the selected parser +# NOTE: TelemetryFile is required even when selected parser does not use it TelemetryFile = 700_crash_to_earth_1.csv -# Required Key: TelemetryMetadataFilePath is the path for TelemetryMetadataFilePath -TelemetryMetadataFilePath = onair/data/telemetry_configs/ +# Required Key: MetaFilePath is the directory of MetaFile +MetaFilePath = onair/data/telemetry_configs/ # Required Key: MetaFile describes frame composition of data MetaFile = data_physics_generation_CONFIG.json -# Required Key: ParserFileName is the name of the parser DataSource object to use -ParserFileName = onair/data_handling/csv_parser.py -# Plugins +# Required Section: DATA_HANDLING section specifies which data source parser to use +[DATA_HANDLING] +# Required Key: DataSourceFile is the name of the parser DataSource object to use +DataSourceFile = onair/data_handling/csv_parser.py + +# Required Section: PLUGINS section contains the plugins wanted for OnAIR to run +[PLUGINS] # NOTE: even though keys are required, they may be set to empty dicts # Required Key: KnowledgeRepPluginDict(s) are used by the VehicleRep KnowledgeRepPluginDict = {'generic':'plugins/generic/__init__.py'} @@ -23,8 +27,8 @@ PlannersPluginDict = {'generic':'plugins/generic/__init__.py'} # Required Key: ComplexPluginDict(s) are used by Agent for complex reasoning ComplexPluginDict = {'generic':'plugins/generic/__init__.py'} -# Required Section: RUN_FLAGS are settable values to change running experience -[RUN_FLAGS] +# Required Section: OPTIONS are settable values to change running experience +[OPTIONS] # Optional Key: IO_Flag denotes whether or not to provide console output -# IO_Flag defaults to false when not provided -IO_Flag = true +# default = false +IO_Enabled = true diff --git a/onair/config/redis_example.ini b/onair/config/redis_example.ini index 773624df..d7e95f3c 100644 --- a/onair/config/redis_example.ini +++ b/onair/config/redis_example.ini @@ -1,14 +1,17 @@ -[DEFAULT] -TelemetryDataFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors +[FILES] +TelemetryFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors TelemetryFile = 700_crash_to_earth_1.csv -TelemetryMetadataFilePath = onair/data/telemetry_configs/ +MetaFilePath = onair/data/telemetry_configs/ MetaFile = data_physics_generation_CONFIG.json -ParserFileName = onair/data_handling/redis_adapter.py +[DATA_HANDLING] +DataSourceFile = onair/data_handling/redis_adapter.py + +[PLUGINS] KnowledgeRepPluginDict = {'generic':'plugins/generic/__init__.py'} LearnersPluginDict = {'generic':'plugins/generic/__init__.py'} PlannersPluginDict = {'generic':'plugins/generic/__init__.py'} ComplexPluginDict = {'generic':'plugins/generic/__init__.py'} -[RUN_FLAGS] -IO_Flag = true +[OPTIONS] +IO_Enabled = true diff --git a/onair/config/reporter_config.ini b/onair/config/reporter_config.ini index 539af535..65b3a9bc 100644 --- a/onair/config/reporter_config.ini +++ b/onair/config/reporter_config.ini @@ -1,10 +1,13 @@ -[DEFAULT] -TelemetryDataFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors +[FILES] +TelemetryFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors TelemetryFile = 700_crash_to_earth_1.csv -TelemetryMetadataFilePath = onair/data/telemetry_configs/ +MetaFilePath = onair/data/telemetry_configs/ MetaFile = data_physics_generation_CONFIG.json -ParserFileName = onair/data_handling/csv_parser.py +[DATA_HANDLING] +DataSourceFile = onair/data_handling/csv_parser.py + +[PLUGINS] KnowledgeRepPluginDict = {'Knowledge Reporter 1':'plugins/reporter', 'Knowledge Reporter 2':'plugins/reporter'} LearnersPluginDict = {'Learners Reporter 1':'plugins/reporter', @@ -14,7 +17,7 @@ PlannersPluginDict = {'Planner Reporter 1':'plugins/reporter', ComplexPluginDict = {'Complex Reporter 1':'plugins/reporter', 'Complex Reporter 2':'plugins/reporter'} -[RUN_FLAGS] -IO_Flag = true -Dev_Flag = false -Viz_Flag = false +[OPTIONS] +IO_Enabled = true +Dev_Enabled = false +Viz_Enabled = false diff --git a/onair/src/run_scripts/execution_engine.py b/onair/src/run_scripts/execution_engine.py index d0d5257d..a9879d3f 100644 --- a/onair/src/run_scripts/execution_engine.py +++ b/onair/src/run_scripts/execution_engine.py @@ -28,19 +28,19 @@ def __init__(self, config_file='', run_name='', save_flag=False): self.run_name = run_name self.config_filepath = config_file - # Init Flags - self.IO_Flag = False + # Init Options + self.IO_Enabled = False # Init Paths self.dataFilePath = '' self.telemetryFile = '' - self.fullTelemetryFileName = '' + self.fullTelemetryFile = '' self.metadataFilePath = '' self.metaFile = '' - self.fullMetaDataFileName = '' + self.fullMetaFile = '' # Init parsing/sim info - self.parser_file_name = '' + self.data_source_file = '' self.simDataSource = None self.sim = None @@ -56,7 +56,7 @@ def __init__(self, config_file='', run_name='', save_flag=False): if config_file != '': self.init_save_paths() self.parse_configs(config_file) - self.parse_data(self.parser_file_name, self.fullTelemetryFileName, self.fullMetaDataFileName) + self.parse_data(self.data_source_file, self.fullTelemetryFile, self.fullMetaFile) self.setup_sim() def parse_configs(self, config_filepath): @@ -66,26 +66,26 @@ def parse_configs(self, config_filepath): raise FileNotFoundError(f"Config file at '{config_filepath}' could not be read.") try: - ## Parse Required Data: Telementry Data & Configuration - self.dataFilePath = config['DEFAULT']['TelemetryDataFilePath'] - self.telemetryFile = config['DEFAULT']['TelemetryFile'] # Vehicle telemetry data - self.fullTelemetryFileName = os.path.join(self.dataFilePath, self.telemetryFile) - self.metadataFilePath = config['DEFAULT']['TelemetryMetadataFilePath'] - self.metaFile = config['DEFAULT']['MetaFile'] # Config for vehicle telemetry - self.fullMetaDataFileName = os.path.join(self.metadataFilePath, self.metaFile) - - ## Parse Required Data: Names - self.parser_file_name = config['DEFAULT']['ParserFileName'] - - ## Parse Required Data: Plugins - self.knowledge_rep_plugin_dict = self.parse_plugins_dict(config['DEFAULT']['KnowledgeRepPluginDict']) - self.learners_plugin_dict = self.parse_plugins_dict(config['DEFAULT']['LearnersPluginDict']) - self.planners_plugin_dict = self.parse_plugins_dict(config['DEFAULT']['PlannersPluginDict']) - self.complex_plugin_dict = self.parse_plugins_dict(config['DEFAULT']['ComplexPluginDict']) - - ## Parse Optional Data: Flags - ## 'RUN_FLAGS' must exist, but individual flags return False if missing - self.IO_Flag = config['RUN_FLAGS'].getboolean('IO_Flag') + ## Parse Required Data: FILES + self.dataFilePath = config['FILES']['TelemetryFilePath'] + self.telemetryFile = config['FILES']['TelemetryFile'] # Vehicle telemetry data + self.fullTelemetryFile = os.path.join(self.dataFilePath, self.telemetryFile) + self.metadataFilePath = config['FILES']['MetaFilePath'] + self.metaFile = config['FILES']['MetaFile'] # Config for vehicle telemetry + self.fullMetaFile = os.path.join(self.metadataFilePath, self.metaFile) + + ## Parse Required Data: DATA_HANDLING + self.data_source_file = config['DATA_HANDLING']['DataSourceFile'] + + ## Parse Required Data: PLUGINS + self.knowledge_rep_plugin_dict = self.parse_plugins_dict(config['PLUGINS']['KnowledgeRepPluginDict']) + self.learners_plugin_dict = self.parse_plugins_dict(config['PLUGINS']['LearnersPluginDict']) + self.planners_plugin_dict = self.parse_plugins_dict(config['PLUGINS']['PlannersPluginDict']) + self.complex_plugin_dict = self.parse_plugins_dict(config['PLUGINS']['ComplexPluginDict']) + + ## Parse Optional Data: OPTIONS + ## 'OPTIONS' must exist, but individual options return False if missing + self.IO_Enabled = config['OPTIONS'].getboolean('IO_Enabled') except KeyError as e: new_message = f"Config file: '{config_filepath}', missing key: {e.args[0]}" @@ -118,7 +118,7 @@ def setup_sim(self): self.complex_plugin_dict) def run_sim(self): - self.sim.run_sim(self.IO_Flag) + self.sim.run_sim(self.IO_Enabled) if self.save_flag: self.save_results(self.save_name) diff --git a/test/onair/src/run_scripts/test_execution_engine.py b/test/onair/src/run_scripts/test_execution_engine.py index daa3559a..74eeb9c7 100644 --- a/test/onair/src/run_scripts/test_execution_engine.py +++ b/test/onair/src/run_scripts/test_execution_engine.py @@ -15,6 +15,8 @@ from onair.src.run_scripts.execution_engine import ExecutionEngine # __init__ tests + + def test_ExecutionEngine__init__sets_expected_values_but_does_no_calls_when_config_file_is_empty_string(mocker): # Arrange arg_config_file = '' @@ -33,14 +35,14 @@ def test_ExecutionEngine__init__sets_expected_values_but_does_no_calls_when_conf # Assert assert cut.run_name == arg_run_name - assert cut.IO_Flag == False + assert cut.IO_Enabled == False assert cut.dataFilePath == '' assert cut.telemetryFile == '' - assert cut.fullTelemetryFileName == '' + assert cut.fullTelemetryFile == '' assert cut.metadataFilePath == '' assert cut.metaFile == '' - assert cut.fullMetaDataFileName == '' - assert cut.parser_file_name == '' + assert cut.fullMetaFile == '' + assert cut.data_source_file == '' assert cut.simDataSource == None assert cut.sim == None assert cut.save_flag == arg_save_flag @@ -50,6 +52,7 @@ def test_ExecutionEngine__init__sets_expected_values_but_does_no_calls_when_conf assert cut.parse_data.call_count == 0 assert cut.setup_sim.call_count == 0 + def test_ExecutionEngine__init__does_calls_when_config_file_is_an_occupied_string(mocker): # Arrange arg_config_file = str(MagicMock()) @@ -71,9 +74,11 @@ def test_ExecutionEngine__init__does_calls_when_config_file_is_an_occupied_strin assert cut.parse_configs.call_count == 1 assert cut.parse_configs.call_args_list[0].args == (arg_config_file, ) assert cut.parse_data.call_count == 1 - assert cut.parse_data.call_args_list[0].args == (cut.parser_file_name, cut.dataFilePath, cut.metadataFilePath, ) + assert cut.parse_data.call_args_list[0].args == ( + cut.data_source_file, cut.dataFilePath, cut.metadataFilePath, ) assert cut.setup_sim.call_count == 1 + def test_ExecutionEngine__init__accepts_no_arguments_using_defaults_instead_with_config_file_default_as_empty_string(mocker): # Arrange cut = ExecutionEngine.__new__(ExecutionEngine) @@ -93,6 +98,8 @@ def test_ExecutionEngine__init__accepts_no_arguments_using_defaults_instead_with assert cut.init_save_paths.call_count == 0 # parse_configs tests + + def test_ExecutionEngine_parse_configs_raises_FileNotFoundError_when_config_cannot_be_read(mocker): # Arrange arg_bad_config_filepath = MagicMock() @@ -103,23 +110,30 @@ def test_ExecutionEngine_parse_configs_raises_FileNotFoundError_when_config_cann cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) - mocker.patch.object(fake_config, 'read', return_value=fake_config_read_result) + mocker.patch(execution_engine.__name__ + + '.configparser.ConfigParser', return_value=fake_config) + mocker.patch.object(fake_config, 'read', + return_value=fake_config_read_result) # Act with pytest.raises(FileNotFoundError) as e_info: cut.parse_configs(arg_bad_config_filepath) # Assert - assert e_info.match(f"Config file at '{arg_bad_config_filepath}' could not be read.") + assert e_info.match(f"Config file at '{ + arg_bad_config_filepath}' could not be read.") + -def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_when_the_required_key_DEFAULT_is_not_in_config(mocker): +def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_when_the_required_key_FILES_is_not_in_config(mocker): # Arrange arg_config_filepath = MagicMock() - missing_key = 'DEFAULT' - fake_run_flags = MagicMock() - fake_dict_for_Config = {'RUN_FLAGS':fake_run_flags} + missing_key = 'FILES' + fake_dict_for_Config = { + "DATA_HANDLING": MagicMock(), + "PLUGINS": MagicMock(), + "OPTIONS": MagicMock() + } fake_config = MagicMock() fake_config.__getitem__.side_effect = fake_dict_for_Config.__getitem__ fake_config_read_result = MagicMock() @@ -127,8 +141,10 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) - mocker.patch.object(fake_config, 'read', return_value=fake_config_read_result) + mocker.patch(execution_engine.__name__ + + '.configparser.ConfigParser', return_value=fake_config) + mocker.patch.object(fake_config, 'read', + return_value=fake_config_read_result) mocker.patch.object(cut, 'parse_plugins_dict', return_value=None) # Act @@ -136,27 +152,39 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe cut.parse_configs(arg_config_filepath) # Assert - assert e_info.match(f"Config file: '{arg_config_filepath}', missing key: {missing_key}") + assert e_info.match( + f"Config file: '{arg_config_filepath}', missing key: {missing_key}") + -def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_when_a_required_DEFAULT_subkey_is_not_in_config(mocker): +def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_when_a_required_FILES_subkey_is_not_in_config(mocker): # Arrange arg_config_filepath = MagicMock() - fake_default = {'TelemetryDataFilePath':MagicMock(), - 'TelemetryFile':MagicMock(), - 'TelemetryMetadataFilePath':MagicMock(), - 'MetaFile':MagicMock(), - 'ParserFileName':MagicMock(), - 'KnowledgeRepPluginDict':"{fake_name:fake_path}", - 'LearnersPluginDict':"{fake_name:fake_path}", - 'PlannersPluginDict':"{fake_name:fake_path}", - 'ComplexPluginDict':"{fake_name:fake_path}" - } - required_keys = [item for item in list(fake_default.keys())] + fake_files = { + 'TelemetryFilePath': MagicMock(), + 'TelemetryFile': MagicMock(), + 'MetaFilePath': MagicMock(), + 'MetaFile': MagicMock() + } + fake_data_handling = { + 'DataSourceFile': MagicMock() + } + fake_plugins = { + 'KnowledgeRepPluginDict': "{fake_name:fake_path}", + 'LearnersPluginDict': "{fake_name:fake_path}", + 'PlannersPluginDict': "{fake_name:fake_path}", + 'ComplexPluginDict': "{fake_name:fake_path}" + } + required_keys = [item for item in list(fake_files.keys())] missing_key = pytest.gen.choice(required_keys) - del fake_default[missing_key] - fake_run_flags = MagicMock() - fake_dict_for_Config = {'DEFAULT':fake_default, 'RUN_FLAGS':fake_run_flags} + del fake_files[missing_key] + fake_options = MagicMock() + fake_dict_for_Config = { + "FILES": fake_files, + "DATA_HANDLING": fake_data_handling, + "PLUGINS": fake_plugins, + "OPTIONS": fake_options + } fake_config = MagicMock() fake_config.__getitem__.side_effect = fake_dict_for_Config.__getitem__ fake_config_read_result = MagicMock() @@ -164,8 +192,10 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) - mocker.patch.object(fake_config, 'read', return_value=fake_config_read_result) + mocker.patch(execution_engine.__name__ + + '.configparser.ConfigParser', return_value=fake_config) + mocker.patch.object(fake_config, 'read', + return_value=fake_config_read_result) mocker.patch.object(cut, 'parse_plugins_dict', return_value=None) # Act @@ -173,15 +203,20 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe cut.parse_configs(arg_config_filepath) # Assert - assert e_info.match(f"Config file: '{arg_config_filepath}', missing key: {missing_key}") + assert e_info.match( + f"Config file: '{arg_config_filepath}', missing key: {missing_key}") -def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_when_the_required_key_RUN_FLAGS_is_not_in_config(mocker): + +def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_when_the_required_key_OPTIONS_is_not_in_config(mocker): # Arrange arg_config_filepath = MagicMock() - fake_default = MagicMock() - missing_key = 'RUN_FLAGS' - fake_dict_for_Config = {'DEFAULT':fake_default} + missing_key = 'OPTIONS' + fake_dict_for_Config = { + "FILES": MagicMock(), + "DATA_HANDLING": MagicMock(), + "PLUGINS": MagicMock() + } fake_config = MagicMock() fake_config.__getitem__.side_effect = fake_dict_for_Config.__getitem__ fake_config_read_result = MagicMock() @@ -189,8 +224,10 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) - mocker.patch.object(fake_config, 'read', return_value=fake_config_read_result) + mocker.patch(execution_engine.__name__ + + '.configparser.ConfigParser', return_value=fake_config) + mocker.patch.object(fake_config, 'read', + return_value=fake_config_read_result) mocker.patch.object(cut, 'parse_plugins_dict', return_value=None) # Act @@ -198,28 +235,39 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe cut.parse_configs(arg_config_filepath) # Assert - assert e_info.match(f"Config file: '{arg_config_filepath}', missing key: {missing_key}") + assert e_info.match( + f"Config file: '{arg_config_filepath}', missing key: {missing_key}") + def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): # Arrange arg_config_filepath = MagicMock() - - fake_default = {'TelemetryDataFilePath':MagicMock(), - 'TelemetryFile':MagicMock(), - 'TelemetryMetadataFilePath':MagicMock(), - 'MetaFile':MagicMock(), - 'ParserFileName':MagicMock(), - 'KnowledgeRepPluginDict':"{fake_name:fake_path}", - 'LearnersPluginDict':"{fake_name:fake_path}", - 'PlannersPluginDict':"{fake_name:fake_path}", - 'ComplexPluginDict':"{fake_name:fake_path}" - } - fake_run_flags = MagicMock() + fake_files = { + 'TelemetryFilePath': MagicMock(), + 'TelemetryFile': MagicMock(), + 'MetaFilePath': MagicMock(), + 'MetaFile': MagicMock() + } + fake_data_handling = { + 'DataSourceFile': MagicMock() + } + fake_plugins = { + 'KnowledgeRepPluginDict': "{fake_name:fake_path}", + 'LearnersPluginDict': "{fake_name:fake_path}", + 'PlannersPluginDict': "{fake_name:fake_path}", + 'ComplexPluginDict': "{fake_name:fake_path}" + } + fake_options = MagicMock() fake_plugin_dict = MagicMock() fake_plugin_dict.body = MagicMock() fake_plugin_dict.body.keys = MagicMock() fake_plugin_dict.body.keys.__len__.return_value = 1 - fake_dict_for_Config = {'DEFAULT':fake_default, 'RUN_FLAGS':fake_run_flags} + fake_dict_for_Config = { + "FILES": fake_files, + "DATA_HANDLING": fake_data_handling, + "PLUGINS": fake_plugins, + "OPTIONS": fake_options + } fake_config = MagicMock() fake_config.__getitem__.side_effect = fake_dict_for_Config.__getitem__ fake_config_read_result = MagicMock() @@ -232,10 +280,10 @@ def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): fake_learners_plugin_list, fake_planners_plugin_list, fake_complex_plugin_list] - fake_IO_flags = MagicMock() - fake_Dev_flags = MagicMock() - fake_Viz_flags = MagicMock() - fake_plugin_dict= MagicMock() + fake_IO_enabled = MagicMock() + fake_Dev_enabled = MagicMock() + fake_Viz_enabled = MagicMock() + fake_plugin_dict = MagicMock() fake_keys = MagicMock() fake_plugin = MagicMock() fake_path = MagicMock() @@ -245,14 +293,19 @@ def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) - mocker.patch.object(fake_config, 'read', return_value=fake_config_read_result) + mocker.patch(execution_engine.__name__ + + '.configparser.ConfigParser', return_value=fake_config) + mocker.patch.object(fake_config, 'read', + return_value=fake_config_read_result) mocker.patch.object(cut, 'parse_plugins_dict', side_effect=fake_plugins) - mocker.patch.object(fake_run_flags, 'getboolean', return_value=fake_IO_flags) + mocker.patch.object(fake_options, 'getboolean', + return_value=fake_IO_enabled) mocker.patch(execution_engine.__name__ + '.isinstance', return_value=True) - mocker.patch(execution_engine.__name__ + '.os.path.exists', return_value=True) + mocker.patch(execution_engine.__name__ + + '.os.path.exists', return_value=True) mocker.patch.object(fake_plugin_dict, 'keys', return_value=fake_keys) - mocker.patch.object(fake_plugin_dict, '__getitem__', return_value=fake_path) + mocker.patch.object(fake_plugin_dict, '__getitem__', + return_value=fake_path) # Act cut.parse_configs(arg_config_filepath) @@ -260,22 +313,23 @@ def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): # Assert assert execution_engine.configparser.ConfigParser.call_count == 1 assert fake_config.read.call_count == 1 - assert cut.dataFilePath == fake_default['TelemetryDataFilePath'] - assert cut.telemetryFile == fake_default['TelemetryFile'] - assert cut.metadataFilePath == fake_default['TelemetryMetadataFilePath'] - assert cut.metaFile == fake_default['MetaFile'] - assert cut.parser_file_name == fake_default['ParserFileName'] + assert cut.dataFilePath == fake_files['TelemetryFilePath'] + assert cut.telemetryFile == fake_files['TelemetryFile'] + assert cut.metadataFilePath == fake_files['MetaFilePath'] + assert cut.metaFile == fake_files['MetaFile'] + assert cut.data_source_file == fake_data_handling['DataSourceFile'] assert cut.parse_plugins_dict.call_count == 4 assert cut.knowledge_rep_plugin_dict == fake_knowledge_rep_plugin_list assert cut.learners_plugin_dict == fake_learners_plugin_list assert cut.planners_plugin_dict == fake_planners_plugin_list assert cut.complex_plugin_dict == fake_complex_plugin_list - assert fake_run_flags.getboolean.call_count == 1 - assert fake_run_flags.getboolean.call_args_list[0].args == ('IO_Flag', ) - assert cut.IO_Flag == fake_IO_flags + assert fake_options.getboolean.call_count == 1 + assert fake_options.getboolean.call_args_list[0].args == ('IO_Enabled', ) + assert cut.IO_Enabled == fake_IO_enabled # parse_plugins_dict + def test_ExecutionEngine_parse_plugins_list_raises_ValueError_when_config_plugin_dict_is_not_dict(mocker): # Arrange arg_config_plugin_dict = MagicMock() @@ -295,11 +349,15 @@ def test_ExecutionEngine_parse_plugins_list_raises_ValueError_when_config_plugin cut.parse_plugins_dict(arg_config_plugin_dict) # Assert - assert e_info.match(f"Plugin dict {arg_config_plugin_dict} from {fake_config_filepath} is invalid. It must be a dict.") + assert e_info.match(f"Plugin dict {arg_config_plugin_dict} from { + fake_config_filepath} is invalid. It must be a dict.") assert cut.ast_parse_eval.call_count == 1 - assert cut.ast_parse_eval.call_args_list[0].args == (arg_config_plugin_dict,) + assert cut.ast_parse_eval.call_args_list[0].args == ( + arg_config_plugin_dict,) assert execution_engine.isinstance.call_count == 1 - assert execution_engine.isinstance.call_args_list[0].args == (fake_plugin_dict.body, execution_engine.ast.Dict, ) + assert execution_engine.isinstance.call_args_list[0].args == ( + fake_plugin_dict.body, execution_engine.ast.Dict, ) + def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_single_config_plugin_dict_key_maps_to_non_existing_file(mocker): # Arrange @@ -319,26 +377,35 @@ def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_single mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) mocker.patch(execution_engine.__name__ + '.isinstance', return_value=True) - mocker.patch(execution_engine.__name__ + '.ast.literal_eval', return_value=fake_temp_plugin_dict) - mocker.patch.object(fake_temp_plugin_dict, 'values', return_value=fake_values) - mocker.patch(execution_engine.__name__ + '.os.path.exists', return_value=False) + mocker.patch(execution_engine.__name__ + '.ast.literal_eval', + return_value=fake_temp_plugin_dict) + mocker.patch.object(fake_temp_plugin_dict, 'values', + return_value=fake_values) + mocker.patch(execution_engine.__name__ + + '.os.path.exists', return_value=False) # Act with pytest.raises(FileNotFoundError) as e_info: cut.parse_plugins_dict(arg_config_plugin_dict) # Assert - assert e_info.match(f"In config file '{fake_config_filepath}' Plugin path '{fake_path}' does not exist.") + assert e_info.match(f"In config file '{fake_config_filepath}' Plugin path '{ + fake_path}' does not exist.") assert cut.ast_parse_eval.call_count == 1 - assert cut.ast_parse_eval.call_args_list[0].args == (arg_config_plugin_dict,) + assert cut.ast_parse_eval.call_args_list[0].args == ( + arg_config_plugin_dict,) assert execution_engine.isinstance.call_count == 1 - assert execution_engine.isinstance.call_args_list[0].args == (fake_plugin_dict.body, execution_engine.ast.Dict, ) + assert execution_engine.isinstance.call_args_list[0].args == ( + fake_plugin_dict.body, execution_engine.ast.Dict, ) assert execution_engine.ast.literal_eval.call_count == 1 - assert execution_engine.ast.literal_eval.call_args_list[0].args == (arg_config_plugin_dict, ) + assert execution_engine.ast.literal_eval.call_args_list[0].args == ( + arg_config_plugin_dict, ) assert fake_temp_plugin_dict.values.call_count == 1 assert fake_temp_plugin_dict.values.call_args_list[0].args == () assert execution_engine.os.path.exists.call_count == 1 - assert execution_engine.os.path.exists.call_args_list[0].args == (fake_path, ) + assert execution_engine.os.path.exists.call_args_list[0].args == ( + fake_path, ) + def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_any_config_plugin_dict_key_maps_to_non_existing_file(mocker): # Arrange @@ -350,40 +417,50 @@ def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_any_co fake_temp_plugin_dict = MagicMock() fake_values = MagicMock() fake_path = MagicMock() - num_fake_items = pytest.gen.randint(2, 10) # from 2 to 10 arbitrary, 1 has own test - num_fake_existing_files = pytest.gen.randint(1, num_fake_items-1) # + # from 2 to 10 arbitrary, 1 has own test + num_fake_items = pytest.gen.randint(2, 10) + num_fake_existing_files = pytest.gen.randint(1, num_fake_items-1) exists_side_effects = [True] * num_fake_existing_files exists_side_effects.append(False) fake_values.__iter__.return_value = iter([fake_path] * num_fake_items) - cut = ExecutionEngine.__new__(ExecutionEngine) cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) mocker.patch(execution_engine.__name__ + '.isinstance', return_value=True) - mocker.patch(execution_engine.__name__ + '.ast.literal_eval', return_value=fake_temp_plugin_dict) - mocker.patch.object(fake_temp_plugin_dict, 'values', return_value=fake_values) - mocker.patch(execution_engine.__name__ + '.os.path.exists', side_effect=exists_side_effects) + mocker.patch(execution_engine.__name__ + '.ast.literal_eval', + return_value=fake_temp_plugin_dict) + mocker.patch.object(fake_temp_plugin_dict, 'values', + return_value=fake_values) + mocker.patch(execution_engine.__name__ + '.os.path.exists', + side_effect=exists_side_effects) # Act with pytest.raises(FileNotFoundError) as e_info: cut.parse_plugins_dict(arg_config_plugin_dict) # Assert - assert e_info.match(f"In config file '{fake_config_filepath}' Plugin path '{fake_path}' does not exist.") + assert e_info.match(f"In config file '{fake_config_filepath}' Plugin path '{ + fake_path}' does not exist.") assert cut.ast_parse_eval.call_count == 1 - assert cut.ast_parse_eval.call_args_list[0].args == (arg_config_plugin_dict,) + assert cut.ast_parse_eval.call_args_list[0].args == ( + arg_config_plugin_dict,) assert execution_engine.isinstance.call_count == 1 - assert execution_engine.isinstance.call_args_list[0].args == (fake_plugin_dict.body, execution_engine.ast.Dict, ) + assert execution_engine.isinstance.call_args_list[0].args == ( + fake_plugin_dict.body, execution_engine.ast.Dict, ) assert execution_engine.ast.literal_eval.call_count == 1 - assert execution_engine.ast.literal_eval.call_args_list[0].args == (arg_config_plugin_dict, ) + assert execution_engine.ast.literal_eval.call_args_list[0].args == ( + arg_config_plugin_dict, ) assert fake_temp_plugin_dict.values.call_count == 1 assert fake_temp_plugin_dict.values.call_args_list[0].args == () - assert execution_engine.os.path.exists.call_count == len(exists_side_effects) + assert execution_engine.os.path.exists.call_count == len( + exists_side_effects) for i in range(len(exists_side_effects)): - assert execution_engine.os.path.exists.call_args_list[i].args == (fake_path, ) + assert execution_engine.os.path.exists.call_args_list[i].args == ( + fake_path, ) + def test_ExecutionEngine_returns_empty_dict_when_config_dict_is_empty(mocker): # Arrange @@ -399,7 +476,8 @@ def test_ExecutionEngine_returns_empty_dict_when_config_dict_is_empty(mocker): mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) mocker.patch(execution_engine.__name__ + '.isinstance', return_value=True) - mocker.patch(execution_engine.__name__ + '.ast.literal_eval', return_value=fake_temp_plugin_dict) + mocker.patch(execution_engine.__name__ + '.ast.literal_eval', + return_value=fake_temp_plugin_dict) # Act result = cut.parse_plugins_dict(arg_config_plugin_dict) @@ -407,11 +485,15 @@ def test_ExecutionEngine_returns_empty_dict_when_config_dict_is_empty(mocker): # Assert assert result == {} assert cut.ast_parse_eval.call_count == 1 - assert cut.ast_parse_eval.call_args_list[0].args == (arg_config_plugin_dict,) + assert cut.ast_parse_eval.call_args_list[0].args == ( + arg_config_plugin_dict,) assert execution_engine.isinstance.call_count == 1 - assert execution_engine.isinstance.call_args_list[0].args == (fake_plugin_dict.body, execution_engine.ast.Dict, ) + assert execution_engine.isinstance.call_args_list[0].args == ( + fake_plugin_dict.body, execution_engine.ast.Dict, ) assert execution_engine.ast.literal_eval.call_count == 1 - assert execution_engine.ast.literal_eval.call_args_list[0].args == (arg_config_plugin_dict, ) + assert execution_engine.ast.literal_eval.call_args_list[0].args == ( + arg_config_plugin_dict, ) + def test_ExecutionEngine_returns_expected_dict_when_all_mapped_files_exist(mocker): # Arrange @@ -423,7 +505,8 @@ def test_ExecutionEngine_returns_expected_dict_when_all_mapped_files_exist(mocke fake_temp_plugin_dict = MagicMock() fake_values = MagicMock() fake_path = MagicMock() - num_fake_items = pytest.gen.randint(1, 10) # from 2 to 10 arbitrary, 0 has own test + # from 2 to 10 arbitrary, 0 has own test + num_fake_items = pytest.gen.randint(1, 10) exists_side_effects = [True] * num_fake_items fake_values.__iter__.return_value = iter([fake_path] * num_fake_items) @@ -433,9 +516,12 @@ def test_ExecutionEngine_returns_expected_dict_when_all_mapped_files_exist(mocke mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) mocker.patch(execution_engine.__name__ + '.isinstance', return_value=True) - mocker.patch(execution_engine.__name__ + '.ast.literal_eval', return_value=fake_temp_plugin_dict) - mocker.patch.object(fake_temp_plugin_dict, 'values', return_value=fake_values) - mocker.patch(execution_engine.__name__ + '.os.path.exists', side_effect=exists_side_effects) + mocker.patch(execution_engine.__name__ + '.ast.literal_eval', + return_value=fake_temp_plugin_dict) + mocker.patch.object(fake_temp_plugin_dict, 'values', + return_value=fake_values) + mocker.patch(execution_engine.__name__ + '.os.path.exists', + side_effect=exists_side_effects) # Act result = cut.parse_plugins_dict(arg_config_plugin_dict) @@ -443,18 +529,25 @@ def test_ExecutionEngine_returns_expected_dict_when_all_mapped_files_exist(mocke # Assert assert result == fake_temp_plugin_dict assert cut.ast_parse_eval.call_count == 1 - assert cut.ast_parse_eval.call_args_list[0].args == (arg_config_plugin_dict,) + assert cut.ast_parse_eval.call_args_list[0].args == ( + arg_config_plugin_dict,) assert execution_engine.isinstance.call_count == 1 - assert execution_engine.isinstance.call_args_list[0].args == (fake_plugin_dict.body, execution_engine.ast.Dict, ) + assert execution_engine.isinstance.call_args_list[0].args == ( + fake_plugin_dict.body, execution_engine.ast.Dict, ) assert execution_engine.ast.literal_eval.call_count == 1 - assert execution_engine.ast.literal_eval.call_args_list[0].args == (arg_config_plugin_dict, ) + assert execution_engine.ast.literal_eval.call_args_list[0].args == ( + arg_config_plugin_dict, ) assert fake_temp_plugin_dict.values.call_count == 1 assert fake_temp_plugin_dict.values.call_args_list[0].args == () - assert execution_engine.os.path.exists.call_count == len(exists_side_effects) + assert execution_engine.os.path.exists.call_count == len( + exists_side_effects) for i in range(len(exists_side_effects)): - assert execution_engine.os.path.exists.call_args_list[i].args == (fake_path, ) + assert execution_engine.os.path.exists.call_args_list[i].args == ( + fake_path, ) # parse_data tests + + def test_ExecutionEngine_parse_data_sets_the_simDataSource_to_a_new_data_source_module_DataSource(mocker): # Arrange arg_parser_file_name = MagicMock() @@ -468,24 +561,32 @@ def test_ExecutionEngine_parse_data_sets_the_simDataSource_to_a_new_data_source_ cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + '.importlib.util.spec_from_file_location', return_value=fake_spec) - mocker.patch(execution_engine.__name__ + '.importlib.util.module_from_spec', return_value=fake_module) + mocker.patch(execution_engine.__name__ + + '.importlib.util.spec_from_file_location', return_value=fake_spec) + mocker.patch(execution_engine.__name__ + + '.importlib.util.module_from_spec', return_value=fake_module) mocker.patch.object(fake_spec, 'loader.exec_module', return_value=None) - mocker.patch.object(fake_module, 'DataSource', return_value=fake_parser_class_instance) + mocker.patch.object(fake_module, 'DataSource', + return_value=fake_parser_class_instance) # Act - cut.parse_data(arg_parser_file_name, arg_dataFile, arg_metadataFile, arg_subsystems_breakdown) + cut.parse_data(arg_parser_file_name, arg_dataFile, + arg_metadataFile, arg_subsystems_breakdown) # Assert assert execution_engine.importlib.util.spec_from_file_location.call_count == 1 - assert execution_engine.importlib.util.spec_from_file_location.call_args_list[0].args == ('data_source', arg_parser_file_name, ) + assert execution_engine.importlib.util.spec_from_file_location.call_args_list[0].args == ( + 'data_source', arg_parser_file_name, ) assert execution_engine.importlib.util.module_from_spec.call_count == 1 - assert execution_engine.importlib.util.module_from_spec.call_args_list[0].args == (fake_spec, ) + assert execution_engine.importlib.util.module_from_spec.call_args_list[0].args == ( + fake_spec, ) assert fake_spec.loader.exec_module.call_count == 1 assert fake_module.DataSource.call_count == 1 - assert fake_module.DataSource.call_args_list[0].args == (arg_dataFile, arg_metadataFile, arg_subsystems_breakdown, ) + assert fake_module.DataSource.call_args_list[0].args == ( + arg_dataFile, arg_metadataFile, arg_subsystems_breakdown, ) assert cut.simDataSource == fake_parser_class_instance + def test_ExecutionEngine_parse_data_argument_subsystems_breakdown_optional_default_is_False(mocker): # Arrange arg_parser_file_name = MagicMock() @@ -508,19 +609,25 @@ def __init__(self, data_file, meta_file, subsystems_breakdown): cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + '.importlib.util.spec_from_file_location', return_value=fake_spec) - mocker.patch(execution_engine.__name__ + '.importlib.util.module_from_spec', return_value=fake_module) + mocker.patch(execution_engine.__name__ + + '.importlib.util.spec_from_file_location', return_value=fake_spec) + mocker.patch(execution_engine.__name__ + + '.importlib.util.module_from_spec', return_value=fake_module) mocker.patch.object(fake_spec, '.loader.exec_module', return_value=None) - mocker.patch.object(fake_module, '.DataSource', return_value=fake_parser_class_instance) + mocker.patch.object(fake_module, '.DataSource', + return_value=fake_parser_class_instance) # Act cut.parse_data(arg_parser_file_name, arg_dataFile, arg_metadataFile) # Assert assert fake_module.DataSource.call_count == 1 - assert fake_module.DataSource.call_args_list[0].args == (arg_dataFile, arg_metadataFile, False, ) + assert fake_module.DataSource.call_args_list[0].args == ( + arg_dataFile, arg_metadataFile, False, ) # setup_sim tests + + def test_ExecutionEngine_setup_sim_sets_self_sim_to_new_Simulator(mocker): # Arrange cut = ExecutionEngine.__new__(ExecutionEngine) @@ -532,7 +639,8 @@ def test_ExecutionEngine_setup_sim_sets_self_sim_to_new_Simulator(mocker): fake_sim = MagicMock() - mocker.patch(execution_engine.__name__ + '.Simulator', return_value=fake_sim) + mocker.patch(execution_engine.__name__ + + '.Simulator', return_value=fake_sim) # Act cut.setup_sim() @@ -547,11 +655,13 @@ def test_ExecutionEngine_setup_sim_sets_self_sim_to_new_Simulator(mocker): assert cut.sim == fake_sim # run_sim tests + + def test_ExecutionEngine_run_sim_runs_but_does_not_save_results_when_save_flag_is_False(mocker): # Arrange cut = ExecutionEngine.__new__(ExecutionEngine) cut.sim = MagicMock() - cut.IO_Flag = MagicMock() + cut.IO_Enabled = MagicMock() cut.save_flag = False mocker.patch.object(cut.sim, 'run_sim') @@ -562,14 +672,15 @@ def test_ExecutionEngine_run_sim_runs_but_does_not_save_results_when_save_flag_i # Assert assert cut.sim.run_sim.call_count == 1 - assert cut.sim.run_sim.call_args_list[0].args == (cut.IO_Flag, ) + assert cut.sim.run_sim.call_args_list[0].args == (cut.IO_Enabled, ) assert cut.save_results.call_count == 0 + def test_ExecutionEngine_run_sim_runs_and_saves_results_when_save_flag_is_True(mocker): # Arrange cut = ExecutionEngine.__new__(ExecutionEngine) cut.sim = MagicMock() - cut.IO_Flag = MagicMock() + cut.IO_Enabled = MagicMock() cut.save_flag = True cut.save_name = MagicMock() @@ -581,15 +692,17 @@ def test_ExecutionEngine_run_sim_runs_and_saves_results_when_save_flag_is_True(m # Assert assert cut.sim.run_sim.call_count == 1 - assert cut.sim.run_sim.call_args_list[0].args == (cut.IO_Flag, ) + assert cut.sim.run_sim.call_args_list[0].args == (cut.IO_Enabled, ) assert cut.save_results.call_count == 1 assert cut.save_results.call_args_list[0].args == (cut.save_name, ) # init_save_paths tests + + def test_ExecutionEngine_init_save_paths_makes_tmp_and_models_and_diagnosis_directories_and_adds_them_to_os_environ(mocker): # Arrange fake_save_path = str(MagicMock()) - fake_environ = {'RESULTS_PATH':fake_save_path} + fake_environ = {'RESULTS_PATH': fake_save_path} fake_tmp_save_path = str(MagicMock()) fake_tmp_models_path = str(MagicMock()) fake_tmp_diagnosis_path = str(MagicMock()) @@ -598,7 +711,7 @@ def test_ExecutionEngine_init_save_paths_makes_tmp_and_models_and_diagnosis_dire mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + '.os.path.join', - side_effect=[fake_tmp_save_path, fake_tmp_models_path, fake_tmp_diagnosis_path]) + side_effect=[fake_tmp_save_path, fake_tmp_models_path, fake_tmp_diagnosis_path]) mocker.patch.object(cut, 'delete_save_paths') mocker.patch(execution_engine.__name__ + '.os.mkdir') @@ -609,9 +722,12 @@ def test_ExecutionEngine_init_save_paths_makes_tmp_and_models_and_diagnosis_dire # NOTE: assert execution_engine.os.path.join.call_count must assert correctly or there are odd errors? Is this due to using side_effect instead of return_value? assert execution_engine.os.path.join.call_count == 3 # NOTE: similar problem with the args lists, bad expected values do not error nicely with good outputs, so beware but correct values pass - assert execution_engine.os.path.join.call_args_list[0].args == (fake_save_path, 'tmp') - assert execution_engine.os.path.join.call_args_list[1].args == (fake_tmp_save_path, 'models') - assert execution_engine.os.path.join.call_args_list[2].args == (fake_tmp_save_path, 'diagnosis') + assert execution_engine.os.path.join.call_args_list[0].args == ( + fake_save_path, 'tmp') + assert execution_engine.os.path.join.call_args_list[1].args == ( + fake_tmp_save_path, 'models') + assert execution_engine.os.path.join.call_args_list[2].args == ( + fake_tmp_save_path, 'diagnosis') # NOTE: apparently the problem persists to other failures because these asserts have the same problem, bad values error, but not correct outputs, good values pass assert execution_engine.os.environ['ONAIR_SAVE_PATH'] == fake_save_path assert execution_engine.os.environ['ONAIR_TMP_SAVE_PATH'] == fake_tmp_save_path @@ -619,19 +735,22 @@ def test_ExecutionEngine_init_save_paths_makes_tmp_and_models_and_diagnosis_dire assert execution_engine.os.environ['ONAIR_DIAGNOSIS_SAVE_PATH'] == fake_tmp_diagnosis_path # delete_save_path tests + + def test_ExecutionEngine_delete_save_paths_does_nothing_when_save_path_has_no_tmp_dir(mocker): # Arrange fake_save_path = str(MagicMock()) - fake_environ = {'RESULTS_PATH':fake_save_path} + fake_environ = {'RESULTS_PATH': fake_save_path} fake_dirs = [] - for i in range(pytest.gen.randint(0, 5)): # 0 to 5 + for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) - mocker.patch(execution_engine.__name__ + '.os.listdir', return_value=fake_dirs) + mocker.patch(execution_engine.__name__ + + '.os.listdir', return_value=fake_dirs) mocker.patch(execution_engine.__name__ + '.shutil.rmtree') # Act @@ -639,25 +758,28 @@ def test_ExecutionEngine_delete_save_paths_does_nothing_when_save_path_has_no_tm # Assert assert execution_engine.os.listdir.call_count == 1 - assert execution_engine.os.listdir.call_args_list[0].args == (fake_save_path, ) + assert execution_engine.os.listdir.call_args_list[0].args == ( + fake_save_path, ) assert execution_engine.shutil.rmtree.call_count == 0 + def test_ExecutionEngine_delete_save_paths_removes_tmp_tree_when_it_exists(mocker): # Arrange fake_save_path = str(MagicMock()) - fake_environ = {'RESULTS_PATH':fake_save_path} + fake_environ = {'RESULTS_PATH': fake_save_path} fake_dirs = [] - for i in range(pytest.gen.randint(0, 5)): # 0 to 5 + for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) fake_dirs.append('tmp') - for i in range(pytest.gen.randint(0, 5)): # 0 to 5 + for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) - mocker.patch(execution_engine.__name__ + '.os.listdir', return_value=fake_dirs) + mocker.patch(execution_engine.__name__ + + '.os.listdir', return_value=fake_dirs) mocker.patch(execution_engine.__name__ + '.shutil.rmtree') mocker.patch(execution_engine.__name__ + '.print') @@ -666,29 +788,35 @@ def test_ExecutionEngine_delete_save_paths_removes_tmp_tree_when_it_exists(mocke # Assert assert execution_engine.os.listdir.call_count == 1 - assert execution_engine.os.listdir.call_args_list[0].args == (fake_save_path, ) + assert execution_engine.os.listdir.call_args_list[0].args == ( + fake_save_path, ) assert execution_engine.shutil.rmtree.call_count == 1 - assert execution_engine.shutil.rmtree.call_args_list[0].args == (fake_save_path + '/tmp', ) + assert execution_engine.shutil.rmtree.call_args_list[0].args == ( + fake_save_path + '/tmp', ) assert execution_engine.print.call_count == 0 + def test_ExecutionEngine_delete_save_paths_prints_error_message_when_rmtree_raises_OSError(mocker): # Arrange fake_save_path = str(MagicMock()) - fake_environ = {'RESULTS_PATH':fake_save_path} + fake_environ = {'RESULTS_PATH': fake_save_path} fake_dirs = [] fake_error_message = str(MagicMock()) - for i in range(pytest.gen.randint(0, 5)): # 0 to 5 + for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) fake_dirs.append('tmp') - for i in range(pytest.gen.randint(0, 5)): # 0 to 5 + for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) - mocker.patch(execution_engine.__name__ + '.os.listdir', return_value=fake_dirs) - mocker.patch(execution_engine.__name__ + '.shutil.rmtree', side_effect=OSError(pytest.gen.randint(0,10),fake_error_message)) # 0 to 10 arbitrary error value for errno + mocker.patch(execution_engine.__name__ + + '.os.listdir', return_value=fake_dirs) + mocker.patch(execution_engine.__name__ + '.shutil.rmtree', side_effect=OSError( + # 0 to 10 arbitrary error value for errno + pytest.gen.randint(0, 10), fake_error_message)) mocker.patch(execution_engine.__name__ + '.print') # Act @@ -696,13 +824,18 @@ def test_ExecutionEngine_delete_save_paths_prints_error_message_when_rmtree_rais # Assert assert execution_engine.os.listdir.call_count == 1 - assert execution_engine.os.listdir.call_args_list[0].args == (fake_save_path, ) + assert execution_engine.os.listdir.call_args_list[0].args == ( + fake_save_path, ) assert execution_engine.shutil.rmtree.call_count == 1 - assert execution_engine.shutil.rmtree.call_args_list[0].args == (fake_save_path + '/tmp', ) + assert execution_engine.shutil.rmtree.call_args_list[0].args == ( + fake_save_path + '/tmp', ) assert execution_engine.print.call_count == 1 - assert execution_engine.print.call_args_list[0].args == (("Error: " + fake_save_path + " : " + fake_error_message), ) + assert execution_engine.print.call_args_list[0].args == ( + ("Error: " + fake_save_path + " : " + fake_error_message), ) # save_results tests + + def test_ExecutionEngine_save_results_creates_expected_save_path_and_copies_proper_tree_to_it(mocker): # Arrange arg_save_name = str(MagicMock()) @@ -711,13 +844,17 @@ def test_ExecutionEngine_save_results_creates_expected_save_path_and_copies_prop fake_complete_time = str(MagicMock()) fake_onair_save_path = str(MagicMock()) fake_onair_tmp_save_path = str(MagicMock()) - fake_environ = {'ONAIR_SAVE_PATH':fake_onair_save_path, 'ONAIR_TMP_SAVE_PATH':fake_onair_tmp_save_path} - fake_save_path = fake_onair_save_path + 'saved/' + arg_save_name + '_' + fake_complete_time + fake_environ = {'ONAIR_SAVE_PATH': fake_onair_save_path, + 'ONAIR_TMP_SAVE_PATH': fake_onair_tmp_save_path} + fake_save_path = fake_onair_save_path + 'saved/' + \ + arg_save_name + '_' + fake_complete_time cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + '.gmtime', return_value=fake_gmtime) - mocker.patch(execution_engine.__name__ + '.strftime', return_value=fake_complete_time) + mocker.patch(execution_engine.__name__ + + '.gmtime', return_value=fake_gmtime) + mocker.patch(execution_engine.__name__ + '.strftime', + return_value=fake_complete_time) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + '.os.makedirs') mocker.patch(execution_engine.__name__ + '.copy_tree') @@ -729,14 +866,20 @@ def test_ExecutionEngine_save_results_creates_expected_save_path_and_copies_prop assert execution_engine.gmtime.call_count == 1 assert execution_engine.gmtime.call_args_list[0].args == () assert execution_engine.strftime.call_count == 1 - assert execution_engine.strftime.call_args_list[0].args == ("%H-%M-%S", fake_gmtime,) + assert execution_engine.strftime.call_args_list[0].args == ( + "%H-%M-%S", fake_gmtime,) assert execution_engine.os.makedirs.call_count == 1 - assert execution_engine.os.makedirs.call_args_list[0].args == (fake_save_path, ) - assert execution_engine.os.makedirs.call_args_list[0].kwargs == {"exist_ok":True} + assert execution_engine.os.makedirs.call_args_list[0].args == ( + fake_save_path, ) + assert execution_engine.os.makedirs.call_args_list[0].kwargs == { + "exist_ok": True} assert execution_engine.copy_tree.call_count == 1 - assert execution_engine.copy_tree.call_args_list[0].args == (fake_onair_tmp_save_path, fake_save_path, ) + assert execution_engine.copy_tree.call_args_list[0].args == ( + fake_onair_tmp_save_path, fake_save_path, ) # set_run_param tests + + def test_ExecutionEngine_set_run_param_passes_given_arguments_to_setattr(mocker): # Arrange arg_name = MagicMock() @@ -750,16 +893,20 @@ def test_ExecutionEngine_set_run_param_passes_given_arguments_to_setattr(mocker) # Assert assert execution_engine.setattr.call_count == 1 - assert execution_engine.setattr.call_args_list[0].args == (cut, arg_name, arg_val, ) + assert execution_engine.setattr.call_args_list[0].args == ( + cut, arg_name, arg_val, ) # ast_parse_eval tests + + def test_ExecutionEngine_ast_parse_eval_returns_call_to_ast_parse_with_mode_eval(mocker): # Arrange arg_config_list = MagicMock() expected_result = MagicMock() cut = ExecutionEngine.__new__(ExecutionEngine) - mocker.patch(execution_engine.__name__ + ".ast.parse", return_value=expected_result) + mocker.patch(execution_engine.__name__ + ".ast.parse", + return_value=expected_result) # Act result = cut.ast_parse_eval(arg_config_list) @@ -767,6 +914,7 @@ def test_ExecutionEngine_ast_parse_eval_returns_call_to_ast_parse_with_mode_eval # Assert assert result == expected_result assert execution_engine.ast.parse.call_count == 1 - assert execution_engine.ast.parse.call_args_list[0].args == (arg_config_list, ) - assert execution_engine.ast.parse.call_args_list[0].kwargs == {'mode':'eval'} - + assert execution_engine.ast.parse.call_args_list[0].args == ( + arg_config_list, ) + assert execution_engine.ast.parse.call_args_list[0].kwargs == { + 'mode': 'eval'} From c301ae59fcc64ac4f8814046b0db0a568ff21e7f Mon Sep 17 00:00:00 2001 From: Evan Tung Date: Sat, 23 Mar 2024 19:00:19 -0400 Subject: [PATCH 2/6] enable OPTIONS section to be optional --- onair/src/run_scripts/execution_engine.py | 70 ++++++++++------- .../src/run_scripts/test_execution_engine.py | 75 ++++++++++++++++--- 2 files changed, 109 insertions(+), 36 deletions(-) diff --git a/onair/src/run_scripts/execution_engine.py b/onair/src/run_scripts/execution_engine.py index a9879d3f..5f46cd04 100644 --- a/onair/src/run_scripts/execution_engine.py +++ b/onair/src/run_scripts/execution_engine.py @@ -21,6 +21,7 @@ from ..run_scripts.sim import Simulator + class ExecutionEngine: def __init__(self, config_file='', run_name='', save_flag=False): @@ -56,59 +57,77 @@ def __init__(self, config_file='', run_name='', save_flag=False): if config_file != '': self.init_save_paths() self.parse_configs(config_file) - self.parse_data(self.data_source_file, self.fullTelemetryFile, self.fullMetaFile) + self.parse_data(self.data_source_file, + self.fullTelemetryFile, self.fullMetaFile) self.setup_sim() def parse_configs(self, config_filepath): config = configparser.ConfigParser() if len(config.read(config_filepath)) == 0: - raise FileNotFoundError(f"Config file at '{config_filepath}' could not be read.") + raise FileNotFoundError( + f"Config file at '{config_filepath}' could not be read.") try: - ## Parse Required Data: FILES + # Parse Required Data: FILES self.dataFilePath = config['FILES']['TelemetryFilePath'] - self.telemetryFile = config['FILES']['TelemetryFile'] # Vehicle telemetry data - self.fullTelemetryFile = os.path.join(self.dataFilePath, self.telemetryFile) + # Vehicle telemetry data + self.telemetryFile = config['FILES']['TelemetryFile'] + self.fullTelemetryFile = os.path.join( + self.dataFilePath, self.telemetryFile) self.metadataFilePath = config['FILES']['MetaFilePath'] - self.metaFile = config['FILES']['MetaFile'] # Config for vehicle telemetry - self.fullMetaFile = os.path.join(self.metadataFilePath, self.metaFile) + # Config for vehicle telemetry + self.metaFile = config['FILES']['MetaFile'] + self.fullMetaFile = os.path.join( + self.metadataFilePath, self.metaFile) - ## Parse Required Data: DATA_HANDLING + # Parse Required Data: DATA_HANDLING self.data_source_file = config['DATA_HANDLING']['DataSourceFile'] - ## Parse Required Data: PLUGINS - self.knowledge_rep_plugin_dict = self.parse_plugins_dict(config['PLUGINS']['KnowledgeRepPluginDict']) - self.learners_plugin_dict = self.parse_plugins_dict(config['PLUGINS']['LearnersPluginDict']) - self.planners_plugin_dict = self.parse_plugins_dict(config['PLUGINS']['PlannersPluginDict']) - self.complex_plugin_dict = self.parse_plugins_dict(config['PLUGINS']['ComplexPluginDict']) - - ## Parse Optional Data: OPTIONS - ## 'OPTIONS' must exist, but individual options return False if missing - self.IO_Enabled = config['OPTIONS'].getboolean('IO_Enabled') + # Parse Required Data: PLUGINS + self.knowledge_rep_plugin_dict = self.parse_plugins_dict( + config['PLUGINS']['KnowledgeRepPluginDict']) + self.learners_plugin_dict = self.parse_plugins_dict( + config['PLUGINS']['LearnersPluginDict']) + self.planners_plugin_dict = self.parse_plugins_dict( + config['PLUGINS']['PlannersPluginDict']) + self.complex_plugin_dict = self.parse_plugins_dict( + config['PLUGINS']['ComplexPluginDict']) + + # Parse Optional Data: OPTIONS + # 'OPTIONS' must exist, but individual options return False if missing + if config.has_section('OPTIONS'): + self.IO_Enabled = config['OPTIONS'].getboolean('IO_Enabled') + else: + self.IO_Enabled = False except KeyError as e: - new_message = f"Config file: '{config_filepath}', missing key: {e.args[0]}" + new_message = f"Config file: '{ + config_filepath}', missing key: {e.args[0]}" raise KeyError(new_message) from e def parse_plugins_dict(self, config_plugin_dict): - ## Parse Required Data: Plugin name to path dict + # Parse Required Data: Plugin name to path dict ast_plugin_dict = self.ast_parse_eval(config_plugin_dict) if isinstance(ast_plugin_dict.body, ast.Dict): temp_plugin_dict = ast.literal_eval(config_plugin_dict) else: - raise ValueError(f"Plugin dict {config_plugin_dict} from {self.config_filepath} is invalid. It must be a dict.") + raise ValueError(f"Plugin dict {config_plugin_dict} from { + self.config_filepath} is invalid. It must be a dict.") for plugin_file in temp_plugin_dict.values(): - if not(os.path.exists(plugin_file)): - raise FileNotFoundError(f"In config file '{self.config_filepath}' Plugin path '{plugin_file}' does not exist.") + if not (os.path.exists(plugin_file)): + raise FileNotFoundError(f"In config file '{self.config_filepath}' Plugin path '{ + plugin_file}' does not exist.") return temp_plugin_dict def parse_data(self, parser_file_name, data_file_name, metadata_file_name, subsystems_breakdown=False): - data_source_spec = importlib.util.spec_from_file_location('data_source', parser_file_name) + data_source_spec = importlib.util.spec_from_file_location( + 'data_source', parser_file_name) data_source_module = importlib.util.module_from_spec(data_source_spec) data_source_spec.loader.exec_module(data_source_module) - self.simDataSource = data_source_module.DataSource(data_file_name, metadata_file_name, subsystems_breakdown) + self.simDataSource = data_source_module.DataSource( + data_file_name, metadata_file_name, subsystems_breakdown) def setup_sim(self): self.sim = Simulator(self.simDataSource, @@ -149,7 +168,8 @@ def delete_save_paths(self): def save_results(self, save_name): complete_time = strftime("%H-%M-%S", gmtime()) - save_path = os.environ['ONAIR_SAVE_PATH'] + 'saved/' + save_name + '_' + complete_time + save_path = os.environ['ONAIR_SAVE_PATH'] + \ + 'saved/' + save_name + '_' + complete_time os.makedirs(save_path, exist_ok=True) copy_tree(os.environ['ONAIR_TMP_SAVE_PATH'], save_path) diff --git a/test/onair/src/run_scripts/test_execution_engine.py b/test/onair/src/run_scripts/test_execution_engine.py index 74eeb9c7..2baa4ebb 100644 --- a/test/onair/src/run_scripts/test_execution_engine.py +++ b/test/onair/src/run_scripts/test_execution_engine.py @@ -207,20 +207,55 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe f"Config file: '{arg_config_filepath}', missing key: {missing_key}") -def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_when_the_required_key_OPTIONS_is_not_in_config(mocker): +def test_ExecutionEngine_parse_configs_skips_OPTIONS_when_the_required_section_OPTIONS_is_not_in_config(mocker): # Arrange arg_config_filepath = MagicMock() - - missing_key = 'OPTIONS' + fake_files = { + 'TelemetryFilePath': MagicMock(), + 'TelemetryFile': MagicMock(), + 'MetaFilePath': MagicMock(), + 'MetaFile': MagicMock() + } + fake_data_handling = { + 'DataSourceFile': MagicMock() + } + fake_plugins = { + 'KnowledgeRepPluginDict': "{fake_name:fake_path}", + 'LearnersPluginDict': "{fake_name:fake_path}", + 'PlannersPluginDict': "{fake_name:fake_path}", + 'ComplexPluginDict': "{fake_name:fake_path}" + } + fake_plugin_dict = MagicMock() + fake_plugin_dict.body = MagicMock() + fake_plugin_dict.body.keys = MagicMock() + fake_plugin_dict.body.keys.__len__.return_value = 1 fake_dict_for_Config = { - "FILES": MagicMock(), - "DATA_HANDLING": MagicMock(), - "PLUGINS": MagicMock() + "FILES": fake_files, + "DATA_HANDLING": fake_data_handling, + "PLUGINS": fake_plugins } fake_config = MagicMock() fake_config.__getitem__.side_effect = fake_dict_for_Config.__getitem__ fake_config_read_result = MagicMock() fake_config_read_result.__len__.return_value = 1 + fake_knowledge_rep_plugin_list = MagicMock() + fake_learners_plugin_list = MagicMock() + fake_planners_plugin_list = MagicMock() + fake_complex_plugin_list = MagicMock() + fake_plugins = [fake_knowledge_rep_plugin_list, + fake_learners_plugin_list, + fake_planners_plugin_list, + fake_complex_plugin_list] + fake_IO_enabled = MagicMock() + fake_Dev_enabled = MagicMock() + fake_Viz_enabled = MagicMock() + fake_plugin_dict = MagicMock() + fake_keys = MagicMock() + fake_plugin = MagicMock() + fake_path = MagicMock() + + fake_keys.__len__.return_value = 1 + fake_keys.__iter__.return_value = iter([str(fake_plugin)]) cut = ExecutionEngine.__new__(ExecutionEngine) @@ -228,15 +263,32 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe '.configparser.ConfigParser', return_value=fake_config) mocker.patch.object(fake_config, 'read', return_value=fake_config_read_result) - mocker.patch.object(cut, 'parse_plugins_dict', return_value=None) + mocker.patch.object(fake_config, "has_section", return_value=False) + mocker.patch.object(cut, 'parse_plugins_dict', side_effect=fake_plugins) + mocker.patch(execution_engine.__name__ + '.isinstance', return_value=True) + mocker.patch(execution_engine.__name__ + + '.os.path.exists', return_value=True) + mocker.patch.object(fake_plugin_dict, 'keys', return_value=fake_keys) + mocker.patch.object(fake_plugin_dict, '__getitem__', + return_value=fake_path) # Act - with pytest.raises(KeyError) as e_info: - cut.parse_configs(arg_config_filepath) + cut.parse_configs(arg_config_filepath) # Assert - assert e_info.match( - f"Config file: '{arg_config_filepath}', missing key: {missing_key}") + assert execution_engine.configparser.ConfigParser.call_count == 1 + assert fake_config.read.call_count == 1 + assert cut.dataFilePath == fake_files['TelemetryFilePath'] + assert cut.telemetryFile == fake_files['TelemetryFile'] + assert cut.metadataFilePath == fake_files['MetaFilePath'] + assert cut.metaFile == fake_files['MetaFile'] + assert cut.data_source_file == fake_data_handling['DataSourceFile'] + assert cut.parse_plugins_dict.call_count == 4 + assert cut.knowledge_rep_plugin_dict == fake_knowledge_rep_plugin_list + assert cut.learners_plugin_dict == fake_learners_plugin_list + assert cut.planners_plugin_dict == fake_planners_plugin_list + assert cut.complex_plugin_dict == fake_complex_plugin_list + assert cut.IO_Enabled == False def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): @@ -297,6 +349,7 @@ def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): '.configparser.ConfigParser', return_value=fake_config) mocker.patch.object(fake_config, 'read', return_value=fake_config_read_result) + mocker.patch.object(fake_config, "has_section", return_value=True) mocker.patch.object(cut, 'parse_plugins_dict', side_effect=fake_plugins) mocker.patch.object(fake_options, 'getboolean', return_value=fake_IO_enabled) From 9eb12bd9bf78e53970ba11b819c904d2802f43c6 Mon Sep 17 00:00:00 2001 From: Evan Tung Date: Thu, 20 Jun 2024 19:31:36 -0700 Subject: [PATCH 3/6] fix: Remove dev_enabled and viz_enabled, use GitHub default python gitignore, remove multiline f-string --- .gitignore | 133 +++++++++++++++++- onair/config/default_config.ini | 2 +- onair/config/reporter_config.ini | 2 - onair/src/run_scripts/execution_engine.py | 16 +-- .../src/run_scripts/test_execution_engine.py | 73 +++++----- 5 files changed, 169 insertions(+), 57 deletions(-) diff --git a/.gitignore b/.gitignore index 3d0969cd..f48b3919 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,132 @@ -*.pyc -.DS_Store +# Byte-compiled / optimized / DLL files __pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ .coverage -.vscode/ \ No newline at end of file +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Visual Studio Code +.vscode/ diff --git a/onair/config/default_config.ini b/onair/config/default_config.ini index c107ab0c..c5e4a922 100644 --- a/onair/config/default_config.ini +++ b/onair/config/default_config.ini @@ -27,7 +27,7 @@ PlannersPluginDict = {'generic':'plugins/generic/__init__.py'} # Required Key: ComplexPluginDict(s) are used by Agent for complex reasoning ComplexPluginDict = {'generic':'plugins/generic/__init__.py'} -# Required Section: OPTIONS are settable values to change running experience +# Optional Section: OPTIONS are settable values to change running experience [OPTIONS] # Optional Key: IO_Flag denotes whether or not to provide console output # default = false diff --git a/onair/config/reporter_config.ini b/onair/config/reporter_config.ini index 65b3a9bc..8eac4a47 100644 --- a/onair/config/reporter_config.ini +++ b/onair/config/reporter_config.ini @@ -19,5 +19,3 @@ ComplexPluginDict = {'Complex Reporter 1':'plugins/reporter', [OPTIONS] IO_Enabled = true -Dev_Enabled = false -Viz_Enabled = false diff --git a/onair/src/run_scripts/execution_engine.py b/onair/src/run_scripts/execution_engine.py index 5f46cd04..6ea946e3 100644 --- a/onair/src/run_scripts/execution_engine.py +++ b/onair/src/run_scripts/execution_engine.py @@ -16,7 +16,7 @@ import importlib import ast import shutil -from distutils.dir_util import copy_tree +from shutil import copytree from time import gmtime, strftime from ..run_scripts.sim import Simulator @@ -65,8 +65,7 @@ def parse_configs(self, config_filepath): config = configparser.ConfigParser() if len(config.read(config_filepath)) == 0: - raise FileNotFoundError( - f"Config file at '{config_filepath}' could not be read.") + raise FileNotFoundError(f"Config file at '{config_filepath}' could not be read.") try: # Parse Required Data: FILES @@ -102,8 +101,7 @@ def parse_configs(self, config_filepath): self.IO_Enabled = False except KeyError as e: - new_message = f"Config file: '{ - config_filepath}', missing key: {e.args[0]}" + new_message = f"Config file: '{config_filepath}', missing key: {e.args[0]}" raise KeyError(new_message) from e def parse_plugins_dict(self, config_plugin_dict): @@ -112,13 +110,11 @@ def parse_plugins_dict(self, config_plugin_dict): if isinstance(ast_plugin_dict.body, ast.Dict): temp_plugin_dict = ast.literal_eval(config_plugin_dict) else: - raise ValueError(f"Plugin dict {config_plugin_dict} from { - self.config_filepath} is invalid. It must be a dict.") + raise ValueError(f"Plugin dict {config_plugin_dict} from {self.config_filepath} is invalid. It must be a dict.") for plugin_file in temp_plugin_dict.values(): if not (os.path.exists(plugin_file)): - raise FileNotFoundError(f"In config file '{self.config_filepath}' Plugin path '{ - plugin_file}' does not exist.") + raise FileNotFoundError(f"In config file '{self.config_filepath}' Plugin path '{plugin_file}' does not exist.") return temp_plugin_dict def parse_data(self, parser_file_name, data_file_name, metadata_file_name, subsystems_breakdown=False): @@ -171,7 +167,7 @@ def save_results(self, save_name): save_path = os.environ['ONAIR_SAVE_PATH'] + \ 'saved/' + save_name + '_' + complete_time os.makedirs(save_path, exist_ok=True) - copy_tree(os.environ['ONAIR_TMP_SAVE_PATH'], save_path) + copytree(os.environ['ONAIR_TMP_SAVE_PATH'], save_path) def set_run_param(self, name, val): setattr(self, name, val) diff --git a/test/onair/src/run_scripts/test_execution_engine.py b/test/onair/src/run_scripts/test_execution_engine.py index 2baa4ebb..4d4b2040 100644 --- a/test/onair/src/run_scripts/test_execution_engine.py +++ b/test/onair/src/run_scripts/test_execution_engine.py @@ -23,7 +23,7 @@ def test_ExecutionEngine__init__sets_expected_values_but_does_no_calls_when_conf arg_run_name = MagicMock() arg_save_flag = MagicMock() - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch.object(cut, 'init_save_paths') mocker.patch.object(cut, 'parse_configs') @@ -59,7 +59,7 @@ def test_ExecutionEngine__init__does_calls_when_config_file_is_an_occupied_strin arg_run_name = MagicMock() arg_save_flag = MagicMock() - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch.object(cut, 'init_save_paths') mocker.patch.object(cut, 'parse_configs') @@ -81,7 +81,7 @@ def test_ExecutionEngine__init__does_calls_when_config_file_is_an_occupied_strin def test_ExecutionEngine__init__accepts_no_arguments_using_defaults_instead_with_config_file_default_as_empty_string(mocker): # Arrange - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch.object(cut, 'init_save_paths') mocker.patch.object(cut, 'parse_configs') @@ -108,7 +108,7 @@ def test_ExecutionEngine_parse_configs_raises_FileNotFoundError_when_config_cann fake_config_read_result = MagicMock() fake_config_read_result.__len__.return_value = 0 - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -120,8 +120,7 @@ def test_ExecutionEngine_parse_configs_raises_FileNotFoundError_when_config_cann cut.parse_configs(arg_bad_config_filepath) # Assert - assert e_info.match(f"Config file at '{ - arg_bad_config_filepath}' could not be read.") + assert e_info.match(f"Config file at '{arg_bad_config_filepath}' could not be read.") def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_when_the_required_key_FILES_is_not_in_config(mocker): @@ -139,7 +138,7 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe fake_config_read_result = MagicMock() fake_config_read_result.__len__.return_value = 1 - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -190,7 +189,7 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe fake_config_read_result = MagicMock() fake_config_read_result.__len__.return_value = 1 - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -246,9 +245,6 @@ def test_ExecutionEngine_parse_configs_skips_OPTIONS_when_the_required_section_O fake_learners_plugin_list, fake_planners_plugin_list, fake_complex_plugin_list] - fake_IO_enabled = MagicMock() - fake_Dev_enabled = MagicMock() - fake_Viz_enabled = MagicMock() fake_plugin_dict = MagicMock() fake_keys = MagicMock() fake_plugin = MagicMock() @@ -257,7 +253,7 @@ def test_ExecutionEngine_parse_configs_skips_OPTIONS_when_the_required_section_O fake_keys.__len__.return_value = 1 fake_keys.__iter__.return_value = iter([str(fake_plugin)]) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -333,8 +329,6 @@ def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): fake_planners_plugin_list, fake_complex_plugin_list] fake_IO_enabled = MagicMock() - fake_Dev_enabled = MagicMock() - fake_Viz_enabled = MagicMock() fake_plugin_dict = MagicMock() fake_keys = MagicMock() fake_plugin = MagicMock() @@ -343,7 +337,7 @@ def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): fake_keys.__len__.return_value = 1 fake_keys.__iter__.return_value = iter([str(fake_plugin)]) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -391,7 +385,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_ValueError_when_config_plugin fake_plugin_dict.body = MagicMock() fake_config_filepath = MagicMock() - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -402,8 +396,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_ValueError_when_config_plugin cut.parse_plugins_dict(arg_config_plugin_dict) # Assert - assert e_info.match(f"Plugin dict {arg_config_plugin_dict} from { - fake_config_filepath} is invalid. It must be a dict.") + assert e_info.match(f"Plugin dict {arg_config_plugin_dict} from {fake_config_filepath} is invalid. It must be a dict.") assert cut.ast_parse_eval.call_count == 1 assert cut.ast_parse_eval.call_args_list[0].args == ( arg_config_plugin_dict,) @@ -425,7 +418,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_single fake_values.__iter__.return_value = iter([fake_path]) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -442,8 +435,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_single cut.parse_plugins_dict(arg_config_plugin_dict) # Assert - assert e_info.match(f"In config file '{fake_config_filepath}' Plugin path '{ - fake_path}' does not exist.") + assert e_info.match(f"In config file '{fake_config_filepath}' Plugin path '{fake_path}' does not exist.") assert cut.ast_parse_eval.call_count == 1 assert cut.ast_parse_eval.call_args_list[0].args == ( arg_config_plugin_dict,) @@ -478,7 +470,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_any_co fake_values.__iter__.return_value = iter([fake_path] * num_fake_items) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -495,8 +487,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_any_co cut.parse_plugins_dict(arg_config_plugin_dict) # Assert - assert e_info.match(f"In config file '{fake_config_filepath}' Plugin path '{ - fake_path}' does not exist.") + assert e_info.match(f"In config file '{fake_config_filepath}' Plugin path '{fake_path}' does not exist.") assert cut.ast_parse_eval.call_count == 1 assert cut.ast_parse_eval.call_args_list[0].args == ( arg_config_plugin_dict,) @@ -524,7 +515,7 @@ def test_ExecutionEngine_returns_empty_dict_when_config_dict_is_empty(mocker): fake_config_filepath = MagicMock() fake_temp_plugin_dict = {} - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -564,7 +555,7 @@ def test_ExecutionEngine_returns_expected_dict_when_all_mapped_files_exist(mocke fake_values.__iter__.return_value = iter([fake_path] * num_fake_items) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -612,7 +603,7 @@ def test_ExecutionEngine_parse_data_sets_the_simDataSource_to_a_new_data_source_ fake_module = MagicMock() fake_parser_class_instance = MagicMock() - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.importlib.util.spec_from_file_location', return_value=fake_spec) @@ -660,7 +651,7 @@ def __init__(self, data_file, meta_file, subsystems_breakdown): fake_module = MagicMock() fake_parser_class_instance = MagicMock() - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.importlib.util.spec_from_file_location', return_value=fake_spec) @@ -683,7 +674,7 @@ def __init__(self, data_file, meta_file, subsystems_breakdown): def test_ExecutionEngine_setup_sim_sets_self_sim_to_new_Simulator(mocker): # Arrange - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() cut.simDataSource = MagicMock() cut.knowledge_rep_plugin_dict = MagicMock() cut.learners_plugin_dict = MagicMock() @@ -712,7 +703,7 @@ def test_ExecutionEngine_setup_sim_sets_self_sim_to_new_Simulator(mocker): def test_ExecutionEngine_run_sim_runs_but_does_not_save_results_when_save_flag_is_False(mocker): # Arrange - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() cut.sim = MagicMock() cut.IO_Enabled = MagicMock() cut.save_flag = False @@ -731,7 +722,7 @@ def test_ExecutionEngine_run_sim_runs_but_does_not_save_results_when_save_flag_i def test_ExecutionEngine_run_sim_runs_and_saves_results_when_save_flag_is_True(mocker): # Arrange - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() cut.sim = MagicMock() cut.IO_Enabled = MagicMock() cut.save_flag = True @@ -760,7 +751,7 @@ def test_ExecutionEngine_init_save_paths_makes_tmp_and_models_and_diagnosis_dire fake_tmp_models_path = str(MagicMock()) fake_tmp_diagnosis_path = str(MagicMock()) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + '.os.path.join', @@ -799,7 +790,7 @@ def test_ExecutionEngine_delete_save_paths_does_nothing_when_save_path_has_no_tm for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + @@ -828,7 +819,7 @@ def test_ExecutionEngine_delete_save_paths_removes_tmp_tree_when_it_exists(mocke for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + @@ -862,7 +853,7 @@ def test_ExecutionEngine_delete_save_paths_prints_error_message_when_rmtree_rais for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + @@ -902,7 +893,7 @@ def test_ExecutionEngine_save_results_creates_expected_save_path_and_copies_prop fake_save_path = fake_onair_save_path + 'saved/' + \ arg_save_name + '_' + fake_complete_time - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.gmtime', return_value=fake_gmtime) @@ -910,7 +901,7 @@ def test_ExecutionEngine_save_results_creates_expected_save_path_and_copies_prop return_value=fake_complete_time) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + '.os.makedirs') - mocker.patch(execution_engine.__name__ + '.copy_tree') + mocker.patch(execution_engine.__name__ + '.copytree') # Act cut.save_results(arg_save_name) @@ -926,8 +917,8 @@ def test_ExecutionEngine_save_results_creates_expected_save_path_and_copies_prop fake_save_path, ) assert execution_engine.os.makedirs.call_args_list[0].kwargs == { "exist_ok": True} - assert execution_engine.copy_tree.call_count == 1 - assert execution_engine.copy_tree.call_args_list[0].args == ( + assert execution_engine.copytree.call_count == 1 + assert execution_engine.copytree.call_args_list[0].args == ( fake_onair_tmp_save_path, fake_save_path, ) # set_run_param tests @@ -937,7 +928,7 @@ def test_ExecutionEngine_set_run_param_passes_given_arguments_to_setattr(mocker) # Arrange arg_name = MagicMock() arg_val = MagicMock() - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + '.setattr') @@ -956,7 +947,7 @@ def test_ExecutionEngine_ast_parse_eval_returns_call_to_ast_parse_with_mode_eval # Arrange arg_config_list = MagicMock() expected_result = MagicMock() - cut = ExecutionEngine.__new__(ExecutionEngine) + cut = ExecutionEngine() mocker.patch(execution_engine.__name__ + ".ast.parse", return_value=expected_result) From b8e3f1598023cbe7950ee3cb5b73dd6173da2c3a Mon Sep 17 00:00:00 2001 From: Evan Tung Date: Wed, 10 Jul 2024 13:50:46 -0400 Subject: [PATCH 4/6] fix: Update redis_example.ini and kalman_csv_output_example.ini to reflect changes --- onair/config/kalman_csv_output_example.ini | 15 +++++++++------ onair/config/redis_example.ini | 4 +++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/onair/config/kalman_csv_output_example.ini b/onair/config/kalman_csv_output_example.ini index 06dab42e..c4f2b28c 100644 --- a/onair/config/kalman_csv_output_example.ini +++ b/onair/config/kalman_csv_output_example.ini @@ -1,14 +1,17 @@ -[DEFAULT] -TelemetryDataFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors +[FILES] +TelemetryFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors TelemetryFile = 700_crash_to_earth_1.csv -TelemetryMetadataFilePath = onair/data/telemetry_configs/ +MetaFilePath = onair/data/telemetry_configs/ MetaFile = data_physics_generation_CONFIG.json -ParserFileName = onair/data_handling/csv_parser.py +[DATA_HANDLING] +DataSourceFile = onair/data_handling/redis_adapter.py + +[PLUGINS] KnowledgeRepPluginDict = {'Kalman Filter': 'plugins/kalman'} LearnersPluginDict = {'csv output':'plugins/csv_output'} PlannersPluginDict = {} ComplexPluginDict = {} -[RUN_FLAGS] -IO_Flag = true +[OPTIONS] +IO_Enabled = true diff --git a/onair/config/redis_example.ini b/onair/config/redis_example.ini index b0a599b0..3f70e421 100644 --- a/onair/config/redis_example.ini +++ b/onair/config/redis_example.ini @@ -3,7 +3,9 @@ TelemetryFilePath = onair/data/raw_telemetry_data/data_physics_generation/Errors TelemetryFile = 700_crash_to_earth_1.csv MetaFilePath = onair/data/telemetry_configs/ MetaFile = redis_example_CONFIG.json -ParserFileName = onair/data_handling/redis_adapter.py + +[DATA_HANDLING] +DataSourceFile = onair/data_handling/redis_adapter.py [PLUGINS] KnowledgeRepPluginDict = {'knowledge':'plugins/generic/__init__.py'} From 17913461e56293b5156408a592a1cda66f60edcf Mon Sep 17 00:00:00 2001 From: Evan Tung Date: Thu, 11 Jul 2024 17:50:54 -0400 Subject: [PATCH 5/6] fix: revert ExecutionEngine instantiation in tests to use __new__ --- .../src/run_scripts/test_execution_engine.py | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/test/onair/src/run_scripts/test_execution_engine.py b/test/onair/src/run_scripts/test_execution_engine.py index 4d4b2040..08f48705 100644 --- a/test/onair/src/run_scripts/test_execution_engine.py +++ b/test/onair/src/run_scripts/test_execution_engine.py @@ -23,7 +23,7 @@ def test_ExecutionEngine__init__sets_expected_values_but_does_no_calls_when_conf arg_run_name = MagicMock() arg_save_flag = MagicMock() - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.object(cut, 'init_save_paths') mocker.patch.object(cut, 'parse_configs') @@ -59,7 +59,7 @@ def test_ExecutionEngine__init__does_calls_when_config_file_is_an_occupied_strin arg_run_name = MagicMock() arg_save_flag = MagicMock() - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.object(cut, 'init_save_paths') mocker.patch.object(cut, 'parse_configs') @@ -81,7 +81,7 @@ def test_ExecutionEngine__init__does_calls_when_config_file_is_an_occupied_strin def test_ExecutionEngine__init__accepts_no_arguments_using_defaults_instead_with_config_file_default_as_empty_string(mocker): # Arrange - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.object(cut, 'init_save_paths') mocker.patch.object(cut, 'parse_configs') @@ -108,7 +108,7 @@ def test_ExecutionEngine_parse_configs_raises_FileNotFoundError_when_config_cann fake_config_read_result = MagicMock() fake_config_read_result.__len__.return_value = 0 - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -138,7 +138,7 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe fake_config_read_result = MagicMock() fake_config_read_result.__len__.return_value = 1 - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -189,7 +189,7 @@ def test_ExecutionEngine_parse_configs_raises_KeyError_with_config_file_info_whe fake_config_read_result = MagicMock() fake_config_read_result.__len__.return_value = 1 - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -253,7 +253,7 @@ def test_ExecutionEngine_parse_configs_skips_OPTIONS_when_the_required_section_O fake_keys.__len__.return_value = 1 fake_keys.__iter__.return_value = iter([str(fake_plugin)]) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -337,7 +337,7 @@ def test_ExecutionEngine_parse_configs_sets_all_items_without_error(mocker): fake_keys.__len__.return_value = 1 fake_keys.__iter__.return_value = iter([str(fake_plugin)]) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.configparser.ConfigParser', return_value=fake_config) @@ -385,7 +385,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_ValueError_when_config_plugin fake_plugin_dict.body = MagicMock() fake_config_filepath = MagicMock() - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -418,7 +418,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_single fake_values.__iter__.return_value = iter([fake_path]) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -470,7 +470,7 @@ def test_ExecutionEngine_parse_plugins_list_raises_FileNotFoundError_when_any_co fake_values.__iter__.return_value = iter([fake_path] * num_fake_items) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -515,7 +515,7 @@ def test_ExecutionEngine_returns_empty_dict_when_config_dict_is_empty(mocker): fake_config_filepath = MagicMock() fake_temp_plugin_dict = {} - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -555,7 +555,7 @@ def test_ExecutionEngine_returns_expected_dict_when_all_mapped_files_exist(mocke fake_values.__iter__.return_value = iter([fake_path] * num_fake_items) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) cut.config_filepath = fake_config_filepath mocker.patch.object(cut, 'ast_parse_eval', return_value=fake_plugin_dict) @@ -603,7 +603,7 @@ def test_ExecutionEngine_parse_data_sets_the_simDataSource_to_a_new_data_source_ fake_module = MagicMock() fake_parser_class_instance = MagicMock() - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.importlib.util.spec_from_file_location', return_value=fake_spec) @@ -651,7 +651,7 @@ def __init__(self, data_file, meta_file, subsystems_breakdown): fake_module = MagicMock() fake_parser_class_instance = MagicMock() - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.importlib.util.spec_from_file_location', return_value=fake_spec) @@ -674,7 +674,7 @@ def __init__(self, data_file, meta_file, subsystems_breakdown): def test_ExecutionEngine_setup_sim_sets_self_sim_to_new_Simulator(mocker): # Arrange - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) cut.simDataSource = MagicMock() cut.knowledge_rep_plugin_dict = MagicMock() cut.learners_plugin_dict = MagicMock() @@ -703,7 +703,7 @@ def test_ExecutionEngine_setup_sim_sets_self_sim_to_new_Simulator(mocker): def test_ExecutionEngine_run_sim_runs_but_does_not_save_results_when_save_flag_is_False(mocker): # Arrange - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) cut.sim = MagicMock() cut.IO_Enabled = MagicMock() cut.save_flag = False @@ -722,7 +722,7 @@ def test_ExecutionEngine_run_sim_runs_but_does_not_save_results_when_save_flag_i def test_ExecutionEngine_run_sim_runs_and_saves_results_when_save_flag_is_True(mocker): # Arrange - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) cut.sim = MagicMock() cut.IO_Enabled = MagicMock() cut.save_flag = True @@ -751,7 +751,7 @@ def test_ExecutionEngine_init_save_paths_makes_tmp_and_models_and_diagnosis_dire fake_tmp_models_path = str(MagicMock()) fake_tmp_diagnosis_path = str(MagicMock()) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + '.os.path.join', @@ -790,7 +790,7 @@ def test_ExecutionEngine_delete_save_paths_does_nothing_when_save_path_has_no_tm for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + @@ -819,7 +819,7 @@ def test_ExecutionEngine_delete_save_paths_removes_tmp_tree_when_it_exists(mocke for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + @@ -853,7 +853,7 @@ def test_ExecutionEngine_delete_save_paths_prints_error_message_when_rmtree_rais for i in range(pytest.gen.randint(0, 5)): # 0 to 5 fake_dirs.append(str(MagicMock())) - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch.dict(execution_engine.__name__ + '.os.environ', fake_environ) mocker.patch(execution_engine.__name__ + @@ -893,7 +893,7 @@ def test_ExecutionEngine_save_results_creates_expected_save_path_and_copies_prop fake_save_path = fake_onair_save_path + 'saved/' + \ arg_save_name + '_' + fake_complete_time - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.gmtime', return_value=fake_gmtime) @@ -928,7 +928,7 @@ def test_ExecutionEngine_set_run_param_passes_given_arguments_to_setattr(mocker) # Arrange arg_name = MagicMock() arg_val = MagicMock() - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + '.setattr') @@ -947,7 +947,7 @@ def test_ExecutionEngine_ast_parse_eval_returns_call_to_ast_parse_with_mode_eval # Arrange arg_config_list = MagicMock() expected_result = MagicMock() - cut = ExecutionEngine() + cut = ExecutionEngine.__new__(ExecutionEngine) mocker.patch(execution_engine.__name__ + ".ast.parse", return_value=expected_result) From c8f0bab5777cf111a7b5cb68b18371c28c2b4414 Mon Sep 17 00:00:00 2001 From: Evan Tung Date: Thu, 11 Jul 2024 17:59:07 -0400 Subject: [PATCH 6/6] fix: re-add .gitignore to ignore macOS .DS_Store files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f48b3919..3011c814 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,6 @@ dmypy.json # Visual Studio Code .vscode/ + +# macOS +.DS_Store \ No newline at end of file