diff options
author | Dieter Verfaillie <dieterv@optionexplicit.be> | 2015-06-23 20:13:17 +0200 |
---|---|---|
committer | Dieter Verfaillie <dieterv@optionexplicit.be> | 2015-06-24 22:03:56 +0200 |
commit | c7144d0ccc4ddca73c4ff690e147d247aedb2def (patch) | |
tree | 6954ad2be9ebcb25f090d92344e0ab8b113f560e | |
parent | 5f72748c8f1e8313b7f6c4c296cffdae7095cfbe (diff) | |
download | gobject-introspection-c7144d0ccc4ddca73c4ff690e147d247aedb2def.tar.gz |
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
-rw-r--r-- | 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 00000000..4c1ec138 --- /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) |