Example #1
0
    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')
Example #2
0
    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