Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/misc/classgraph.py
4036 views
1
r"""
2
Class inheritance graphs
3
"""
4
#*****************************************************************************
5
# Copyright (C) 2007 William Stein <[email protected]>
6
# 2011 Nicolas M. Thiery <nthiery at users.sf.net>
7
#
8
# Distributed under the terms of the GNU General Public License (GPL)
9
# http://www.gnu.org/licenses/
10
#******************************************************************************
11
12
import inspect
13
14
def class_graph(top, depth=5, name_filter=None, classes=None, as_graph = True):
15
"""
16
Returns the class inheritance graph of a module, class, or object
17
18
INPUT:
19
20
- ``top`` -- the module, class, or object to start with (e.g. ``sage``, ``Integer``, ``3``)
21
- ``depth`` -- maximal recursion depth within submodules (default: 5)
22
- ``name_filter`` -- e.g. 'sage.rings' to only consider classes in :mod:`sage.rings`
23
- ``classes`` -- optional dictionary to be filled in (it is also returned)
24
- ``as_graph`` -- a boolean (default: True)
25
26
OUTPUT:
27
28
- An oriented graph, with class names as vertices, and an edge
29
from each class to each of its bases.
30
31
EXAMPLES:
32
33
We construct the inheritance graph of the classes within a given module::
34
35
sage: from sage.rings.polynomial.padics import polynomial_padic_capped_relative_dense, polynomial_padic_flat
36
sage: G = class_graph(sage.rings.polynomial.padics); G
37
Digraph on 4 vertices
38
sage: G.vertices()
39
['Polynomial_generic_dense', 'Polynomial_generic_domain', 'Polynomial_padic_capped_relative_dense', 'Polynomial_padic_flat']
40
sage: G.edges(labels=False)
41
[('Polynomial_padic_capped_relative_dense', 'Polynomial_generic_domain'), ('Polynomial_padic_flat', 'Polynomial_generic_dense')]
42
43
We construct the inheritance graph of a given class::
44
45
sage: class_graph(Parent).edges(labels=False)
46
[('CategoryObject', 'SageObject'), ('Parent', 'CategoryObject'), ('SageObject', 'object')]
47
48
We construct the inheritance graph of the class of an object::
49
50
sage: class_graph([1,2,3]).edges(labels=False)
51
[('list', 'object')]
52
53
.. warning:: the output of ``class_graph`` used to be a dictionary
54
mapping each class name to the list of names of its bases. This
55
can be emulated by setting the option ``as_graph`` to ``False``::
56
57
sage: class_graph(sage.rings.polynomial.padics, depth=2, as_graph=False)
58
{'Polynomial_padic_capped_relative_dense': ['Polynomial_generic_domain'],
59
'Polynomial_padic_flat': ['Polynomial_generic_dense']}
60
61
62
.. note:: the ``classes`` and ``as_graph`` options are mostly
63
intended for internal recursive use.
64
65
.. note:: ``class_graph`` does not yet handle nested classes
66
67
TESTS::
68
69
sage: G = class_graph(sage.rings.polynomial.padics, depth=2); G
70
Digraph on 4 vertices
71
"""
72
# This function descends recursively down the submodules of the
73
# top module (if ``top`` is a module) and then down the hierarchy
74
# of classes. Along the way, the result is stored in the "global"
75
# dictionary ``classes`` which associates to each class the list
76
# of its bases.
77
78
# Termination
79
if depth < 0:
80
return classes
81
82
# (first recursive call)
83
if classes is None:
84
classes = dict()
85
86
# Build the list ``children`` of submodules (resp. base classes)
87
# of ``top`` the function will recurse through
88
if inspect.ismodule(top):
89
if top.__name__.endswith('.all'): # Ignore sage.rings.all and friends
90
return classes
91
if name_filter is None:
92
name_filter = top.__name__
93
children = [item for item in top.__dict__.values()
94
if inspect.ismodule(item) or inspect.isclass(item)]
95
depth = depth -1
96
elif inspect.isclass(top):
97
if name_filter is None:
98
name_filter = ""
99
if not top.__module__.startswith(name_filter):
100
return classes
101
children = top.__bases__
102
classes[top.__name__] = [e.__name__ for e in children]
103
else: # top is a plain Python object; inspect its class
104
children = [top.__class__]
105
106
# Recurse
107
for child in children:
108
class_graph(child, depth = depth, name_filter=name_filter, classes=classes, as_graph = False)
109
110
# (first recursive call): construct the graph
111
if as_graph:
112
from sage.graphs.digraph import DiGraph
113
return DiGraph(classes)
114
else:
115
return classes
116
117
118