[gobject-introspection] misc: add tool semi-automating the GTK-Doc test suite update procedure



commit c7144d0ccc4ddca73c4ff690e147d247aedb2def
Author: Dieter Verfaillie <dieterv optionexplicit be>
Date:   Tue Jun 23 20:13:17 2015 +0200

    misc: add tool semi-automating the GTK-Doc test suite update procedure
    
    Creates .xml.in files in tests/scanner/annotationparser/gtk-doc
    which then need to be carefully compared for changes (using your
    favorite diff tool) with the .xml files already contained in that
    same directory.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=725685

 misc/update-gtkdoc-tests.py |  234 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 234 insertions(+), 0 deletions(-)
---
diff --git a/misc/update-gtkdoc-tests.py b/misc/update-gtkdoc-tests.py
new file mode 100644
index 0000000..4c1ec13
--- /dev/null
+++ b/misc/update-gtkdoc-tests.py
@@ -0,0 +1,234 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# -*- Mode: Python -*-
+
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2012-2015 Dieter Verfaillie <dieterv optionexplicit be>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+
+import os
+import sys
+import io
+
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
+from giscanner.annotationparser import (COMMENT_BLOCK_START_RE, COMMENT_BLOCK_END_RE,
+                                        GtkDocCommentBlockParser, GtkDocCommentBlockWriter)
+from giscanner.message import MessageLogger, ERROR, FATAL
+
+
+HEADER = '''<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test";>
+
+'''
+
+TEST = '''<test>
+  <input>%(docblock)s</input>
+  <parser>
+%(tree)s
+  </parser>
+  <output>%(serialized)s</output>
+</test>
+
+'''
+
+FOOTER = '''</tests>
+'''
+
+
+def parsed2tree(docblock):
+    parsed = ''
+
+    if docblock is not None:
+        parsed += '    <docblock>\n'
+
+        parsed += '      <identifier>\n'
+        parsed += '        <name>%s</name>\n' % (docblock.name, )
+        if docblock.annotations:
+            parsed += '        <annotations>\n'
+            for ann_name, ann_options in docblock.annotations.items():
+                parsed += '          <annotation>\n'
+                parsed += '            <name>%s</name>\n' % (ann_name, )
+                if ann_options:
+                    parsed += '            <options>\n'
+                    if isinstance(ann_options, list):
+                        for option in ann_options:
+                            parsed += '              <option>\n'
+                            parsed += '                <name>%s</name>\n' % (option, )
+                            parsed += '              </option>\n'
+                    else:
+                        for (option, value) in ann_options.items():
+                            parsed += '              <option>\n'
+                            parsed += '                <name>%s</name>\n' % (option, )
+                            if value:
+                                parsed += '                <value>%s</value>\n' % (value, )
+                            parsed += '              </option>\n'
+                    parsed += '            </options>\n'
+                parsed += '          </annotation>\n'
+            parsed += '        </annotations>\n'
+        parsed += '      </identifier>\n'
+
+        if docblock.params:
+            parsed += '      <parameters>\n'
+            for param_name in docblock.params:
+                param = docblock.params.get(param_name)
+                parsed += '        <parameter>\n'
+                parsed += '          <name>%s</name>\n' % (param_name, )
+                if param.annotations:
+                    parsed += '          <annotations>\n'
+                    for ann_name, ann_options in param.annotations.items():
+                        parsed += '            <annotation>\n'
+                        parsed += '              <name>%s</name>\n' % (ann_name, )
+                        if ann_options:
+                            parsed += '              <options>\n'
+                            if isinstance(ann_options, list):
+                                for option in ann_options:
+                                    parsed += '                <option>\n'
+                                    parsed += '                  <name>%s</name>\n' % (option, )
+                                    parsed += '                </option>\n'
+                            else:
+                                for (option, value) in ann_options.items():
+                                    parsed += '                <option>\n'
+                                    parsed += '                  <name>%s</name>\n' % (option, )
+                                    if value:
+                                        parsed += '                  <value>%s</value>\n' % (value, )
+                                    parsed += '                </option>\n'
+                            parsed += '              </options>\n'
+                        parsed += '            </annotation>\n'
+                    parsed += '          </annotations>\n'
+                if param.description:
+                    parsed += '          <description>%s</description>\n' % (param.description, )
+                parsed += '        </parameter>\n'
+            parsed += '      </parameters>\n'
+
+        if docblock.description:
+            parsed += '      <description>%s</description>\n' % (docblock.description, )
+
+        if docblock.tags:
+            parsed += '      <tags>\n'
+            for tag_name in docblock.tags:
+                tag = docblock.tags.get(tag_name)
+                parsed += '        <tag>\n'
+                parsed += '          <name>%s</name>\n' % (tag_name, )
+                if tag.annotations:
+                    parsed += '          <annotations>\n'
+                    for ann_name, ann_options in tag.annotations.items():
+                        parsed += '            <annotation>\n'
+                        parsed += '              <name>%s</name>\n' % (ann_name, )
+                        if ann_options:
+                            parsed += '              <options>\n'
+                            if isinstance(ann_options, list):
+                                for option in ann_options:
+                                    parsed += '                <option>\n'
+                                    parsed += '                  <name>%s</name>\n' % (option, )
+                                    parsed += '                </option>\n'
+                            else:
+                                for (option, value) in ann_options.items():
+                                    parsed += '                <option>\n'
+                                    parsed += '                  <name>%s</name>\n' % (option, )
+                                    if value:
+                                        parsed += '                  <value>%s</value>\n' % (value, )
+                                    parsed += '                </option>\n'
+                            parsed += '              </options>\n'
+                        parsed += '            </annotation>\n'
+                    parsed += '          </annotations>\n'
+                if tag.value:
+                    parsed += '          <value>%s</value>\n' % (tag.value, )
+                if tag.description:
+                    parsed += '          <description>%s</description>\n' % (tag.description, )
+                parsed += '        </tag>\n'
+            parsed += '      </tags>\n'
+
+        parsed += '    </docblock>'
+
+    return parsed
+
+
+if __name__ == '__main__':
+    if sys.version_info < (3, 0):
+        print('Sorry, update-gtkdoc-tests.py requires Python 3.x')
+        sys.exit(1)
+
+    gi_tests = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'tests', 'scanner', 
'annotationparser', 'gtkdoc'))
+
+    gtkdoc_tests = None
+    if len(sys.argv) == 2:
+        gtkdoc_tests = sys.argv[1]
+    else:
+        # Fall back to default jhbuild checkoutroot directory layout
+        gtkdoc_tests = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'gtk-doc', 
'tests'))
+
+    if not gtkdoc_tests or not os.path.isdir(gtkdoc_tests):
+        print('GTK-Doc source directory "%s" not found' % gtkdoc_tests)
+        sys.exit(1)
+    else:
+        print('Using GTK-Doc source directory "%s"' % gtkdoc_tests)
+
+    for root, dirs, files in os.walk(gtkdoc_tests):
+        for inputfile in files:
+            ext = os.path.splitext(inputfile)[-1].lower()
+            if 'src' in root and ext in ['.c', '.h']:
+                path = os.path.join(root, inputfile)
+                print('Reading "%s"' % path)
+
+                relpath = os.path.relpath(path, gtkdoc_tests).split(os.sep)
+                relpath = os.path.join(relpath[0], relpath[len(relpath) - 1])
+
+                logger = MessageLogger.get(namespace=None)
+                parser = GtkDocCommentBlockParser()
+                writer = GtkDocCommentBlockWriter(indent=True)
+                logger.enable_warnings((ERROR, FATAL))
+
+                with io.open(path, 'rU') as f:
+                    lines = f.readlines()
+
+                chunks = []
+                in_comment = False
+                chunk_start = 0
+                chunk_end = 0
+
+                for line_index, line in enumerate(lines):
+                    if not in_comment:
+                        if COMMENT_BLOCK_START_RE.match(line):
+                            # We are at a line that starts a GTK-Doc comment block
+                            in_comment = True
+                            # Store where this GTK-Doc comment block starts
+                            chunk_start = line_index
+                    else:
+                        if COMMENT_BLOCK_END_RE.match(line):
+                            # We are at a line that closes a GTK-Doc comment block
+                            in_comment = False
+                            # Store the GTK-Doc comment block
+                            chunks.append([''.join(lines[chunk_start:line_index + 1]), relpath, chunk_start 
+ 1])
+                            # Data chunk after the GTK-Doc comment block starts at the next line
+                            chunk_start = line_index + 1
+                            # Store where the GTK-Doc comment block ends
+                            chunk_end = line_index
+
+                outputfile = os.path.join(gi_tests, '%s.xml.in' % relpath)
+                print('Writing "%s"' % outputfile)
+                with io.open(outputfile, 'w', newline='', encoding='utf-8') as f:
+                    f.write(HEADER)
+                    for chunk in chunks:
+                        docblock = parser.parse_comment_block(chunk[0].rstrip(), chunk[1], chunk[2])
+                        if docblock:
+                            f.write(TEST % {'docblock': chunk[0].rstrip(),
+                                            'tree': parsed2tree(docblock),
+                                            'serialized': writer.write(docblock).rstrip()})
+                    f.write(FOOTER)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]