def write_xpak(cls, target_source, data): """ write an xpak dict to disk; overwriting an xpak if it exists :param target_source: string path, or \ :obj:`snakeoil.data_source.base` derivative :param data: mapping instance to write into the xpak. :return: xpak instance """ try: old_xpak = cls(target_source) # force access list(old_xpak.keys()) start = old_xpak.xpak_start source_is_path = old_xpak._source_is_path except (MalformedXpak, IOError): source_is_path = isinstance(target_source, str) if source_is_path: try: start = os.lstat(target_source).st_size except FileNotFoundError: start = 0 else: f = target_source.bytes_fileobj(writable=True) f.seek(0, 2) start = f.tell() new_index = [] new_data = [] cur_pos = 0 for key, val in data.items(): if isinstance(val, str): val = val.encode('utf8') if isinstance(key, str): key = key.encode() new_index.append(struct.pack( ">L%isLL" % len(key), len(key), key, cur_pos, len(val))) new_data.append(val) cur_pos += len(val) if source_is_path: # rb+ required since A) binary, B) w truncates from the getgo handle = open(target_source, "r+b") else: handle = target_source.bytes_fileobj(writable=True) joiner = b'' new_index = joiner.join(new_index) new_data = joiner.join(new_data) handle.seek(start, 0) cls.header.write( handle, cls.header_pre_magic, len(new_index), len(new_data)) handle.write(struct.pack( ">%is%is" % (len(new_index), len(new_data)), new_index, new_data)) # the +8 is for the longs for new_index/new_data cls.trailer.write( handle, cls.trailer_pre_magic, len(new_index) + len(new_data) + cls.trailer.size + 8, cls.trailer_post_magic) handle.truncate() handle.close() return Xpak(target_source)
def write_xpak(cls, target_source, data): """ write an xpak dict to disk; overwriting an xpak if it exists :param target_source: string path, or \ :obj:`snakeoil.data_source.base` derivative :param data: mapping instance to write into the xpak. :return: xpak instance """ try: old_xpak = cls(target_source) # force access old_xpak.keys() start = old_xpak.xpak_start source_is_path = old_xpak._source_is_path except (MalformedXpak, IOError): source_is_path = isinstance(target_source, basestring) if source_is_path: try: start = os.lstat(target_source).st_size except OSError as e: if e.errno != errno.ENOENT: raise start = 0 else: f = target_source.bytes_fileobj(writable=True) f.seek(0, 2) start = f.tell() new_index = [] new_data = [] cur_pos = 0 for key, val in data.iteritems(): if isinstance(val, unicode): val = val.encode('utf8') if isinstance(key, unicode): key = key.encode() new_index.append(struct.pack( ">L%isLL" % len(key), len(key), key, cur_pos, len(val))) new_data.append(val) cur_pos += len(val) if source_is_path: # rb+ required since A) binary, B) w truncates from the getgo handle = open(target_source, "r+b") else: handle = target_source.bytes_fileobj(writable=True) joiner = '' if compatibility.is_py3k: # can't do str.join(bytes), thus this. # written this way since the py3k translator doesn't allow us to # just do b'' joiner = joiner.encode() new_index = joiner.join(new_index) new_data = joiner.join(new_data) handle.seek(start, 0) cls.header.write( handle, cls.header_pre_magic, len(new_index), len(new_data)) handle.write(struct.pack( ">%is%is" % (len(new_index), len(new_data)), new_index, new_data)) # the +8 is for the longs for new_index/new_data cls.trailer.write( handle, cls.trailer_pre_magic, len(new_index) + len(new_data) + cls.trailer.size + 8, cls.trailer_post_magic) handle.truncate() handle.close() return Xpak(target_source)
def write_xpak(cls, target_source, data): """ write an xpak dict to disk; overwriting an xpak if it exists :param target_source: string path, or \ :obj:`snakeoil.data_source.base` derivative :param data: mapping instance to write into the xpak. :return: xpak instance """ try: old_xpak = cls(target_source) # force access old_xpak.keys() start = old_xpak.xpak_start source_is_path = old_xpak._source_is_path except (MalformedXpak, IOError): source_is_path = isinstance(target_source, basestring) if source_is_path: try: start = os.lstat(target_source).st_size except OSError as e: if e.errno != errno.ENOENT: raise start = 0 else: f = target_source.bytes_fileobj(writable=True) f.seek(0, 2) start = f.tell() new_index = [] new_data = [] cur_pos = 0 for key, val in data.iteritems(): if isinstance(val, unicode): val = val.encode('utf8') if isinstance(key, unicode): key = key.encode() new_index.append( struct.pack(">L%isLL" % len(key), len(key), key, cur_pos, len(val))) new_data.append(val) cur_pos += len(val) if source_is_path: # rb+ required since A) binary, B) w truncates from the getgo handle = open(target_source, "r+b") else: handle = target_source.bytes_fileobj(writable=True) joiner = '' if compatibility.is_py3k: # can't do str.join(bytes), thus this. # written this way since the py3k translator doesn't allow us to # just do b'' joiner = joiner.encode() new_index = joiner.join(new_index) new_data = joiner.join(new_data) handle.seek(start, 0) cls.header.write(handle, cls.header_pre_magic, len(new_index), len(new_data)) handle.write( struct.pack(">%is%is" % (len(new_index), len(new_data)), new_index, new_data)) # the +8 is for the longs for new_index/new_data cls.trailer.write( handle, cls.trailer_pre_magic, len(new_index) + len(new_data) + cls.trailer.size + 8, cls.trailer_post_magic) handle.truncate() handle.close() return Xpak(target_source)