import xml.etree.ElementTree import hashdb class DatImportError(Exception): '''This error is raised when a DAT import fails.''' # TODO: l o g g i n g # TODO: Consider using a context object to avoid keeping large XML trees in memory. class Dat: '''A Dat object processes DAT files into the data structures defined in hashdb. ''' def __init__(self, filename): '''Open the given DAT file and gather metadata from it.''' xml_tree = xml.etree.ElementTree.parse(filename) self._xml_root = xml_tree.getroot() dat_header = self._xml_root.find('header') self.info = hashdb.DatInfo(name=dat_header.find('name').text, description=dat_header.find('description').text, platform=None, version=dat_header.find('version').text) def set_platform(self, platform_info): ''' Set a platform for this DAT file. DAT files don't include platform metadata, but are all platform-specific. ''' new_info = hashdb.DatInfo(name=self.info.name, description=self.info.description, platform=platform_info.shortcode, version=self.info.version) self.info = new_info def set_name(self, new_name): ''' Override the DAT file's name. DAT files often have less-than-helpful names. ''' new_info = hashdb.DatInfo(name=new_name, description=self.info.description, platform=self.info.platform, version=self.info.version) self.info = new_info def read_all_hashes(self): '''Read every hash in the DAT file and return it as a large list of RomInfo tuples.''' if self.info.platform is None: raise DatImportError('DAT platform not set.') rom_info_list = [] all_rom_entries = self._xml_root.findall('.//rom') for rom in all_rom_entries: rom_info = hashdb.RomInfo(sha1sum=rom.get('sha1'), filename=rom.get('name'), platform=self.info.platform, datorigin=self.info.name) rom_info_list.append(rom_info) return rom_info_list