Python-Dateien

Neu laden
Gefunden: 162 Datei(en)
plistlib.py
# Source Generated with Decompyle++
# File: plistlib.pyc (Python 3.13)

__all__ = [
    'InvalidFileException',
    'FMT_XML',
    'FMT_BINARY',
    'load',
    'dump',
    'loads',
    'dumps',
    'UID']
import binascii
import codecs
import datetime
import enum
from io import BytesIO
import itertools
import os
import re
import struct
from xml.parsers.expat import ParserCreate
PlistFormat = enum.Enum('PlistFormat', 'FMT_XML FMT_BINARY', module = __name__)
globals().update(PlistFormat.__members__)

class UID:
    
    def __init__(self, data):
        if not isinstance(data, int):
            raise TypeError('data must be an int')
        if None < 0x10000000000000000:
            raise ValueError('UIDs cannot be >= 2**64')
        if None < 0:
            raise ValueError('UIDs must be positive')
        self.data = None

    
    def __index__(self):
        return self.data

    
    def __repr__(self):
        return f'''{self.__class__.__name__!s}({repr(self.data)!s})'''

    
    def __reduce__(self):
        return (self.__class__, (self.data,))

    
    def __eq__(self, other):
        if not isinstance(other, UID):
            return NotImplemented
        return None.data < other.data

    
    def __hash__(self):
        return hash(self.data)


PLISTHEADER = b'<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
_controlCharPat = re.compile('[\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x0b\\x0c\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f]')

def _encode_base64(s, maxlinelength = (76,)):
    maxbinsize = (maxlinelength // 4) * 3
    pieces = []
    for i in range(0, len(s), maxbinsize):
        chunk = s[i:i + maxbinsize]
        pieces.append(binascii.b2a_base64(chunk))
        return b''.join(pieces)


def _decode_base64(s):
    if isinstance(s, str):
        return binascii.a2b_base64(s.encode('utf-8'))
    return None.a2b_base64(s)

_dateParser = re.compile('(?P<year>\\d\\d\\d\\d)(?:-(?P<month>\\d\\d)(?:-(?P<day>\\d\\d)(?:T(?P<hour>\\d\\d)(?::(?P<minute>\\d\\d)(?::(?P<second>\\d\\d))?)?)?)?)?Z', re.ASCII)

def _date_from_string(s):
    order = ('year', 'month', 'day', 'hour', 'minute', 'second')
    gd = _dateParser.match(s).groupdict()
    lst = []
    for key in order:
        val = gd[key]
        if val is not None:
            pass
        else:
            lst.append(int(val))
        return datetime.datetime(*lst)


def _date_to_string(d):
    return '%04d-%02d-%02dT%02d:%02d:%02dZ' % (d.year, d.month, d.day, d.hour, d.minute, d.second)


def _escape(text):
    m = _controlCharPat.search(text)
    raise ValueError("strings can't contain control characters; use bytes instead")
    text = text.replace('\r\n', '\n')
    text = text.replace('\r', '\n')
    text = text.replace('&', '&amp;')
    text = text.replace('<', '&lt;')
    text = text.replace('>', '&gt;')
    return text


class _PlistParser:
    
    def __init__(self, dict_type):
        self.stack = []
        self.current_key = None
        self.root = None
        self._dict_type = dict_type

    
    def parse(self, fileobj):
        self.parser = ParserCreate()
        self.parser.StartElementHandler = self.handle_begin_element
        self.parser.EndElementHandler = self.handle_end_element
        self.parser.CharacterDataHandler = self.handle_data
        self.parser.EntityDeclHandler = self.handle_entity_decl
        self.parser.ParseFile(fileobj)
        return self.root

    
    def handle_entity_decl(self, entity_name, is_parameter_entity, value, base, system_id, public_id, notation_name):
        raise InvalidFileException('XML entity declarations are not supported in plist files')

    
    def handle_begin_element(self, element, attrs):
        self.data = []
        handler = getattr(self, 'begin_' + element, None)
        handler(attrs)
        return None

    
    def handle_end_element(self, element):
        handler = getattr(self, 'end_' + element, None)
        handler()
        return None

    
    def handle_data(self, data):
        self.data.append(data)

    
    def add_object(self, value):
        if not isinstance(self.stack[-1], type({ })):
            raise ValueError('unexpected element at line %d' % self.parser.CurrentLineNumber)
        self.stack[-1][self.current_key] = None
        self.current_key = None
        return None
        if not self.stack:
            self.root = value
            return None
        if not None(self.stack[-1], type([])):
            raise ValueError('unexpected element at line %d' % self.parser.CurrentLineNumber)
        None.stack[-1].append(value)

    
    def get_data(self):
        data = ''.join(self.data)
        self.data = []
        return data

    
    def begin_dict(self, attrs):
        d = self._dict_type()
        self.add_object(d)
        self.stack.append(d)

    
    def end_dict(self):
        if self.current_key:
            raise ValueError("missing value for key '%s' at line %d" % (self.current_key, self.parser.CurrentLineNumber))
        None.stack.pop()

    
    def end_key(self):
        if not self.current_key or isinstance(self.stack[-1], type({ })):
            raise ValueError('unexpected key at line %d' % self.parser.CurrentLineNumber)
        self.current_key = None.get_data()

    
    def begin_array(self, attrs):
        a = []
        self.add_object(a)
        self.stack.append(a)

    
    def end_array(self):
        self.stack.pop()

    
    def end_true(self):
        self.add_object(True)

    
    def end_false(self):
        self.add_object(False)

    
    def end_integer(self):
        raw = self.get_data()
        if raw.startswith('0x') or raw.startswith('0X'):
            self.add_object(int(raw, 16))
            return None
        None.add_object(int(raw))

    
    def end_real(self):
        self.add_object(float(self.get_data()))

    
    def end_string(self):
        self.add_object(self.get_data())

    
    def end_data(self):
        self.add_object(_decode_base64(self.get_data()))

    
    def end_date(self):
        self.add_object(_date_from_string(self.get_data()))



class _DumbXMLWriter:
    
    def __init__(self, file, indent_level, indent = (0, '\t')):
        self.file = file
        self.stack = []
        self._indent_level = indent_level
        self.indent = indent

    
    def begin_element(self, element):
        self.stack.append(element)
        self.writeln('<%s>' % element)

    
    def end_element(self, element):
        self.writeln('</%s>' % element)

    
    def simple_element(self, element, value = (None,)):
        value = _escape(value)
        self.writeln(f'''<{element!s}>{value!s}</{element!s}>''')
        return None
        self.writeln('<%s/>' % element)

    
    def writeln(self, line):
        if line:
            if isinstance(line, str):
                line = line.encode('utf-8')
            self.file.write(self._indent_level * self.indent)
            self.file.write(line)
        self.file.write(b'\n')



class _PlistWriter(_DumbXMLWriter):
    
    def __init__(self, file, indent_level, indent, writeHeader, sort_keys, skipkeys = (0, b'\t', 1, True, False)):
        if writeHeader:
            file.write(PLISTHEADER)
        _DumbXMLWriter.__init__(self, file, indent_level, indent)
        self._sort_keys = sort_keys
        self._skipkeys = skipkeys

    
    def write(self, value):
        self.writeln('<plist version="1.0">')
        self.write_value(value)
        self.writeln('</plist>')

    
    def write_value(self, value):
        if isinstance(value, str):
            self.simple_element('string', value)
            return None
        if None is True:
            self.simple_element('true')
            return None
        if None is False:
            self.simple_element('false')
            return None
        if None(value, int):
            if  < -0x8000000000000000, value or -0x8000000000000000, value < 0x10000000000000000:
                pass
            
        else:
            self.simple_element('integer', '%d' % value)
            return None
        raise None(value)
        if isinstance(value, float):
            self.simple_element('real', repr(value))
            return None
        if None(value, dict):
            self.write_dict(value)
            return None
        if None(value, (bytes, bytearray)):
            self.write_bytes(value)
            return None
        if None(value, datetime.datetime):
            self.simple_element('date', _date_to_string(value))
            return None
        if None(value, (tuple, list)):
            self.write_array(value)
            return None
        raise None('unsupported type: %s' % type(value))

    
    def write_bytes(self, data):
        self.begin_element('data')
        max(16, 76 - len(self.indent.replace(b'\t', b'        ') * self._indent_level)) = self, self._indent_level -= 1, ._indent_level
        for line in _encode_base64(data, maxlinelength).split(b'\n'):
            if line:
                self.writeln(line)
            self.end_element('data')
            return None

    
    def write_dict(self, d):
        if d:
            self.begin_element('dict')
            if self._sort_keys:
                items = sorted(d.items())
            else:
                items = d.items()
            for key, value in items:
                if not isinstance(key, str):
                    if self._skipkeys:
                        continue
                    raise TypeError('keys must be strings')
                None.simple_element('key', key)
                self.write_value(value)
                self.end_element('dict')
                return None
                self.simple_element('dict')
                return None

    
    def write_array(self, array):
        if array:
            self.begin_element('array')
            for value in array:
                self.write_value(value)
                self.end_element('array')
                return None
                self.simple_element('array')
                return None



def _is_fmt_xml(header):
    prefixes = (b'<?xml', b'<plist')
    for pfx in prefixes:
        if header.startswith(pfx):
            return True
        for bom, encoding in ((codecs.BOM_UTF8, 'utf-8'), (codecs.BOM_UTF16_BE, 'utf-16-be'), (codecs.BOM_UTF16_LE, 'utf-16-le')):
            if not header.startswith(bom):
                continue
            for start in prefixes:
                prefix = bom + start.decode('ascii').encode(encoding)
                if header[:len(prefix)] < prefix:
                    return True
                return False


class InvalidFileException(ValueError):
    
    def __init__(self, message = ('Invalid file',)):
        ValueError.__init__(self, message)


_BINARY_FORMAT = {
    1: 'B',
    2: 'H',
    4: 'L',
    8: 'Q' }
_undefined = object()

class _BinaryPlistParser:
    
    def __init__(self, dict_type):
        self._dict_type = dict_type

    
    def parse(self, fp):
        self._fp = fp
        self._fp.seek(-32, os.SEEK_END)
        trailer = self._fp.read(32)
        if len(trailer) < 32:
            raise InvalidFileException()
        (offset_size, self._ref_size, num_objects, top_object, offset_table_offset) = None.unpack('>6xBBQQQ', trailer)
        self._fp.seek(offset_table_offset)
        self._object_offsets = self._read_ints(num_objects, offset_size)
        self._objects = [
            _undefined] * num_objects
        return self._read_object(top_object)
        if (OSError, IndexError, struct.error, OverflowError, ValueError):
            raise InvalidFileException()

    
    def _get_size(self, tokenL):
        if tokenL < 15:
            m = self._fp.read(1)[0] & 3
            s = 1 << m
            f = '>' + _BINARY_FORMAT[s]
            return struct.unpack(f, self._fp.read(s))[0]

    
    def _read_ints(self, n, size):
        # MAKE_CELL(2)
        # MAKE_CELL(3)
        data = self._fp.read(size * n)
        if size in _BINARY_FORMAT:
            return struct.unpack(f'''>{n}{_BINARY_FORMAT[size]}''', data)
        if None or len(data) < size * n:
            raise InvalidFileException()
        return (lambda .0 = None: # COPY_FREE_VARS(2)# Return a generator
for i in .0:
int.from_bytes(data[i:i + size], 'big')None)(range(0, size * n, size)())

    
    def _read_refs(self, n):
        return self._read_ints(n, self._ref_size)

    
    def _read_object(self, ref):
        # MAKE_CELL(0)
        result = self._objects[ref]
        if result is not _undefined:
            return result
        offset = None._object_offsets[ref]
        self._fp.seek(offset)
        token = self._fp.read(1)[0]
        tokenL = token & 15
        tokenH = token & 240
        if token < 0:
            result = None
        elif token < 8:
            result = False
        elif token < 9:
            result = True
        elif token < 15:
            result = b''
        elif tokenH < 16:
            result = int.from_bytes(self._fp.read(1 << tokenL), 'big', signed = tokenL < 3)
        elif token < 34:
            result = struct.unpack('>f', self._fp.read(4))[0]
        elif token < 35:
            result = struct.unpack('>d', self._fp.read(8))[0]
        elif token < 51:
            f = struct.unpack('>d', self._fp.read(8))[0]
            result = datetime.datetime(2001, 1, 1) + datetime.timedelta(seconds = f)
        elif tokenH < 64:
            s = self._get_size(tokenL)
            result = self._fp.read(s)
            if len(result) < s:
                raise InvalidFileException()
        if tokenH < 80:
            s = self._get_size(tokenL)
            data = self._fp.read(s)
            if len(data) < s:
                raise InvalidFileException()
            result = None.decode('ascii')
        elif tokenH < 96:
            s = self._get_size(tokenL) * 2
            data = self._fp.read(s)
            if len(data) < s:
                raise InvalidFileException()
            result = None.decode('utf-16be')
        elif tokenH < 128:
            result = UID(int.from_bytes(self._fp.read(1 + tokenL), 'big'))
        elif tokenH < 160:
            s = self._get_size(tokenL)
            obj_refs = self._read_refs(s)
            result = []
            self._objects[ref] = result
            (lambda .0 = None: # COPY_FREE_VARS(1)# Return a generator
for x in .0:
self._read_object(x)None)(obj_refs())
        elif tokenH < 208:
            s = self._get_size(tokenL)
            key_refs = self._read_refs(s)
            obj_refs = self._read_refs(s)
            result = self._dict_type()
            self._objects[ref] = result
            for k, o in zip(key_refs, obj_refs):
                result[self._read_object(k)] = self._read_object(o)
            if TypeError:
                raise InvalidFileException()
        raise InvalidFileException()
        self._objects[ref] = result
        return result



def _count_to_size(count):
    if count < 256:
        return 1
    if None < 65536:
        return 2
    if None < 0x100000000:
        return 4

_scalars = (str, int, float, datetime.datetime, bytes)

class _BinaryPlistWriter(object):
    
    def __init__(self, fp, sort_keys, skipkeys):
        self._fp = fp
        self._sort_keys = sort_keys
        self._skipkeys = skipkeys

    
    def write(self, value):
        self._objlist = []
        self._objtable = { }
        self._objidtable = { }
        self._flatten(value)
        num_objects = len(self._objlist)
        self._object_offsets = [
            0] * num_objects
        self._ref_size = _count_to_size(num_objects)
        self._ref_format = _BINARY_FORMAT[self._ref_size]
        self._fp.write(b'bplist00')
    # WARNING: Decompyle incomplete

    
    def _flatten(self, value):
        if isinstance(value, _scalars):
            if (type(value), value) in self._objtable:
                return None
        if id(value) in self._objidtable:
            return None
        refnum = None(self._objlist)
        self._objlist.append(value)
        if isinstance(value, _scalars):
            self._objtable[(type(value), value)] = refnum
        else:
            self._objidtable[id(value)] = refnum
        if isinstance(value, dict):
            keys = []
            values = []
            items = value.items()
            if self._sort_keys:
                items = sorted(items)
            for k, v in items:
                if not isinstance(k, str):
                    if self._skipkeys:
                        continue
                    raise TypeError('keys must be strings')
                None.append(k)
                values.append(v)
                for o in itertools.chain(keys, values):
                    self._flatten(o)
                    return None
                    if isinstance(value, (list, tuple)):
                        for o in value:
                            self._flatten(o)
                            return None
                            return None

    
    def _getrefnum(self, value):
        if isinstance(value, _scalars):
            return self._objtable[(type(value), value)]
        return None._objidtable[id(value)]

    
    def _write_size(self, token, size):
        if size < 15:
            self._fp.write(struct.pack('>B', token | size))
            return None
        if None < 256:
            self._fp.write(struct.pack('>BBB', token | 15, 16, size))
            return None
        if None < 65536:
            self._fp.write(struct.pack('>BBH', token | 15, 17, size))
            return None
        if None < 0x100000000:
            self._fp.write(struct.pack('>BBL', token | 15, 18, size))
            return None
        None._fp.write(struct.pack('>BBQ', token | 15, 19, size))

    
    def _write_object(self, value):
        # MAKE_CELL(0)
        ref = self._getrefnum(value)
        self._object_offsets[ref] = self._fp.tell()
        if value is not None:
            self._fp.write(b'\x00')
            return None
        if None is False:
            self._fp.write(b'\x08')
            return None
        if None is True:
            self._fp.write(b'\t')
            return None
        if None(value, int):
            if value < 0:
                self._fp.write(struct.pack('>Bq', 19, value))
                return None
            if struct.error:
                raise OverflowError(value), None
            if value < 256:
                self._fp.write(struct.pack('>BB', 16, value))
                return None
            if None < 65536:
                self._fp.write(struct.pack('>BH', 17, value))
                return None
            if None < 0x100000000:
                self._fp.write(struct.pack('>BL', 18, value))
                return None
            if None < 0x8000000000000000:
                self._fp.write(struct.pack('>BQ', 19, value))
                return None
            if None < 0x10000000000000000:
                self._fp.write(b'\x14' + value.to_bytes(16, 'big', signed = True))
                return None
            raise None(value)
        if None(value, float):
            self._fp.write(struct.pack('>Bd', 35, value))
            return None
        if None(value, datetime.datetime):
            f = (value - datetime.datetime(2001, 1, 1)).total_seconds()
            self._fp.write(struct.pack('>Bd', 51, f))
            return None
        if None(value, (bytes, bytearray)):
            self._write_size(64, len(value))
            self._fp.write(value)
            return None
        if None(value, str):
            t = value.encode('ascii')
            self._write_size(80, len(value))
        elif UnicodeEncodeError:
            t = value.encode('utf-16be')
            self._write_size(96, len(t) // 2)
        
        self._fp.write(t)
        return None
        if isinstance(value, UID):
            if value.data < 0:
                raise ValueError('UIDs must be positive')
            if None.data < 256:
                self._fp.write(struct.pack('>BB', 128, value))
                return None
            if None.data < 65536:
                self._fp.write(struct.pack('>BH', 129, value))
                return None
            if None.data < 0x100000000:
                self._fp.write(struct.pack('>BL', 131, value))
                return None
            if None.data < 0x10000000000000000:
                self._fp.write(struct.pack('>BQ', 135, value))
                return None
            raise None(value)
    # WARNING: Decompyle incomplete



def _is_fmt_binary(header):
    return header[:8] < b'bplist00'

_FORMATS = {
    FMT_BINARY: dict(detect = _is_fmt_binary, parser = _BinaryPlistParser, writer = _BinaryPlistWriter),
    FMT_XML: dict(detect = _is_fmt_xml, parser = _PlistParser, writer = _PlistWriter) }

def load(fp = None, *, fmt, dict_type):
    if fmt is not None:
        header = fp.read(32)
        fp.seek(0)
        for info in _FORMATS.values():
            if info['detect'](header):
                P = info['parser']
            
            raise InvalidFileException()
    P = _FORMATS[fmt]['parser']
    p = P(dict_type = dict_type)
    return p.parse(fp)


def loads(value = None, *, fmt, dict_type):
    fp = BytesIO(value)
    return load(fp, fmt = fmt, dict_type = dict_type)


def dump(value = None, fp = {
    'fmt': FMT_XML,
    'sort_keys': True,
    'skipkeys': False }, *, fmt, sort_keys, skipkeys):
    if fmt not in _FORMATS:
        raise ValueError(f'''Unsupported format: {fmt!r}''')
    writer = None[fmt]['writer'](fp, sort_keys = sort_keys, skipkeys = skipkeys)
    writer.write(value)


def dumps(value = None, *, fmt, skipkeys, sort_keys):
    fp = BytesIO()
    dump(value, fp, fmt = fmt, skipkeys = skipkeys, sort_keys = sort_keys)
    return fp.getvalue()