class File2clrdat(object): """ file2clrdat class """ def __init__(self, input_path, datfile_path, search_type, matched_dir, unmatched_dir, copy_scanned): """ Class initializer Return: None :type input_path: string :param input_path: file or directory to work with :type datfile_path: string :param datfile_path: work dat file :type search_type: string :param search_type: value that will be searched in dat file """ self.input_path = input_path self.datfile_path = datfile_path self.search_type = search_type self.matched_dir = matched_dir self.unmatched_dir = unmatched_dir self.copy_scanned = copy_scanned input_path = None search_type = None datfile_path = None matched_dir = None unmatched_dir = None copy_scanned = False file_data = None VALID_SEARCH_TYPES = ['size', 'md5', 'crc', 'sha1'] SCRIPT_PATH = os.path.dirname(os.path.realpath(__file__)) clrmamepro_dtd_file = 'C:\lab\_wip\File2clrdat\datafile.dtd' rom_template_file = os.path.join(SCRIPT_PATH, 'ClrMamePro_rom_dat.tpl') rom_template_content = None rom_template_populated = None def generate_rom_data(self): """ Calls functions to according if input is file or directory Return: None """ # TODO: Move input_path initializer arg to this function if os.path.isfile(self.input_path): self.__process_file() elif os.path.isdir(self.input_path): self.__process_directory() else: print("Invalid file or directory") def search_in_datfile(self, search_type, search_content): """ Checks if a given content is inside dat file Return: If content was found, returns filename :type search_type: string :param search_type: Type of search (md5, size, crc...) :type search_content: string :param search_content: Content that will be matched """ with open(self.datfile_path) as f_xml: xml_data = f_xml.read() datafile = objectify.fromstring(xml_data) xml_error = self.file_data.validate_xml_with_dtd(datafile, self.clrmamepro_dtd_file) if xml_error: print('- Provided file is not a valid ClrMamePro dat file.') print(xml_error) sys.exit(5) for games in datafile.getchildren(): for game in games.getchildren(): if game.get(search_type) == search_content: return game.get("name") def __process_file(self): """ Calls all methods to process a file Return: None """ self.file_data = File(self.input_path) self.file_data.get_hashes() if self.datfile_path: rom_found_in_datfile = self.search_in_datfile( self.search_type, getattr(self.file_data, self.search_type)) if rom_found_in_datfile: self.__print_match_found_in_datfile(rom_found_in_datfile) if self.matched_dir: self._move_or_copy_file(self.matched_dir) else: if self.unmatched_dir: self._move_or_copy_file(self.unmatched_dir) self.__get_template_content() self.__populate_template() self.__write_populated_template() else: self.__get_template_content() self.__populate_template() self.__write_populated_template() def _move_or_copy_file(self, destination_dir): """ Move or copy rom file to a given directory. If exists it will be renamed. Return: None :type destination_dir: string :param destination_dir: Directory where file will be moved """ destination_file = os.path.join(destination_dir, self.file_data.name) destination_file = self.file_data.compose_unique_filename(destination_file, 'timestamp') if self.copy_scanned: shutil.copy2(self.file_data.path_and_name, destination_file) else: shutil.move(self.file_data.path_and_name, destination_file) def __print_match_found_in_datfile(self, rom_found_in_datfile): """ Print found match message Return: None :type input_romfile: string :param input_romfile: Input file :type rom_found_in_datfile: string :param rom_found_in_datfile: Rom matched in datfile """ message = """ Input rom file found in provided dat file: - Input rom file: %s - Rom name in dat: %s """ % (self.input_path, rom_found_in_datfile) print(message) def __process_directory_recursive(self): """ Calls all methods to process a directory and all subdirectories Return: None """ for root, dirs, files in os.walk(self.input_path): for thisfile in files: self.input_path = os.path.join(root, thisfile) self.__process_file() def __process_directory(self): """ Calls all methods to process a directory Return: None """ path = self.input_path for thisfile in os.listdir(path): path_and_file = os.path.join(path, thisfile) if os.path.isfile(path_and_file): self.input_path = path_and_file self.__process_file() def __get_template_content(self): """ Gets content of template file Return: None """ f_rom_template = open(self.rom_template_file) self.rom_template_content = string.Template(f_rom_template.read()) f_rom_template.close() def __populate_template(self): """ Puts file data inside template Return: None """ template_dictionary = { 'gameName': self.file_data.nameNoExtension, 'romDescription': self.file_data.nameNoExtension, 'romName': self.file_data.name, 'romSize': self.file_data.size, 'romCrc': self.file_data.crc, 'romMd5': self.file_data.md5, 'romSha1': self.file_data.sha1 } self.rom_template_populated = ( self.rom_template_content.safe_substitute(template_dictionary) ) def __write_populated_template(self): """ Writes rom data to output file Return: None """ if self.unmatched_dir: dst_dir = self.unmatched_dir else: dst_dir = self.file_data.path romdata_file = os.path.join(dst_dir, self.file_data.name + '_romdata') romdata_file = self.file_data.compose_unique_filename(romdata_file, 'timestamp') f_output = open(romdata_file, "w") print(self.rom_template_populated, file=f_output) f_output.close()