示例#1
0
 def __init__(self, gi_extension):
     Formatter.__init__(self, gi_extension)
     self._order_by_parent = True
     self._symbol_formatters.update(
             {
                 GIClassSymbol: self._format_class_symbol,
                 GIStructSymbol: self._format_class_symbol,
             })
     self._ordering.insert(self._ordering.index(ClassSymbol) + 1, GIClassSymbol)
     self._ordering.insert(self._ordering.index(GIClassSymbol) + 1, GIStructSymbol)
     self.__annotation_parser = GIAnnotationParser()
示例#2
0
class GIFormatter(Formatter):
    sitemap_language = None
    engine = None

    def __init__(self, gi_extension):
        Formatter.__init__(self, gi_extension)
        self._order_by_parent = True
        self._symbol_formatters.update({
            GIClassSymbol:
            self._format_class_symbol,
            GIStructSymbol:
            self._format_class_symbol,
        })
        self._ordering.insert(
            self._ordering.index(ClassSymbol) + 1, GIClassSymbol)
        self._ordering.insert(
            self._ordering.index(GIClassSymbol) + 1, GIStructSymbol)
        self.__annotation_parser = GIAnnotationParser()

    def format_annotations(self, annotations):
        template = self.engine.get_template('gi_annotations.html')
        return template.render({'annotations': annotations})

    def __add_attrs(self, symbol, **kwargs):
        if not symbol:
            return
        self.extension.add_attrs(symbol, **kwargs)
        for csym in symbol.get_children_symbols():
            self.__add_attrs(csym, **kwargs)

    def __wrap_in_language(self, symbol, c_doc, python_doc, js_doc):
        template = self.get_template('symbol_language_wrapper.html')
        res = template.render({
            'symbol': symbol,
            'c_doc': c_doc,
            'python_doc': python_doc,
            'js_doc': js_doc
        })
        return res

    def _format_symbol(self, symbol):
        if isinstance(symbol,
                      (QualifiedSymbol, FieldSymbol, EnumMemberSymbol)):
            return Formatter._format_symbol(self, symbol)

        self.extension.setup_language('c', None)
        self.__add_attrs(symbol, language='c')

        c_out = Formatter._format_symbol(self, symbol)
        python_out = None
        js_out = None

        self.extension.setup_language('python', 'c')
        if is_introspectable(symbol.unique_name, 'python'):
            self.__add_attrs(symbol, language='python')
            python_out = Formatter._format_symbol(self, symbol)

        self.extension.setup_language('javascript', 'python')
        if is_introspectable(symbol.unique_name, 'javascript'):
            self.__add_attrs(symbol, language='javascript')
            js_out = Formatter._format_symbol(self, symbol)

        self.extension.setup_language(None, 'javascript')
        return self.__wrap_in_language(symbol, c_out, python_out, js_out)

    def _format_flags(self, flags):
        template = self.engine.get_template('gi_flags.html')
        out = template.render({'flags': flags})
        return out

    def _format_type_tokens(self, symbol, type_tokens):
        language = symbol.get_extension_attribute(
            self.extension.extension_name, 'language')
        if language != 'c':
            type_desc = self.extension.get_attr(symbol, 'type_desc')
            assert (type_desc)
            gi_name = type_desc.gi_name
            new_tokens = []
            link = None
            if gi_name in FUNDAMENTALS[language]:
                fund_link = FUNDAMENTALS[language][gi_name]
                link = Link(fund_link.ref, fund_link._title, gi_name)
            elif gi_name in ALL_GI_TYPES:
                ctype_name = ALL_GI_TYPES[gi_name]
                link = self.extension.app.link_resolver.get_named_link(
                    ctype_name)

            if type_desc.nesting_depth:
                new_tokens.append('[' * type_desc.nesting_depth + ' ')
            if link:
                new_tokens.append(link)
            else:  # Should not happen but let's be conservative
                new_tokens.append(type_desc.gi_name)
            if type_desc.nesting_depth:
                new_tokens.append(']' * type_desc.nesting_depth)

            return Formatter._format_type_tokens(self, symbol, new_tokens)

        return Formatter._format_type_tokens(self, symbol, type_tokens)

    def __add_annotations(self, symbol):
        if self.extension.get_attr(symbol, 'language') == 'c':
            annotations = self.__annotation_parser.make_annotations(symbol)

            # FIXME: OK this is format time but still seems strange
            if annotations:
                extra_content = self.format_annotations(annotations)
                symbol.extension_contents['Annotations'] = extra_content
        else:
            symbol.extension_contents.pop('Annotations', None)

    def _format_return_item_symbol(self, symbol):
        self.__add_annotations(symbol)
        return Formatter._format_return_item_symbol(self, symbol)

    def _format_return_value_symbol(self, *args):
        retval = args[0]
        is_void = retval[0] is None or \
                retval[0].get_extension_attribute('gi-extension',
                        'gi_name') == 'none'

        if not is_void:
            language = retval[0].get_extension_attribute(
                self.extension.extension_name, 'language')
        else:
            language = 'c'

        if language == 'c':
            if is_void:
                retval = [None]
            else:
                retval = retval[:1]

            for item in retval:
                if item:
                    item.formatted_link = ''

        elif is_void:
            retval = retval[1:] or [None]

        args = list(args)
        args[0] = retval
        return Formatter._format_return_value_symbol(self, *args)

    def _format_parameter_symbol(self, parameter):
        self.__add_annotations(parameter)
        language = parameter.get_extension_attribute(
            self.extension.extension_name, 'language')
        if language != 'c':
            direction = parameter.get_extension_attribute(
                'gi-extension', 'direction')
            if direction == 'out':
                return None

            is_destroy = parameter.get_extension_attribute(
                'gi-extension', 'is_destroy')
            if is_destroy:
                return None

            is_closure = parameter.get_extension_attribute(
                'gi-extension', 'is_closure')

            if is_closure and language == 'python':
                parameter.extension_contents['type-link'] = self._format_link(
                    PYTHON_VARIADIC_LINK, None, 'variadic')
            else:
                parameter.extension_contents[
                    'type-link'] = self._format_linked_symbol(parameter)
        else:
            parameter.extension_contents.pop('type-link', None)

        res = Formatter._format_parameter_symbol(self, parameter)
        return res

    def _format_linked_symbol(self, symbol):
        if not symbol:
            return Formatter._format_linked_symbol(self, symbol)

        language = symbol.get_extension_attribute(
            self.extension.extension_name, 'language')
        if language == 'c':
            res = Formatter._format_linked_symbol(self, symbol)
            if symbol == None:
                res = 'void'
            return res

        if not isinstance(symbol, QualifiedSymbol):
            return Formatter._format_linked_symbol(self, symbol)

        type_desc = symbol.get_extension_attribute('gi-extension', 'type_desc')
        if type_desc:
            return self._format_type_tokens(symbol, symbol.type_tokens)

        return Formatter._format_linked_symbol(self, symbol)

    def _format_prototype(self, function, is_pointer, title):
        language = function.get_extension_attribute(
            self.extension.extension_name, 'language')
        if language == 'c':
            return Formatter._format_prototype(self, function, is_pointer,
                                               title)

        params = function.get_extension_attribute('gi-extension', 'parameters')

        if params is None:
            return Formatter._format_prototype(self, function, is_pointer,
                                               title)

        c_name = function.make_name()

        if language == 'python':
            template = self.engine.get_template('python_prototype.html')
        else:
            template = self.engine.get_template('javascript_prototype.html')

        if type(function) == SignalSymbol:
            comment = "%s callback for the '%s' signal" % (language, c_name)
        elif type(function) == VFunctionSymbol:
            comment = "%s implementation of the '%s' virtual method" % \
                    (language, c_name)
        else:
            comment = "%s wrapper for '%s'" % (language, c_name)

        res = template.render({
            'return_value': function.return_value,
            'parent_name': function.parent_name,
            'function_name': title,
            'parameters': params,
            'comment': comment,
            'throws': function.throws,
            'out_params': [],
            'is_method': isinstance(function, MethodSymbol)
        })

        return res

    def _format_members_list(self, members, member_designation, struct):
        language = struct.get_extension_attribute(
            self.extension.extension_name, 'language')
        if language != 'c':
            # Never render members that are in a union, introspected won't show them
            members = [
                m for m in members if not m.get_extension_attribute(
                    self.extension.extension_name, 'in_union')
            ]

        return super()._format_members_list(members, member_designation,
                                            struct)

    def _format_struct(self, struct):
        language = struct.get_extension_attribute(
            self.extension.extension_name, 'language')
        if language == 'c':
            return Formatter._format_struct(self, struct)

        members_list = self._format_members_list(struct.members, 'Attributes',
                                                 struct)

        template = self.engine.get_template("python_compound.html")
        out = template.render({"symbol": struct, "members_list": members_list})
        return out

    def _format_class_symbol(self, klass):
        saved_raw_text = klass.raw_text
        if klass.get_extension_attribute(self.extension.extension_name,
                                         'language') != 'c':
            klass.raw_text = None
        out = Formatter._format_class_symbol(self, klass)

        if klass.get_extension_attribute(self.extension.extension_name,
                                         'language') == 'c':
            # Render class structure if available.
            if klass.class_struct_symbol:
                out += '<h3>Class structure</h3>'
                out += klass.class_struct_symbol.detailed_description

        klass.raw_text = saved_raw_text
        return out

    def _format_constant(self, constant):
        language = constant.get_extension_attribute(
            self.extension.extension_name, 'language')
        if language == 'c':
            return Formatter._format_constant(self, constant)

        template = self.engine.get_template('constant.html')
        out = template.render({
            'symbol': constant,
            'definition': None,
            'constant': constant
        })
        return out

    def _format_comment(self, comment, link_resolver):
        ast = comment.extension_attrs['gi-extension']['ast']

        if not comment.description:
            out = u''
        elif ast:
            out = self._docstring_formatter.ast_to_html(ast, link_resolver)
        else:
            ast = self._docstring_formatter.comment_to_ast(
                comment, link_resolver)
            out = self._docstring_formatter.ast_to_html(ast, link_resolver)
            comment.extension_attrs['gi-extension']['ast'] = ast

        return out

    def _format_callable(self,
                         callable_,
                         callable_type,
                         title,
                         is_pointer=False):
        language = callable_.get_extension_attribute(
            self.extension.extension_name, 'language')
        if language == 'python' and isinstance(callable_, ClassMethodSymbol):
            return None

        return super()._format_callable(callable_, callable_type, title,
                                        is_pointer)

    def _format_property_prototype(self, prop, title, type_link):
        language = prop.get_extension_attribute(self.extension.extension_name,
                                                'language')
        if language == 'python':
            title = 'self.props.%s' % title
        return Formatter._format_property_prototype(self, prop, title,
                                                    type_link)

    def _format_alias(self, alias):
        language = alias.get_extension_attribute(self.extension.extension_name,
                                                 'language')
        if language == 'c':
            return super()._format_alias(alias)

        return None

    def get_template(self, name):
        return GIFormatter.engine.get_template(name)

    def parse_toplevel_config(self, config):
        super().parse_toplevel_config(config)
        if GIFormatter.engine is None:
            module_path = os.path.dirname(__file__)
            searchpath = [os.path.join(module_path, "html_templates")
                          ] + Formatter.engine.loader.searchpath
            GIFormatter.engine = Engine(
                loader=FileLoader(searchpath, encoding='UTF-8'),
                extensions=[CoreExtension(), CodeExtension()])
            GIFormatter.engine.global_vars.update({'e': html.escape})