def is_pluggable_section(section_name): section_name = JSONSchema.format_section_name(section_name) for pluggable_type in local_pluggables_types(): if section_name == pluggable_type.value: return True return False
def test_pluggable_configuration(self): """ pluggable configuration tests """ err_msgs = [] for pluggable_type in local_pluggables_types(): for pluggable_name in local_pluggables(pluggable_type): cls = get_pluggable_class(pluggable_type, pluggable_name) configuration = get_pluggable_configuration( pluggable_type, pluggable_name) if not isinstance(configuration, dict): err_msgs.append( "{} configuration isn't a dictionary.".format(cls)) continue if pluggable_type in [ PluggableType.ALGORITHM, PluggableType.INPUT ]: if not configuration.get('problems', []): err_msgs.append( "{} missing or empty 'problems' section.".format( cls)) schema_found = False for configuration_name, configuration_value in configuration.items( ): if configuration_name in ['problems', 'depends']: if not isinstance(configuration_value, list): err_msgs.append( "{} configuration section:'{}' isn't a list.". format(cls, configuration_name)) continue if configuration_name == 'depends': err_msgs.extend( self._validate_depends(cls, configuration_value)) continue if configuration_name == 'input_schema': schema_found = True if not isinstance(configuration_value, dict): err_msgs.append( "{} configuration section:'{}' isn't a dictionary." .format(cls, configuration_name)) continue err_msgs.extend( self._validate_schema(cls, configuration_value)) continue if not schema_found: err_msgs.append( "{} configuration missing schema.".format(cls)) if err_msgs: self.fail('\n'.join(err_msgs))
def __init__(self, input=None): """Create Parser object.""" json_schema = JSONSchema( os.path.join(os.path.dirname(__file__), 'input_schema.json')) # get some properties from algorithms schema json_schema.copy_section_from_aqua_schema( PluggableType.ALGORITHM.value) json_schema.copy_section_from_aqua_schema(JSONSchema.BACKEND) json_schema.copy_section_from_aqua_schema(JSONSchema.PROBLEM) json_schema.schema['properties'][JSONSchema.PROBLEM]['properties'][ InputParser.AUTO_SUBSTITUTIONS] = { "type": "boolean", "default": "true" } super().__init__(json_schema) # limit Chemistry problems to energy and excited_states chemistry_problems = [ problem for problem in self.json_schema.get_property_default_values( JSONSchema.PROBLEM, JSONSchema.NAME) if any(problem == item.value for item in ChemistryProblem) ] self.json_schema.schema['properties'][JSONSchema.PROBLEM]['properties'][JSONSchema.NAME]['oneOf'] = \ [{'enum': chemistry_problems}] self._json_schema.commit_changes() # --- self._inputdict = None if input is not None: if isinstance(input, dict): self._inputdict = input elif isinstance(input, str): self._filename = input else: raise QiskitChemistryError("Invalid parser input type.") self._section_order = [ JSONSchema.NAME, JSONSchema.PROBLEM, InputParser.DRIVER, InputParser._UNKNOWN, InputParser.OPERATOR, PluggableType.ALGORITHM.value ] for pluggable_type in local_pluggables_types(): if pluggable_type not in [ PluggableType.INPUT, PluggableType.ALGORITHM ]: self._section_order.append(pluggable_type.value) self._section_order.extend([JSONSchema.BACKEND, InputParser._UNKNOWN]) jsonfile = os.path.join(os.path.dirname(__file__), 'substitutions.json') with open(jsonfile) as json_file: self._substitutions = json.load(json_file)
def merge_default_values(self): section_names = self.get_section_names() if JSONSchema.NAME not in section_names: self.set_section(JSONSchema.NAME) if PluggableType.ALGORITHM.value in section_names: if JSONSchema.PROBLEM not in section_names: self.set_section(JSONSchema.PROBLEM) self.json_schema.update_backend_schema() self.json_schema.update_pluggable_schemas(self) self._merge_dependencies() self._update_driver_sections() self._update_driver_input_schemas() self._update_operator_input_schema() # do not merge any pluggable that doesn't have name default in schema default_section_names = [] pluggable_type_names = [ pluggable_type.value for pluggable_type in local_pluggables_types() ] for section_name in self.get_default_section_names(): if section_name in pluggable_type_names: if self.get_property_default_value( section_name, JSONSchema.NAME) is not None: default_section_names.append(section_name) else: default_section_names.append(section_name) section_names = set( self.get_section_names()) | set(default_section_names) for section_name in section_names: if section_name not in self._sections: self.set_section(section_name) new_properties = self.get_section_default_properties(section_name) if new_properties is not None: if self.section_is_text(section_name): text = self.get_section_text(section_name) if (text is None or len(text) == 0) and \ isinstance(new_properties, str) and \ len(new_properties) > 0 and \ text != new_properties: self.set_section_data(section_name, new_properties) else: properties = self.get_section_properties(section_name) new_properties.update(properties) self.set_section_properties(section_name, new_properties) self._sections = self._order_sections(self._sections)
def _merge_dependencies(self): algo_name = self.get_section_property(PluggableType.ALGORITHM.value, JSONSchema.NAME) if algo_name is None: return config = get_pluggable_configuration(PluggableType.ALGORITHM, algo_name) pluggable_dependencies = [] if 'depends' not in config else config[ 'depends'] pluggable_defaults = {} if 'defaults' not in config else config[ 'defaults'] for pluggable_type in local_pluggables_types(): if pluggable_type not in [PluggableType.INPUT, PluggableType.ALGORITHM] and \ pluggable_type.value not in pluggable_dependencies: # remove pluggables from input that are not in the dependencies if pluggable_type.value in self._sections: del self._sections[pluggable_type.value] section_names = self.get_section_names() for pluggable_type in pluggable_dependencies: pluggable_name = None new_properties = {} if pluggable_type in pluggable_defaults: for key, value in pluggable_defaults[pluggable_type].items(): if key == JSONSchema.NAME: pluggable_name = pluggable_defaults[pluggable_type][ key] else: new_properties[key] = value if pluggable_name is None: continue if pluggable_type not in section_names: self.set_section(pluggable_type) if self.get_section_property(pluggable_type, JSONSchema.NAME) is None: self.set_section_property(pluggable_type, JSONSchema.NAME, pluggable_name) if pluggable_name == self.get_section_property( pluggable_type, JSONSchema.NAME): properties = self.get_section_properties(pluggable_type) if new_properties: new_properties.update(properties) else: new_properties = properties self.set_section_properties(pluggable_type, new_properties)
def update_pluggable_schemas(self, input_parser): """ Updates schemas of all pluggables Args: input_parser (obj): input parser """ # find algorithm default_algo_name = self.get_property_default_value( PluggableType.ALGORITHM.value, JSONSchema.NAME) algo_name = input_parser.get_section_property( PluggableType.ALGORITHM.value, JSONSchema.NAME, default_algo_name) # update algorithm scheme if algo_name is not None: self._update_pluggable_schema(PluggableType.ALGORITHM.value, algo_name, default_algo_name) # update algorithm dependencies scheme config = {} if algo_name is None else get_pluggable_configuration( PluggableType.ALGORITHM, algo_name) classical = config.get('classical', False) # update algorithm backend from schema if it is classical or not if classical: if JSONSchema.BACKEND in self._schema['properties']: del self._schema['properties'][JSONSchema.BACKEND] else: if JSONSchema.BACKEND not in self._schema['properties']: self._schema['properties'][ JSONSchema.BACKEND] = self._original_schema['properties'][ JSONSchema.BACKEND] self.update_backend_schema(input_parser) pluggable_dependencies = config.get('depends', []) # remove pluggables from schema that are not in the dependencies of algorithm pluggable_dependency_names = [ item['pluggable_type'] for item in pluggable_dependencies if 'pluggable_type' in item ] for pluggable_type in local_pluggables_types(): if pluggable_type not in [PluggableType.INPUT, PluggableType.ALGORITHM] and \ pluggable_type.value not in pluggable_dependency_names and \ pluggable_type.value in self._schema['properties']: del self._schema['properties'][pluggable_type.value] self._update_dependency_schemas(pluggable_dependencies, input_parser)
def _update_dependency_sections(self): algo_name = self.get_section_property(PluggableType.ALGORITHM.value, JSONSchema.NAME) config = {} if algo_name is None else get_pluggable_configuration( PluggableType.ALGORITHM, algo_name) classical = config['classical'] if 'classical' in config else False pluggable_dependencies = [] if 'depends' not in config else config[ 'depends'] pluggable_defaults = {} if 'defaults' not in config else config[ 'defaults'] for pluggable_type in local_pluggables_types(): # remove pluggables from input that are not in the dependencies if pluggable_type not in [PluggableType.INPUT, PluggableType.ALGORITHM] and \ pluggable_type.value not in pluggable_dependencies and \ pluggable_type.value in self._sections: del self._sections[pluggable_type.value] for pluggable_type in pluggable_dependencies: pluggable_name = None if pluggable_type in pluggable_defaults: if JSONSchema.NAME in pluggable_defaults[pluggable_type]: pluggable_name = pluggable_defaults[pluggable_type][ JSONSchema.NAME] if pluggable_name is not None and pluggable_type not in self._sections: self.set_section_property(pluggable_type, JSONSchema.NAME, pluggable_name) # update default values for new dependency pluggable types self.set_section_properties( pluggable_type, self.get_section_default_properties(pluggable_type)) # update backend based on classical if classical: if JSONSchema.BACKEND in self._sections: del self._sections[JSONSchema.BACKEND] else: if JSONSchema.BACKEND not in self._sections: self.set_section_properties( JSONSchema.BACKEND, self.get_section_default_properties(JSONSchema.BACKEND)) # reorder sections self._sections = self._order_sections(self._sections)
def __init__(self, input_value=None): """Create Parser object.""" super().__init__(JSONSchema(os.path.join(os.path.dirname(__file__), 'input_schema.json'))) if input is not None: if isinstance(input_value, dict): self._sections = input_value elif isinstance(input_value, str): self._filename = input_value else: raise AquaError("Invalid parser input type.") self._section_order = [JSONSchema.PROBLEM, PluggableType.INPUT.value, PluggableType.ALGORITHM.value] for pluggable_type in local_pluggables_types(): if pluggable_type not in [PluggableType.INPUT, PluggableType.ALGORITHM]: self._section_order.append(pluggable_type.value) self._section_order.extend([JSONSchema.BACKEND, InputParser._UNKNOWN])
def _load_data(self): if self._data_loaded: return from qiskit.aqua import (local_pluggables_types, local_pluggables, get_pluggable_configuration) self._schema_property_titles = OrderedDict() self._sections = OrderedDict() for pluggable_type in sorted(local_pluggables_types(), key=lambda x: x.value): self._sections[pluggable_type.value] = OrderedDict() self._schema_property_titles[pluggable_type.value] = OrderedDict() for pluggable_name in sorted(local_pluggables(pluggable_type)): config = copy.deepcopy( get_pluggable_configuration(pluggable_type, pluggable_name)) self._populate_section(pluggable_type.value, pluggable_name, config) self._data_loaded = True
def update_pluggable_input_schemas(self, input_parser): """ Updates schemas of all pluggables Args: input_parser (obj): input parser """ # find algorithm default_algo_name = self.get_property_default_value( PluggableType.ALGORITHM.value, JSONSchema.NAME) algo_name = input_parser.get_section_property( PluggableType.ALGORITHM.value, JSONSchema.NAME, default_algo_name) # update algorithm scheme if algo_name is not None: self._update_pluggable_input_schema(PluggableType.ALGORITHM.value, algo_name, default_algo_name) # update algorithm depoendencies scheme config = {} if algo_name is None else get_pluggable_configuration( PluggableType.ALGORITHM, algo_name) classical = config['classical'] if 'classical' in config else False pluggable_dependencies = [] if 'depends' not in config else config[ 'depends'] pluggable_defaults = {} if 'defaults' not in config else config[ 'defaults'] pluggable_types = local_pluggables_types() for pluggable_type in pluggable_types: if pluggable_type not in [PluggableType.INPUT, PluggableType.ALGORITHM] and \ pluggable_type.value not in pluggable_dependencies: # remove pluggables from schema that ate not in the dependencies if pluggable_type.value in self._schema['properties']: del self._schema['properties'][pluggable_type.value] # update algorithm backend from schema if it is classical or not if classical: if JSONSchema.BACKEND in self._schema['properties']: del self._schema['properties'][JSONSchema.BACKEND] else: if JSONSchema.BACKEND not in self._schema['properties']: self._schema['properties'][ JSONSchema.BACKEND] = self._original_schema['properties'][ JSONSchema.BACKEND] # update schema with dependencies for pluggable_type in pluggable_dependencies: pluggable_name = None default_properties = {} if pluggable_type in pluggable_defaults: for key, value in pluggable_defaults[pluggable_type].items(): if key == JSONSchema.NAME: pluggable_name = pluggable_defaults[pluggable_type][ key] else: default_properties[key] = value default_name = pluggable_name pluggable_name = input_parser.get_section_property( pluggable_type, JSONSchema.NAME, pluggable_name) # update dependency schema self._update_pluggable_input_schema(pluggable_type, pluggable_name, default_name) for property_name in self._schema['properties'][pluggable_type][ 'properties'].keys(): if property_name in default_properties: self._schema['properties'][pluggable_type]['properties'][ property_name]['default'] = default_properties[ property_name]