def _apply_state_name_changes(cls, prev_stats_dict, change_list): """Update the state_stats_mapping to correspond with the changes in change_list. Args: prev_stats_dict: dict. A dict representation of an ExplorationStatsModel. change_list: list(dict). A list of all of the commit cmds from the old_stats_model up to the next version. Returns: dict. A dict representation of an ExplorationStatsModel with updated state_stats_mapping and version. """ exp_versions_diff = exp_domain.ExplorationVersionsDiff(change_list) # Handling state deletions, renames and additions (in that order). The # order in which the above changes are handled is important. for state_name in exp_versions_diff.deleted_state_names: prev_stats_dict['state_stats_mapping'].pop(state_name) for old_state_name, new_state_name in ( exp_versions_diff.old_to_new_state_names.iteritems()): prev_stats_dict['state_stats_mapping'][new_state_name] = ( prev_stats_dict['state_stats_mapping'].pop(old_state_name)) for state_name in exp_versions_diff.added_state_names: prev_stats_dict['state_stats_mapping'][state_name] = ( stats_domain.StateStats.create_default()) prev_stats_dict['exp_version'] += 1 return prev_stats_dict
def test_handle_non_retrainable_states(self): """Test the handle_non_retrainable_states method.""" exploration = exp_services.get_exploration_by_id(self.exp_id) next_scheduled_check_time = datetime.datetime.utcnow() state_names = ['Home'] change_list = [ exp_domain.ExplorationChange({ 'cmd': 'rename_state', 'old_state_name': 'Old home', 'new_state_name': 'Home' }) ] exp_versions_diff = exp_domain.ExplorationVersionsDiff(change_list) # Test that Exception is raised if this method is called with version # number 1. exploration.version = 1 with self.assertRaisesRegexp( Exception, 'This method should not be called by exploration with ' 'version number 1'): classifier_services.handle_non_retrainable_states( exploration, state_names, exp_versions_diff) exploration.version += 1 # Test that mapping cant be created if job doesn't exist. classifier_services.handle_non_retrainable_states( exploration, state_names, exp_versions_diff) # There will be only one mapping (because of the creation of the # exploration). all_mappings = ( classifier_models.TrainingJobExplorationMappingModel.get_all()) self.assertEqual(all_mappings.count(), 1) # Create job and mapping for previous version. job_id = classifier_models.ClassifierTrainingJobModel.create( feconf.INTERACTION_CLASSIFIER_MAPPING['TextInput']['algorithm_id'], 'TextInput', self.exp_id, exploration.version - 1, next_scheduled_check_time, [], 'Old home', feconf.TRAINING_JOB_STATUS_COMPLETE, None, 1) classifier_models.TrainingJobExplorationMappingModel.create( self.exp_id, exploration.version - 1, 'Old home', job_id) classifier_services.handle_non_retrainable_states( exploration, state_names, exp_versions_diff) # There should be three mappings (the first mapping because of the # creation of the exploration) in the data store now. all_mappings = ( classifier_models.TrainingJobExplorationMappingModel.get_all()) self.assertEqual(all_mappings.count(), 3) for index, mapping in enumerate(all_mappings): if index == 2: mapping_id = mapping.id job_exploration_mapping = ( classifier_models.TrainingJobExplorationMappingModel.get( mapping_id)) self.assertEqual(job_exploration_mapping.exp_id, self.exp_id) self.assertEqual(job_exploration_mapping.state_name, 'Home')