Source code for pyggui.configure.asset_builder

"""
Module for building assets objects used in Game object.
"""

import os
import inspect
from typing import Dict, List, Union

from pyggui.exceptions import AssetsDirectoryNotDefinedError, AssetDoesNotExistError


[docs]class Directory: """ Class for building directory objects. Every directories file and sub-directory can be accessed through attributes, if the file/directory does not exist the AssetDoesNotExistError gets raised. Properties: files: Returns a list of file paths of files contained in the directory. directories (List[]): Returns a list of directory paths of sub-directories. empty (bool): If directory is empty. path (str): Will return the directories path. Directory can be iterated through every one of its contents, where sub-directories come first and files second. Printing out the object will output its structure. TODO: Implement repr method. """ def __init__(self, directory_structure: Dict): """ Args: directory_structure (Dict): Dictionary containing information of subdirectories and files. """ self.directory_structure = directory_structure self._files = [] if "_files" in self.directory_structure: self._files = [value["_path"] for value in self.directory_structure["_files"].values()] self._directories = [] # Create directories list, long way without list comprehension, it's more readable for key, value in self.directory_structure.items(): if key != "_path" and "_path" in value: self.directories.append(value["_path"]) @property def files(self) -> List[str]: return self._files @property def directories(self) -> List[str]: return self._directories @property def empty(self) -> bool: return not ((self._files != []) and (self._folders != [])) def __getattr__(self, attr): print(attr) if attr in self: getattr(self, attr) else: # Raise error otherwise asset_path = self.directory_structure["_path"] + "\\" + attr message = f"The asset {asset_path} does not exist in the defined assets directory." raise AssetDoesNotExistError(message) def __iter__(self): for directory in self._directories: yield directory for file in self._files: yield file
[docs]def build_directory(directory_structure: Dict) -> Directory: """ Function builds directory object by setting it appropriate attributes, sub-directories get also added as attributes and recursively built. Args: directory_structure (Dict): Dictionary containing structure, created inside the AssetBuilder.build method. Returns: Directory: Object. """ parent_directory = Directory(directory_structure) def build(dir_structure, directory): setattr(directory, "path", dir_structure["_path"]) for attr in directory.directory_structure: # If sub-directory, set new sub-Directory object if attr != "_path" and attr != "_files": child_dir = Directory(directory_structure=dir_structure[attr]) # Make object setattr(directory, attr, child_dir) # Set is as an attribute build(directory.directory_structure[attr], child_dir) # Recursive build child if "_files" in dir_structure: # If file, return file path for attr in directory.directory_structure["_files"]: setattr(directory, attr, dir_structure["_files"][attr]["_path"]) build(directory_structure, parent_directory) return parent_directory
[docs]class Assets: """ Dummy class for raising error (when fetching attribute) when Asset directory was not defined. """ def __init__(self): self.directory_structure = None def __getattr__(self, attr): message = "The Asset directory was not defined in the initialization of Game object. " \ "Set: assets_directory = path/to/your/assets/folder." raise AssetsDirectoryNotDefinedError(message) def __repr__(self): return "Asset directory was not defined. Define it passing assets_directory to the Game object."
[docs]class AssetBuilder: """ Class used for building the Directory object. """ def __init__(self, directory: str = None): """ Args: directory (str): Path to assets directory. """ # Check directory argument if not directory: # If not passed grab modules parent directory self.directory_path = None else: self.directory_path = os.path.normpath(directory) # Normalize path
[docs] def build(self) -> Dict: """ Method will build and return the correct object for using assets in game. If path was not defined the dummy Asset object gets returned, so if access to some file is attempted an error gets returned. """ if not self.directory_path: # Return dummy object if path was not given return Assets() norm_dir_path = os.path.normpath(self.directory_path) # Normalize path main_structure = {"_path": norm_dir_path} # Main mutable dictionary that will get returned def traverse(structure: Dict, directory: str) -> None: """ Recursive function goes over directory, adding its files in the structure key = 'files' list, recursive call for each directory found. """ for name, full_path in [(path, os.path.join(directory, path)) for path in os.listdir(directory)]: # If file if os.path.isfile(full_path): # Add each file to files key in structure if "_files" not in structure: structure["_files"] = {} # Empty dict name_split = name.split(".") # Get file name and extension _name, _extension = name_split[0], name_split[1] structure["_files"][_name] = {"_extension": _extension, "_path": full_path} # If directory if os.path.isdir(full_path): # Add new structure under basename, recursive call basename = os.path.basename(full_path) structure[basename] = {"_path": full_path} traverse(structure[basename], full_path) # Call function traverse(main_structure, norm_dir_path) # Return directory object return build_directory(main_structure)