Esempio n. 1
0
 def __call__(self, wrapper, name, restype, argtypes, varargs):
     cls = wrapper.get_pyclass(self.clsname)
     methname = name
     methname = self._strip_prefix(methname)
     meth = cls.new_method(methname)
     meth.decorators.append('classmethod')
     args = []
     for idx, param in enumerate(argtypes, varargs):
         argname = 'arg%d' % idx
         meth.arguments.append('arg%d' % idx)
         if wrapper.get_wrapper(str(param)):
             args.append('%s._internal' % argname)
         else:
             args.append(argname)
     if varargs:
         meth.arguments.append('*varargs')
         args.append('*varargs')
     t = template(
         '$funcname($args)',
             funcname=name,
             args=', '.join(args))
     t = template("$cls._from_internal($t)",
             cls=self.clsname,
             t=t)
     t = template('return $t', t=t)
     meth.code.append(t)
     return True
Esempio n. 2
0
 def __call__(self, wrapper, name, restype, argtypes, varargs):
     cls = wrapper.get_pyclass(self.clsname)
     methname = name
     methname = self._strip_prefix(methname)
     meth = cls.new_method(methname)
     args = []
     for idx, param in enumerate(argtypes):
         if idx == self.self_arg:
             if not str(param) == cls.tag:
                 print '`self` argument tags not matching in %s: parameter: %s / class: %s' % (name, str(param), cls.tag)
             args.append('self._internal')
             continue
         argname = 'arg%d' % idx
         meth.arguments.append('arg%d' % idx)
         if wrapper.get_wrapper(str(param)):
             args.append('%s._internal' % argname)
         else:
             args.append(argname)
     if varargs:
         meth.arguments.append('*varargs')
         args.append('*varargs')
     t = template(
         '$funcname($args)',
             funcname=name,
             args=', '.join(args))
     if wrapper.get_wrapper(str(restype)):
         t = template("$cls._from_internal($t)",
                 cls=wrapper.get_wrapper(str(restype)).name,
                 t=t)
     t = template('return $t', t=t)
     meth.code.append(t)
     return True
Esempio n. 3
0
def make_lazy_atom_xizer(name, conn='self.conn'):
    code = []
    code.append(template("if isinstance($name, basestring):", name=name))
    code.append(INDENT)
    code.append(template("$name = $conn.atoms[$name]", conn=conn, name=name))
    code.append(DEDENT)
    return lambda code=code: code
Esempio n. 4
0
def make_rectangles_xizer(list_in='rectangles', list_out='rectangles', length_out='rectangles_length'):
    code = []
    code.append(template("$list_out = []", list_out=list_out))
    code.append(template("for rect in $list_in:", list_in=list_in))
    code.append(INDENT)
    code.append(template("$list_out.extend([rect.x, rect.y, rect.width, rect.height])", list_out=list_out))
    code.append(DEDENT)
    code.append(template("$length_out = len($list_in)", length_out=length_out, list_in=list_in))
    return lambda code=code: code
Esempio n. 5
0
def make_string_xizer(seq_in='value', seq_out='value', length_out='value_len'):
    code = []
    code.append(template('if isinstance($seq_in, unicode):', seq_in=seq_in))
    code.extend([
        INDENT,
            template('$seq_in = $seq_in.encode("utf-8")', seq_in=seq_in),
        DEDENT
        ])
    code.append(template('$length_out = len($seq_in)', length_out=length_out, seq_in=seq_in))
    code.append(template('$seq_out = map(ord, $seq_in)', seq_out=seq_out, seq_in=seq_in))
    return lambda code=code: code
Esempio n. 6
0
def make_utf16_xizer(seq_in='value', seq_out='value', length_out='value_len'):
    code = []
    code.append(template('if not isinstance($seq_in, unicode):', seq_in=seq_in))
    code.extend([
        INDENT,
            template('raise XcbException("`$seq_in` has to be an unicode string")', seq_in=seq_in),
        DEDENT
        ])
    code.append(template('$seq_out = $seq_in.encode("utf-16be")', seq_out=seq_out, seq_in=seq_in))
    code.append(template('$length_out = len($seq_out) / 2 # should work',
        length_out=length_out,
        seq_out=seq_out))
    return lambda code=code: code
Esempio n. 7
0
def make_mask_xizer(iterable_in, enum_name, mask_out):
    code = []
    enum = ALL[enum_name]
    code.append(template("$mask_out = 0", mask_out=mask_out))
    for member in enum.members:
        if not isinstance(member, PyAttribute):
            continue
        key = pythonize_camelcase_name(member.name)
        value = member.value
        code.extend([
            template('if "${key}" in ${iterable_in}:',
                key=key,
                iterable_in=iterable_in),
            INDENT,
            template('$mask_out |= $value',
                mask_out=mask_out,
                value=value),
            DEDENT])
    return lambda code=code: code
Esempio n. 8
0
def make_values_xizer(enum_name, values_dict_name, mask_out='value_mask', list_out='value_list', xize=()):
    """
        make a simple values xizer code list and return it.
        A values xizer takes all values from the values dict
        and stores it in a values list and a values mask.
    """
    enum = ALL[enum_name]
    code = []
    pyvalues = []

    code.append(template("$mask_out, $list_out = 0, []",
        mask_out=mask_out,
        list_out=list_out
        ))
    for member in enum.members:#key, value in enum.values:
        if not isinstance(member, PyAttribute):
            continue

        key = pythonize_camelcase_name(member.name)
        value = member.value
        code.append(template('if "${key}" in ${values_dict_name}:',
                    key=key,
                    values_dict_name=values_dict_name))
        code.append(INDENT)
        code.append(template('$mask_out |= $value',
            mask_out=mask_out,
            value=value
            ))

        s = template('$values_dict_name["$key"]',
            values_dict_name=values_dict_name,
            key=key,
            )
        if key in xize:
            s = 'get_internal(%s)' % s

        code.append(template('$list_out.append($s)',
            list_out=list_out,
            s=s
            ))
        code.append(DEDENT)

    return lambda code=code: code
Esempio n. 9
0
    def _add_fields(fields):
        read_code.append('_unpacked = unpack_from_stream("=%s", stream)' % fmt)
        build_fields = []
        for idx, field in enumerate(fields):
            # try if we can get a modifier
            modifier = get_modifier(field)
            value = modifier % ('_unpacked[%d]' % idx)
            read_code.append(template('self.$fieldname = $value',
                fieldname=prefix_if_needed(field.field_name),
                value=value
            ))

            if modifier != '%s':
                build_fields.append('get_internal(self.%s)' % prefix_if_needed(field.field_name))
            else:
                build_fields.append('self.%s' % prefix_if_needed(field.field_name))
            cls.add_instance_attribute(prefix_if_needed(field.field_name), '') # TODO: description
        build_code.append('stream.write(pack("=%s", %s))' %
                (fmt, ', '.join(build_fields)))
Esempio n. 10
0
def py_complex(self, name, cls):
    m_init = cls.get_member_by_name('__init__')
    init_code = m_init.code

    m_read = cls.new_method('read')
    m_read.arguments.append('stream')
    read_code = m_read.code

    m_build = cls.new_method('build')
    m_build.arguments.append('stream')
    build_code = m_build.code

    def _add_fields(fields):
        read_code.append('_unpacked = unpack_from_stream("=%s", stream)' % fmt)
        build_fields = []
        for idx, field in enumerate(fields):
            # try if we can get a modifier
            modifier = get_modifier(field)
            value = modifier % ('_unpacked[%d]' % idx)
            read_code.append(template('self.$fieldname = $value',
                fieldname=prefix_if_needed(field.field_name),
                value=value
            ))

            if modifier != '%s':
                build_fields.append('get_internal(self.%s)' % prefix_if_needed(field.field_name))
            else:
                build_fields.append('self.%s' % prefix_if_needed(field.field_name))
            cls.add_instance_attribute(prefix_if_needed(field.field_name), '') # TODO: description
        build_code.append('stream.write(pack("=%s", %s))' %
                (fmt, ', '.join(build_fields)))

    need_alignment = False

    # because of that address storing, we'll only be able to read
    # from a MemStream. That's sad. But the address of the struct
    # seems to be needed by some replys, e.g. GetKeyboardMappingReply,
    # to access `self.length`.
    read_code.extend(['self._address = stream.address', 'root = stream.tell()'])
    # Here we store the index of the `root = stream.tell()` line to be able
    # to remove obsolete calls later.
    needs_root = False

    build_code.append('count = 0')
    # prework to pad to the correct size
    if cls.base == 'ooxcb.Event':
        build_code.append('root = stream.tell()')
    struct = Struct()
    for field in self.fields:
        # This hack is ugly, but it seems to be required for valid send_event stuff.
        # Normally, `response_type` is set automatically, but it isn't if the
        # event is part of a send_event request. We have to set it explicitly then
        # to avoid `BadValue` errors. I hope that doesn't have any side effects.
        if (field.field_name == 'response_type' and isinstance(self, xcbgen.xtypes.Event)):
            init_code.append('self.response_type = %s' % self.opcodes[name])
            struct.push_format(field)
            continue
        if field.auto:
            struct.push_pad(field.type.size)
            continue
        if field.type.is_simple:
            struct.push_format(field)
            # add a simple default value (needs to be changed by the user, of course)
            init_code.append('self.%s = None' % (prefix_if_needed(field.field_name)))
            cls.add_instance_attribute(prefix_if_needed(field.field_name), '') # TODO: description
            continue
        if field.type.is_pad:
            struct.push_pad(field.type.nmemb)
            continue
        fields, size, fmt = struct.flush()
        if fields:
            _add_fields(fields)
        if size > 0:
            if not fields: # if no fields got added, the pad would get lost. add it manually then.
                read_code.append(template('stream.seek($size, 1)', size=size))
            build_code.append(template('count += $size', size=size))
        if need_alignment:
            read_code.append('stream.seek(ooxcb.type_pad(%d, stream.tell() - root), 1)' % align_size(field))
            needs_root = True
            # need to add pad for `build`?
#            build_code.append(r'stream.write("\0" * ooxcb.type_pad(%d, count)' % align_size(field))
        need_alignment = True

        if field.type.is_list:
            if field.type.member.py_type == 'void':
                # It is a void list. The problem about void lists is:
                # we don't exactly know if it's 8, 16 or 32 bit per item.
                # Fortunately, there seems to be an complex type
                # attribute called `self.format` present which has the
                # value 8, 16 or 32. So, we'll use this value
                # to get the type of the list members.
                # That should work for the GetPropertyReply in xproto,
                # but it might not work for other stuff. TODO? It's not nice.
                #
                # If `self.format` is 0 (happens for GetPropertyReply
                # if we try to access a non-existent property),
                # we use "B" (which is an unsigned byte) as a fallback.
                lread_code = ('ooxcb.List(self.conn, stream, %s, SIZES.get(self.format, "B"), self.format // 8)' % \
                        (get_expr(field.type.expr)))
            else:
                lread_code = ('ooxcb.List(self.conn, stream, %s, %s, %d)' % \
                        (get_expr(field.type.expr),
                            field.py_listtype,
                            field.py_listsize))
                if field.py_type == 'char':
                    # convert a list of chars to strings
                    lread_code = '%s.to_string()' % lread_code
                elif field.py_type in INTERFACE.get('ResourceClasses', []):
                    # is a resource. wrap them.
                    lread_code = '[%s for w in %s]' % (get_modifier(field) % 'w', lread_code)
                elif field.py_type == 'ATOM': # TODO: hey, to have this hardcoded is not cool!
                    lread_code = 'map(self.conn.atoms.get_by_id, %s)' % lread_code
            read_code.append('self.%s = %s' % (prefix_if_needed(field.field_name), lread_code))
            cls.add_instance_attribute(prefix_if_needed(field.field_name), '') # TODO: description

            # TODO: add the lazy length property setter ...
            # e.g. `self.cmaps_length` is set to `len(self.colormaps)`.
            # The problem is: the field type expr isn't always a simple
            # expression, it also can be "(self.keycodes_per_modifier * 5)" -
            # how should we solve that?
            build_code.append('build_list(self.conn, stream, self.%s, %s)' % (
                prefix_if_needed(field.field_name), field.py_listtype))

            init_code.append('self.%s = []' % (prefix_if_needed(field.field_name)))
        elif field.type.is_container and field.type.fixed_size():
            read_code.append('self.%s = %s.create_from_stream(self.conn, stream)' % (prefix_if_needed(field.field_name),
                    get_wrapped(field.py_type)))
            cls.add_instance_attribute(prefix_if_needed(field.field_name), '') # TODO: description

            build_code.append('self.%s.build(stream)' % prefix_if_needed(field.field_name))
            init_code.append('self.%s = None' % (prefix_if_needed(field.field_name)))
        else:
            read_code.append('self.%s = %s.create_from_stream(self.conn, stream)' % (prefix_if_needed(field.field_name),
                    get_wrapped(field.py_type)))
            cls.add_instance_attribute(prefix_if_needed(field.field_name), '') # TODO: description
            build_code.append('self.%s.build(stream)' % prefix_if_needed(field.field_name))
            init_code.append('self.%s = None' % (prefix_if_needed(field.field_name)))

    fields, size, fmt = struct.flush()
    if fields:
        if need_alignment:
            read_code.append('stream.seek(ooxcb.type_pad(4, stream.tell() - root), 1)')
            needs_root = True
        _add_fields(fields)
    if (not self.fixed_size() and cls.base == 'ooxcb.Struct'):
        # only do that for variable-length structs.
        # However, the check above is very nasty.
        needs_root = True
    # Events have a fixed size of 32 bytes. Here we pad them to the correct size
    # in the build code.TODO: this solution is nasty, but at least it works.
    if cls.base == 'ooxcb.Event':
        build_code.append(r'stream.write("\0" * (32 - (stream.tell() - root)))')
    if not needs_root:
        read_code.remove('root = stream.tell()')
Esempio n. 11
0
def make_seq_xizer(seq_in='value', seq_out='value', length_out='value_len'):
    code = []
    code.append(template('$length_out = len($seq_in)', length_out=length_out, seq_in=seq_in))
    if seq_in != seq_out:
        code.append(template('$seq_out = $seq_in', seq_out=seq_out, seq_in=seq_in))
    return lambda code=code: code