def make_module_dirs(self, tempdir: str, destination: str, include_init: bool): """ Create entry sub-directories with .generated file to indicate the subdirectory is created by this procedure. No such file will be added if the directory already exists. Args: tempdir: A temp directory to create the structure, code will be first generated here. destination: The destination directory where the code should be placed include_init: True if `__init__.py` is to be generated in existing packages in which `__init__.py` does not already exists Returns: """ entry_dir_split = split_file_path(self.pkg_dir) rel_dir_paths = it.accumulate(entry_dir_split, os.path.join) for rel_dir_path in rel_dir_paths: temp_path = os.path.join(tempdir, rel_dir_path) if not os.path.exists(temp_path): os.mkdir(temp_path) dest_path = os.path.join(destination, rel_dir_path) dest_path_exists = os.path.exists(dest_path) if not dest_path_exists: Path(os.path.join(temp_path, AUTO_GEN_FILENAME)).touch() # Create init file if not dest_path_exists or include_init: init_file_path = os.path.join(temp_path, '__init__.py') with open(init_file_path, 'w') as init_file: init_file.write(f'# {AUTO_GEN_SIGNATURE}\n')
def parse_config(self, schema: Dict, modules_to_import: List[str], destination_dir: str) -> List[str]: r""" Generates ontology code for ontology dictionary 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. modules_to_import: Dependencies to be imported by generated modules. Returns: Modules to be imported by dependencies of the current ontology. """ entry_definitions: List[Dict] = schema["definitions"] allowed_packages = set( schema.get("additional_prefixes", []) + ["ft.onto"]) modules_to_import += list(allowed_packages) new_modules_to_import = [] for definition in entry_definitions: entry_name = definition["entry_name"] entry_splits = entry_name.split('.') filename, name = entry_name.split('.')[-2:] pkg = '.'.join(entry_splits[0:-2]) if len(entry_splits) < 4: raise ValueError(f"EntryNameNotComplete: {entry_name} is not " f"complete, please provide full package, " f"module and class name.") if pkg not in allowed_packages: raise ValueError(f"EntryPackageConflict: Package name for " f"{entry_name} conflicts with the provided " f"prefixes.") self.ref_to_full_name[name] = entry_name self.ref_to_full_name[entry_name] = entry_name if entry_name in self.allowed_types_tree: warnings.warn(f"DuplicateEntryWarning: " f"Class {entry_name} already present in the " f"ontology, will be overridden.") self.allowed_types_tree[entry_name] = set() entry_item, properties = self.parse_entry(name, entry_name, definition) module_name: str = f"{pkg}.{filename}" class_name: str = f"{module_name}.{name}" try: # Creating entry directory and file in the tempdir if required. entry_pkg_dir = pkg.replace('.', '/') entry_dir: str = os.path.join(self.tempdir, entry_pkg_dir) entry_file: str = f'{os.path.join(entry_dir, filename)}.py' file_desc: str = 'Automatically generated file. ' \ 'Do not change manually.' all_imports = self.required_imports + modules_to_import file_item = FileItem(entry_item, entry_file, self.ignore_errors, file_desc, all_imports) # Path(entry_dir).mkdir(parents=True, exist_ok=True) # Create entry sub-directories with .generated file if the # subdirectory is created programmatically # Peak if the folder exists at the destination directory entry_dir_split = utils.split_file_path(entry_pkg_dir) rel_dir_paths = it.accumulate(entry_dir_split, os.path.join) for rel_dir_path in rel_dir_paths: temp_path = os.path.join(self.tempdir, rel_dir_path) dest_path = os.path.join(destination_dir, rel_dir_path) if not os.path.exists(temp_path): os.mkdir(temp_path) if not os.path.exists(dest_path): Path(os.path.join(temp_path, '.generated')).touch() # Creating the file if it does not exist. with open(entry_file, 'a+') as f: f.write(file_item.to_code(0)) except ValueError: self.cleanup_generated_ontology(self.tempdir, is_forced=True) raise # Modules to be imported by the dependencies. new_modules_to_import.append(module_name) # Adding entry attributes to the allowed types for validation. for property_name in properties: if property_name in self.allowed_types_tree[class_name]: warnings.warn( f"DuplicateAttributeWarning: " f"Attribute type for the entry {class_name} and " f"the attribute {property_name} already present in " f"the ontology, will be overridden") self.allowed_types_tree[class_name].add(property_name) return new_modules_to_import