diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-06-16 10:24:49 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-06-16 21:12:12 +0000 |
commit | 54a8785cab070bca044ca0ceeff3219e20514a37 (patch) | |
tree | 91bd72e1b2da84df4b1dd25df7ef28b4600f7868 | |
parent | 69a353f625ac8d4ae0a3d53ca804ebd7bbf47647 (diff) |
Split out a test driver from the Sphinx inheritance graph generation
Similar to 5b0918c6c6fa575a16b3ec1637281397e951f62b,
3a1e793c0a91deae4e986efb11724040349ce9ca.
Add a note to the README.md and fix it to be viewable.
Task-number: PYSIDE-2362
Task-number: PYSIDE-1106
Change-Id: I1c0bbc745fffc16d6981e806618c1fce04ac8d18
Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit 7008aa6bd17d1f56b54c30e60110668aed79a3cb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | sources/pyside6/doc/README.md | 15 | ||||
-rw-r--r-- | sources/pyside6/doc/inheritance_diagram.py | 102 | ||||
-rw-r--r-- | sources/pyside6/doc/inheritance_diagram.pyproject | 6 | ||||
-rw-r--r-- | sources/pyside6/doc/inheritance_graph.py | 126 |
4 files changed, 148 insertions, 101 deletions
diff --git a/sources/pyside6/doc/README.md b/sources/pyside6/doc/README.md index 88bf3a64d..746e44989 100644 --- a/sources/pyside6/doc/README.md +++ b/sources/pyside6/doc/README.md @@ -4,7 +4,7 @@ The source tree contains .rst files containing the module description in doc/extras (named for example "QtCore.rst"). They are extracted/adapted from the C++ module descriptions. If there is no module description file, shiboken will extract the module description from the webxml files generated by qdoc. -This ends up in the build directory under doc/rst/PySide6/<module>/index.rst. +This ends up in the build directory under doc/rst/PySide6/<module>/index.rst. It can be used as a starting point for a module description file. C++ specific information like build instructions should be removed. @@ -20,6 +20,7 @@ adaption by shiboken/sphinx. The list can be created by the below script and some hand-editing. It will find almost all documents. Quite a number of them might be unreferenced, but there is no good way of filtering for this. +Pages of examples that exist in Python should be removed. for F in *.webxml do @@ -32,3 +33,15 @@ is no good way of filtering for this. fi fi done + +# Inheritance graphs + +`inheritance_diagram.pyproject` lists the script involved in inheritance graph +generation, `inheritance_diagram.py` being the main one used by sphinx. The +others have main-test drivers for checking. + +There are 2 scripts used for determining the inheritance: +* json_inheritance.py (env var `INHERITANCE_FILE`) reads a + inheritance.json file containing the class hierarchy generated by + shiboken's doc generator. +* import_inheritance.py actually tries to import the class (legacy) diff --git a/sources/pyside6/doc/inheritance_diagram.py b/sources/pyside6/doc/inheritance_diagram.py index 22d7d87ad..d1e095ce6 100644 --- a/sources/pyside6/doc/inheritance_diagram.py +++ b/sources/pyside6/doc/inheritance_diagram.py @@ -48,111 +48,13 @@ from docutils.parsers.rst import directives, Directive from sphinx.ext.graphviz import render_dot_html, render_dot_latex +from inheritance_graph import InheritanceGraph from import_inheritance import (get_inheritance_entries_by_import, InheritanceException) from json_inheritance import (is_inheritance_from_json_enabled, get_inheritance_entries_from_json) -class InheritanceGraph(object): - """ - Given a list of classes, determines the set of classes that they inherit - from all the way to the root "object", and then is able to generate a - graphviz dot graph from them. - """ - def __init__(self, class_names, currmodule, show_builtins=False, parts=0): - """ - *class_names* is a list of child classes to show bases from. - - If *show_builtins* is True, then Python builtins will be shown - in the graph. - """ - self.class_names = class_names - if is_inheritance_from_json_enabled(): - self.class_info = get_inheritance_entries_from_json(class_names) - else: - self.class_info = get_inheritance_entries_by_import(class_names, - currmodule, - __builtins__, - show_builtins, - parts) - - def get_all_class_names(self): - """ - Get all of the class names involved in the graph. - """ - return [fullname for (_, fullname, _) in self.class_info] - - # These are the default attrs for graphviz - default_graph_attrs = { - 'rankdir': 'LR', - 'size': '"8.0, 12.0"', - } - default_node_attrs = { - 'shape': 'box', - 'fontsize': 10, - 'height': 0.25, - 'fontname': '"Vera Sans, DejaVu Sans, Liberation Sans, ' - 'Arial, Helvetica, sans"', - 'style': '"setlinewidth(0.5)"', - } - default_edge_attrs = { - 'arrowsize': 0.5, - 'style': '"setlinewidth(0.5)"', - } - - def _format_node_attrs(self, attrs): - return ','.join([f'{x[0]}={x[1]}' for x in attrs.items()]) - - def _format_graph_attrs(self, attrs): - return ''.join([f"{x[0]}={x[1]};\n" for x in attrs.items()]) - - def generate_dot(self, name, urls={}, env=None, - graph_attrs={}, node_attrs={}, edge_attrs={}): - """ - Generate a graphviz dot graph from the classes that - were passed in to __init__. - - *name* is the name of the graph. - - *urls* is a dictionary mapping class names to HTTP URLs. - - *graph_attrs*, *node_attrs*, *edge_attrs* are dictionaries containing - key/value pairs to pass on as graphviz properties. - """ - g_attrs = self.default_graph_attrs.copy() - n_attrs = self.default_node_attrs.copy() - e_attrs = self.default_edge_attrs.copy() - g_attrs.update(graph_attrs) - n_attrs.update(node_attrs) - e_attrs.update(edge_attrs) - if env: - g_attrs.update(env.config.inheritance_graph_attrs) - n_attrs.update(env.config.inheritance_node_attrs) - e_attrs.update(env.config.inheritance_edge_attrs) - - res = [] - res.append(f'digraph {name} {{\n') - res.append(self._format_graph_attrs(g_attrs)) - - for name, fullname, bases in self.class_info: - # Write the node - this_node_attrs = n_attrs.copy() - url = urls.get(fullname) - if url is not None: - this_node_attrs['URL'] = f'"{url}"' - this_node_attrs['target'] = '"_top"' # Browser target frame attribute (same page) - attribute = self._format_node_attrs(this_node_attrs) - res.append(f' "{name}" [{attribute}];\n') - - # Write the edges - for base_name in bases: - attribute = self._format_node_attrs(e_attrs) - res.append(f' "{base_name}" -> "{name}" [{attribute}];\n') - res.append('}\n') - return ''.join(res) - - class inheritance_diagram(nodes.General, nodes.Element): """ A docutils node to use as a placeholder for the inheritance diagram. @@ -186,7 +88,7 @@ class InheritanceDiagram(Directive): try: graph = InheritanceGraph( class_names, env.temp_data.get('py:module'), - parts=node['parts']) + __builtins__, parts=node['parts']) except InheritanceException as err: return [node.document.reporter.warning(err.args[0], line=self.lineno)] diff --git a/sources/pyside6/doc/inheritance_diagram.pyproject b/sources/pyside6/doc/inheritance_diagram.pyproject new file mode 100644 index 000000000..a44dc93b8 --- /dev/null +++ b/sources/pyside6/doc/inheritance_diagram.pyproject @@ -0,0 +1,6 @@ +{ + "files": ["inheritance_diagram.py", + "import_inheritance.py", + "inheritance_graph.py", + "json_inheritance.py"] +} diff --git a/sources/pyside6/doc/inheritance_graph.py b/sources/pyside6/doc/inheritance_graph.py new file mode 100644 index 000000000..2911b4582 --- /dev/null +++ b/sources/pyside6/doc/inheritance_graph.py @@ -0,0 +1,126 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +import sys + +from import_inheritance import (get_inheritance_entries_by_import, + InheritanceException) +from json_inheritance import (is_inheritance_from_json_enabled, + get_inheritance_entries_from_json) + + +TEST_DRIVER_USAGE = """Usage: inheritance_graph.py [module] [class] + +Example: +python inheritance_graph.py PySide6.QtWidgets PySide6.QtWidgets.QWizard +""" + + +class InheritanceGraph(object): + """ + Given a list of classes, determines the set of classes that they inherit + from all the way to the root "object", and then is able to generate a + graphviz dot graph from them. + """ + def __init__(self, class_names, currmodule, builtins=None, show_builtins=False, parts=0): + """ + *class_names* is a list of child classes to show bases from. + + If *show_builtins* is True, then Python builtins will be shown + in the graph. + """ + self.class_names = class_names + if is_inheritance_from_json_enabled(): + self.class_info = get_inheritance_entries_from_json(class_names) + else: + self.class_info = get_inheritance_entries_by_import(class_names, + currmodule, + builtins, + show_builtins, + parts) + + def get_all_class_names(self): + """ + Get all of the class names involved in the graph. + """ + return [fullname for (_, fullname, _) in self.class_info] + + # These are the default attrs for graphviz + default_graph_attrs = { + 'rankdir': 'LR', + 'size': '"8.0, 12.0"', + } + default_node_attrs = { + 'shape': 'box', + 'fontsize': 10, + 'height': 0.25, + 'fontname': '"Vera Sans, DejaVu Sans, Liberation Sans, ' + 'Arial, Helvetica, sans"', + 'style': '"setlinewidth(0.5)"', + } + default_edge_attrs = { + 'arrowsize': 0.5, + 'style': '"setlinewidth(0.5)"', + } + + def _format_node_attrs(self, attrs): + return ','.join([f'{x[0]}={x[1]}' for x in attrs.items()]) + + def _format_graph_attrs(self, attrs): + return ''.join([f"{x[0]}={x[1]};\n" for x in attrs.items()]) + + def generate_dot(self, name, urls={}, env=None, + graph_attrs={}, node_attrs={}, edge_attrs={}): + """ + Generate a graphviz dot graph from the classes that + were passed in to __init__. + + *name* is the name of the graph. + + *urls* is a dictionary mapping class names to HTTP URLs. + + *graph_attrs*, *node_attrs*, *edge_attrs* are dictionaries containing + key/value pairs to pass on as graphviz properties. + """ + g_attrs = self.default_graph_attrs.copy() + n_attrs = self.default_node_attrs.copy() + e_attrs = self.default_edge_attrs.copy() + g_attrs.update(graph_attrs) + n_attrs.update(node_attrs) + e_attrs.update(edge_attrs) + if env: + g_attrs.update(env.config.inheritance_graph_attrs) + n_attrs.update(env.config.inheritance_node_attrs) + e_attrs.update(env.config.inheritance_edge_attrs) + + res = [] + res.append(f'digraph {name} {{\n') + res.append(self._format_graph_attrs(g_attrs)) + + for name, fullname, bases in self.class_info: + # Write the node + this_node_attrs = n_attrs.copy() + url = urls.get(fullname) + if url is not None: + this_node_attrs['URL'] = f'"{url}"' + this_node_attrs['target'] = '"_top"' # Browser target frame attribute (same page) + attribute = self._format_node_attrs(this_node_attrs) + res.append(f' "{name}" [{attribute}];\n') + + # Write the edges + for base_name in bases: + attribute = self._format_node_attrs(e_attrs) + res.append(f' "{base_name}" -> "{name}" [{attribute}];\n') + res.append('}\n') + return ''.join(res) + + +if __name__ == "__main__": + if len(sys.argv) < 2: + print(TEST_DRIVER_USAGE) + sys.exit(-1) + module = sys.argv[1] + class_names = sys.argv[2:] + graph = InheritanceGraph(class_names, module) + dot = graph.generate_dot("test") + print(dot) |