Esempio n. 1
0
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()