Exemplo n.º 1
0
    def _populate(self, entry, stack, intermediates):
        """Walk down all entries contained within this entry, checking for visibility."""
        if entry in stack:
            # An entry is within itself. This entry will be 'visible' either if
            # it itself is visible, or it contains a visible child, but at this
            # stage we don't know for sure (as all of its children haven't been
            # processed). If so, we'll mark all of its children to a list that 
            # requires them to be re-processed.
            if not self._has_data[entry]:
                for inter in stack[stack.index(entry)+1:]:
                    intermediates.add(inter)
            return

        if entry in self._has_data:
            return

        # This entry isn't yet calculated; do so now.
        self._has_data[entry] = not entry.is_hidden()
        stack.append(entry)
        for child in entry.children:
             assert child not in self._parents, \
                     "Found child '%s' in parents '%s' and '%s'! Entries " \
                     "cannot be repeated unless they are common entries." % (
                             child, entry, self._parents[child])
             self._parents[child] = entry
             self._populate(child.entry, stack, intermediates)
        stack.remove(entry)

        if not isinstance(entry, chc.Choice) and not entry.is_hidden():
            # We are visible; check to see if either we (or any of our
            # children) contain data.
            for child in entry.children:
                if not ent.is_hidden(child.name) and self._has_data[child.entry]:
                    break
            else:
                # None of the children contain data; this entry will only contain
                # data if implicitly has data itself.
                if isinstance(entry, fld.Field) or \
                        (isinstance(entry, seq.Sequence) and entry.value is not None):
                    # This entry's children don't contain data, but it appears to
                    # have some implicit data.
                    for constraint in entry.constraints:
                        if isinstance(constraint, Equals):
                            # The 'implicit' data has an expected value, so it
                            # isn't considered as new data.
                            self._has_data[entry] = False
                            break
                elif isinstance(entry, sof.SequenceOf) and \
                        not ent.is_hidden(entry.children[0].name):
                    self._has_data[entry] = True
                else:
                    self._has_data[entry] = False

        if not self._has_data[entry]:
            self._hide_children(entry)
Exemplo n.º 2
0
Arquivo: param.py Projeto: TauPan/bdec
    def _populate_visible(self, entry, common, entries, visible=True):
        if entry in entries:
            return

        if entry in common:
            # Common entries are visible if their name is public, regardless of
            # what their parents do.
            visible = not ent.is_hidden(entry.name)
        else:
            # Entries that aren't common are visible if both they and their parents
            # are visible.
            visible &= not ent.is_hidden(entry.name)

        entries[entry] = not visible
        for child in entry.children:
            self._populate_visible(child.entry, common, entries, visible)
Exemplo n.º 3
0
Arquivo: param.py Projeto: TauPan/bdec
    def child_has_data(self, child):
        """Does a bdec.entry.Child instance contain data.

        This is different from contains_data when a referenced entry has been
        hidden."""
        entry = self._parents[child]
        return self.contains_data(entry) and not ent.is_hidden(child.name) \
                and self._has_data[child.entry]
Exemplo n.º 4
0
def get_instance(items):
    """Convert an iterable list of decode items to a python instance."""
    stack = [_DecodedItem(None)]
    for is_starting, name, entry, data, value in items:
        if is_starting:
            stack.append(_DecodedItem(entry))
        else:
            item = stack.pop()
            if not ent.is_hidden(name):
                stack[-1].add_entry(name, item.get_value(value))

    assert len(stack) == 1
    return stack[0].get_value(None)
Exemplo n.º 5
0
def to_file(decoder, binary, output, encoding="utf-8", verbose=False):
    handler = _XMLGenerator(output, encoding)
    offset = 0
    is_first = True
    hidden_count = 0
    has_children = False
    for is_starting, name, entry, data, value in decoder.decode(binary):
        # If we have an entry that is hidden, all entries under that should
        # also be hidden.
        if is_starting:
            if hidden_count or ent.is_hidden(name):
                hidden_count += 1
        is_hidden = hidden_count != 0
        if not is_starting and hidden_count:
            hidden_count -= 1

        if not verbose and (is_hidden or isinstance(entry, chc.Choice)):
            # By default, we don't output hidden or choice entries.
            continue

        if is_starting:
            if not is_first:
                _print_whitespace(handler, offset)
            is_first = False

            handler.startElement(escape_name(name), xml.sax.xmlreader.AttributesImpl({}))
            offset = offset + 4
            has_children = False
        else:
            # An element is ending; we only include the surrounding whitespace
            # if the entry has visible children (otherwise we try an keep the
            # value compact with the entries). This means strings with leading
            # and trailing whitespace can be represented (and produces nicer
            # xml).
            if value is not None and not _has_expected_value(entry):
                if has_children:
                    _print_whitespace(handler, offset)

                text = xml_strip(unicode(value))
                handler.characters(text)

            if verbose and data:
                handler.comment(str(data))
            offset = offset - 4
            if has_children:
                _print_whitespace(handler, offset)
            handler.endElement(escape_name(name))

            has_children = True
    handler.ignorableWhitespace('\n')
Exemplo n.º 6
0
def decode(decoder, binary):
    """
    Create a python instance representing the decoded data.
    """
    stack = [_DecodedItem(None)]
    for is_starting, name, entry, data, value in decoder.decode(binary):
        if is_starting:
            stack.append(_DecodedItem(entry))
        else:
            item = stack.pop()
            if not ent.is_hidden(name):
                stack[-1].add_entry(name, item.get_value(value))

    assert len(stack) == 1
    return stack[0].get_value(None)
Exemplo n.º 7
0
    def parseString(self, text):
        if isinstance(text, unicode):
            text = text.encode("ascii")

        token_stack = [[]]
        name_stack = [{}]
        for is_starting, name, entry, data, value in self._decode(text, "<string>"):
            if is_starting:
                token_stack.append([])
                name_stack.append({})
            else:
                if name and not is_hidden(name) and value is not None:
                    token_stack[-1].append(value)

                names = name_stack.pop()
                tokens = ParseResults(token_stack.pop(), names)
                for action in getattr(entry, "actions", []):
                    tokens = action(tokens)
                    if not isinstance(tokens, ParseResults):
                        if not isinstance(tokens, list):
                            tokens = [tokens]
                        names = {}
                        tokens = ParseResults(tokens, names)

                if name is not None and not is_hidden(name):
                    # FIXME: This isn't entirely correct, as it includes the
                    # default names we use in the decoder (such as 'and',
                    # 'or', etc), instead of just the user defined names.
                    name_stack[-1][name] = tokens
                name_stack[-1].update(names)

                # Extend the current tokens list with the child tokens
                token_stack[-1] += tokens
        assert len(token_stack) == 1
        assert len(name_stack) == 1
        return ParseResults(token_stack.pop(), name_stack.pop())
Exemplo n.º 8
0
def _mock_query(parent, entry, offset, name):
    """A mock query object to return data for hidden common entries.

    It will return null data for fields, etc."""
    if isinstance(parent, (int, long)) or parent is None:
        raise MissingInstanceError(parent, entry)

    try:
        return parent[name]
    except KeyError:
        pass

    # Check to see if it's a compound name...
    result = {}
    for param, value in parent.items():
        names = param.split('.')
        if names[0] == name:
            child_name = '.'.join(names[1:])
            result[child_name] = value
    if result:
        return result

    if is_hidden(entry.name):
        raise MissingInstanceError(parent, entry)

    # We have to return some suitable data for these entries; return a null
    # data object.
    if isinstance(entry, Field):
        length = entry.length.evaluate({})
        if entry.format == Field.INTEGER:
            return 0
        elif entry.format == Field.TEXT:
            return ''
        elif entry.format == Field.FLOAT:
            return 0.0
        else:
            return Data('\x00' * (length / 8 + 1), length)
    elif isinstance(entry, Sequence):
        return MockSequenceValue()
    elif isinstance(entry, SequenceOf):
        return []
    elif isinstance(entry, Choice):
        return {}
    else:
        raise NotImplementedError('Unknown entry %s to mock data for...' % entry)
Exemplo n.º 9
0
def _decode_visible(spec, data):
    """ Use the spec to decode the given data, returning all visible entries. """
    hidden_count = 0
    for (is_starting, name, entry, data, value) in spec.decode(data):

        is_visible = True
        if isinstance(entry, Choice):
            # Choice entries aren't printed...
            is_visible = False

        if is_starting:
            if hidden_count or is_hidden(name):
                # This entry is hidden; all child entries should also be
                # hidden, even if their names are visible.
                hidden_count += 1
                is_visible = False
        else:
            if hidden_count:
                # We are finishing a hidden entry...
                hidden_count -= 1
                is_visible = False

        if is_visible:
            yield is_starting, name, entry, data, value
Exemplo n.º 10
0
    def endElement(self, name):
        assert self._stack[-1][0] == name
        (name, attrs, breaks, lineno, colno) = self._stack.pop()

        # We don't pop the children item until after we have called the
        # handler, as it may be used when creating a value reference.
        children = self._children[-1]

        length = None
        if attrs.has_key('length'):
            length = self._parse_expression(attrs['length'])
        entry_name = ""
        if attrs.has_key('name'):
            entry_name = attrs['name']
        entry = self._handlers[name](attrs, children, entry_name, length, breaks)

        # Check for value constraints
        constraints = []
        if attrs.has_key('min'):
            minimum = self._parse_expression(attrs['min'])
            constraints.append(Minimum(minimum))
        if attrs.has_key('max'):
            maximum = self._parse_expression(attrs['max'])
            constraints.append(Maximum(maximum))
        if attrs.has_key('expected'):
            expected = self._parse_expression(attrs['expected'])
            constraints.append(Equals(expected))
        if name == 'field' and not isinstance(entry, fld.Field) and attrs.has_key('value'):
            # Fields that are long integers can be internally converted to
            # references to Sequences; we need to handle the expected values.
            expected = self._parse_expression(attrs['value'])
            constraints.append(Equals(expected))

        if constraints:
            if isinstance(entry, ReferencedEntry):
                # We found a reference with constraints; create an intermediate
                # sequence that will have the constraints.
                reference = entry
                if not ent.is_hidden(reference.name):
                    reference.name = '%s:' % reference.name
                value = self._parse_expression("${%s}" % reference.name)
                entry = seq.Sequence(entry_name, [reference], value=value)
            entry.constraints += constraints

        self._children.pop()

        if attrs.has_key('if'):
            # This is a 'conditional' entry; only present if the expression in
            # 'if' is true. To decode this, we create a choice with a 'not
            # present' option; this option attempts to decode first, with the
            # condition inverted.
            try:
                not_present = exp.parse_conditional_inverse(attrs['if'])
                not_present.name = 'not present:'
            except exp.ExpressionError, ex:
                raise XmlExpressionError(ex, self._filename, self.locator)
            assert isinstance(not_present, ent.Entry)

            self.lookup[not_present] = (self._filename, lineno, colno)
            self.lookup[entry] = (self._filename, lineno, colno)

            name = 'optional %s' % entry_name if entry_name else 'optional:'
            optional = chc.Choice(name, [not_present, entry])
            entry = optional
Exemplo n.º 11
0
Arquivo: param.py Projeto: TauPan/bdec
 def contains_data(self, entry):
     """Does an entry contain data."""
     return not ent.is_hidden(entry.name) and self._has_data[entry]