def parse_schema( self, schema: Dict, source_json_file: str, merged_schema: List[Dict], merged_prefixes: List[str], lenient_prefix=False, merged_entry_tree: Optional[EntryTree] = None, ): r"""Generates ontology code for a parsed schema extracted from a json config. Appends entry code to the corresponding module. Creates a new module file if module is generated for the first time. Args: schema: Ontology dictionary extracted from a json config. source_json_file: Path of the source json file. merged_schema: The merged schema is used to remember all definitions during parsing. merged_prefixes: To remember all prefixes encountered during parsing. lenient_prefix: Whether to remove the constraint on the prefix set. merged_entry_tree: an EntryTree type object and if it's not`None` then after running this function, all the entries from ontology specification file would be parsed into a tree structure with parent and children entries to represent the relationship. Returns: Modules to be imported by dependencies of the current ontology. """ entry_definitions: List[Dict] = schema[SchemaKeywords.definitions] merged_schema.extend(entry_definitions) if SchemaKeywords.prefixes in schema: merged_prefixes.extend(schema[SchemaKeywords.prefixes]) allowed_packages = set( schema.get(SchemaKeywords.prefixes, []) + [DEFAULT_PREFIX]) sorted_prefixes = analyze_packages(allowed_packages) file_desc = file_header( schema.get(SchemaKeywords.description, ""), schema.get(SchemaKeywords.ontology_name, ""), ) for definition in entry_definitions: raw_entry_name = definition[SchemaKeywords.entry_name] validate_entry(raw_entry_name, sorted_prefixes, lenient_prefix) if raw_entry_name in self.allowed_types_tree: warnings.warn( f"Class {raw_entry_name} already present in the " f"ontology, will be overridden.", DuplicateEntriesWarning, ) self.allowed_types_tree[raw_entry_name] = set() # Add the entry definition to the import managers. # This time adding to the root manager so everyone can access it # if needed, but they will only appear in the import list when # requested. # Entry class should be added to the imports before the attributes # to be able to used as the attribute type for the same entry. self.import_managers.root.add_object_to_import(raw_entry_name) # Get various parts of the entry name. en = EntryName(raw_entry_name) entry_item, properties = self.parse_entry(en, definition) # Add it as a defining object. self.import_managers.get( en.module_name).add_defining_objects(raw_entry_name) # Get or set module writer only if the ontology to be generated # is not already installed. if source_json_file not in self.exclude_from_writing: module_writer = self.module_writers.get(en.module_name) module_writer.set_description(file_desc) module_writer.source_file = source_json_file # Add entry item to the writer. module_writer.add_entry(en, entry_item) # Adding entry attributes to the allowed types for validation. for property_name in properties: # Check if the name is allowed. if not property_name.isidentifier(): raise InvalidIdentifierException( f"The property name: {property_name} is not a valid " f"python identifier.") if property_name in self.allowed_types_tree[en.class_name]: warnings.warn( f"Attribute type for the entry {en.class_name} " f"and the attribute {property_name} already present in " f"the ontology, will be overridden", DuplicatedAttributesWarning, ) self.allowed_types_tree[en.class_name].add(property_name) # populate the entry tree based on information if merged_entry_tree is not None: curr_entry_name = en.class_name parent_entry_name = definition["parent_entry"] curr_entry_attributes = self.allowed_types_tree[en.class_name] merged_entry_tree.add_node(curr_entry_name, parent_entry_name, curr_entry_attributes)
def parse_schema(self, schema: Dict, source_json_file: str, merged_schema: List[Dict]): r""" Generates ontology code for a parsed schema extracted from a json config. Appends entry code to the corresponding module. Creates a new module file if module is generated for the first time. Args: schema: Ontology dictionary extracted from a json config. source_json_file: Path of the source json file. merged_schema: The merged schema is used to remember all definitions during parsing. Returns: Modules to be imported by dependencies of the current ontology. """ entry_definitions: List[Dict] = schema[SchemaKeywords.definitions] merged_schema.extend(entry_definitions) allowed_packages = set( schema.get(SchemaKeywords.prefixes, []) + [DEFAULT_PREFIX]) sorted_prefixes = analyze_packages(allowed_packages) file_desc = file_header(schema.get(SchemaKeywords.description, ""), schema.get(SchemaKeywords.ontology_name, "")) for definition in entry_definitions: raw_entry_name = definition[SchemaKeywords.entry_name] validate_entry(raw_entry_name, sorted_prefixes) if raw_entry_name in self.allowed_types_tree: warnings.warn( f"Class {raw_entry_name} already present in the " f"ontology, will be overridden.", DuplicateEntriesWarning) self.allowed_types_tree[raw_entry_name] = set() # Add the entry definition to the import managers. # This time adding to the root manager so everyone can access it # if needed, but they will only appear in the import list when # requested. # Entry class should be added to the imports before the attributes # to be able to used as the attribute type for the same entry. self.import_managers.root.add_object_to_import(raw_entry_name) # Get various parts of the entry name. en = EntryName(raw_entry_name) entry_item, properties = self.parse_entry(en, definition) # Add it as a defining object. self.import_managers.get( en.module_name).add_defining_objects(raw_entry_name) # Get or set module writer only if the ontology to be generated # is not already installed. if source_json_file not in self.exclude_from_writing: module_writer = self.module_writers.get(en.module_name) module_writer.set_description(file_desc) module_writer.source_file = source_json_file # Add entry item to the writer. module_writer.add_entry(en, entry_item) # Adding entry attributes to the allowed types for validation. for property_name in properties: if property_name in self.allowed_types_tree[en.class_name]: warnings.warn( f"Attribute type for the entry {en.class_name} " f"and the attribute {property_name} already present in " f"the ontology, will be overridden", DuplicatedAttributesWarning) self.allowed_types_tree[en.class_name].add(property_name)