We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Redundant inheritance lines in inheritance-graph printer
Hey guys! I've been using Slither for some time now and found it quite useful, so thanks for all the effort you put into developing this tool.

While using the `inheritance-graph` printer, I found that the resulting graph contains several redundant inheritance lines that should be better left off the graph. For instance: 
~~~solidity
pragma solidity ^0.4.25;
contract Grandparent { }
contract Parent is Grandparent {}
contract Child is Parent {}
~~~

Slither's printer output is:
![inheritance](https://user-images.githubusercontent.com/8171248/52140418-8188f400-2631-11e9-80bf-5466d8d86f8d.png)

Note that there's a line that goes from `Child` to `Grandparent` which is redundant, as `Child` is already `Parent` and `Parent` is already `Grandparent`. While this example is pretty simple, in far more complex inheritance chains these extra lines add little to no value and the graph ends up being too cluttered with lines pointing everywhere.

I'm not sure if this is a feature you added on purpose or a bug. If the former, are you considering adding an extra flag to the printer so those extra lines are not included in the final inheritance graph?.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `slither/printers/inheritance/inheritance.py`
Content:
```
1 """
2     Module printing the inheritance relation
3 
4     The inheritance shows the relation between the contracts
5 """
6 
7 from slither.printers.abstract_printer import AbstractPrinter
8 from slither.utils.colors import blue, green
9 
10 
11 class PrinterInheritance(AbstractPrinter):
12     ARGUMENT = 'inheritance'
13     HELP = 'Print the inheritance relations between contracts'
14 
15     def _get_child_contracts(self, base):
16         # Generate function to get all child contracts of a base contract
17         for child in self.contracts:
18             if base in child.inheritance:
19                 yield child
20 
21     def output(self, filename):
22         """
23             Output the inheritance relation
24 
25             _filename is not used
26             Args:
27                 _filename(string)
28         """
29         info = 'Inheritance\n'
30 
31         if not self.contracts:
32             return
33 
34         info += blue('Child_Contract -> ') + green('Base_Contracts')
35         for child in self.contracts:
36             info += blue(f'\n+ {child.name}')
37             if child.inheritance:
38                 info += ' -> ' + green(", ".join(map(str, child.inheritance)))
39 
40         info += green('\n\nBase_Contract -> ') + blue('Child_Contracts')
41         for base in self.contracts:
42             info += green(f'\n+ {base.name}')
43             children = list(self._get_child_contracts(base))
44             if children:
45                 info += ' -> ' + blue(", ".join(map(str, children)))
46         self.info(info)
47
```

Path: `slither/printers/inheritance/inheritance_graph.py`
Content:
```
1 """
2     Module printing the inheritance graph
3 
4     The inheritance graph shows the relation between the contracts
5     and their functions/modifiers/public variables.
6     The output is a dot file named filename.dot
7 """
8 
9 from slither.core.declarations.contract import Contract
10 from slither.detectors.shadowing.shadowing_functions import ShadowingFunctionsDetection
11 from slither.printers.abstract_printer import AbstractPrinter
12 
13 class PrinterInheritanceGraph(AbstractPrinter):
14     ARGUMENT = 'inheritance-graph'
15     HELP = 'Export the inheritance graph of each contract to a dot file'
16 
17     def __init__(self, slither, logger):
18         super(PrinterInheritanceGraph, self).__init__(slither, logger)
19 
20         inheritance = [x.inheritance for x in slither.contracts]
21         self.inheritance = set([item for sublist in inheritance for item in sublist])
22 
23         shadow = ShadowingFunctionsDetection(slither, None)
24         ret = shadow.detect()
25         functions_shadowed = {}
26         for s in ret:
27             if s['contractShadower'] not in functions_shadowed:
28                 functions_shadowed[s['contractShadower']] = []
29             functions_shadowed[s['contractShadower']] += s['functions']
30         self.functions_shadowed = functions_shadowed
31 
32     def _get_pattern_func(self, func, contract):
33         # Html pattern, each line is a row in a table
34         func_name = func.full_name
35         pattern = '<TR><TD align="left">    %s</TD></TR>'
36         pattern_shadow = '<TR><TD align="left"><font color="#FFA500">    %s</font></TD></TR>'
37         if contract.name in self.functions_shadowed:
38             if func_name in self.functions_shadowed[contract.name]:
39                 return pattern_shadow % func_name
40         return pattern % func_name
41 
42     def _get_pattern_var(self, var, contract):
43         # Html pattern, each line is a row in a table
44         var_name = var.name
45         pattern = '<TR><TD align="left">    %s</TD></TR>'
46         pattern_contract = '<TR><TD align="left">    %s<font color="blue" POINT-SIZE="10"> (%s)</font></TD></TR>'
47         # pattern_arrow  = '<TR><TD align="left" PORT="%s"><font color="blue">    %s</font></TD></TR>'
48         if isinstance(var.type, Contract):
49             return pattern_contract % (var_name, str(var.type))
50             # return pattern_arrow%(self._get_port_id(var, contract), var_name)
51         return pattern % var_name
52 
53     def _get_port_id(self, var, contract):
54         return "%s%s" % (var.name, contract.name)
55 
56     def _summary(self, contract):
57         """
58             Build summary using HTML
59         """
60         ret = ''
61         # Add arrows
62         for i in contract.inheritance:
63             ret += '%s -> %s;\n' % (contract.name, i)
64 
65         # Functions
66         visibilities = ['public', 'external']
67         public_functions = [self._get_pattern_func(f, contract) for f in contract.functions if
68                             not f.is_constructor and f.contract == contract and f.visibility in visibilities]
69         public_functions = ''.join(public_functions)
70         private_functions = [self._get_pattern_func(f, contract) for f in contract.functions if
71                              not f.is_constructor and f.contract == contract and f.visibility not in visibilities]
72         private_functions = ''.join(private_functions)
73         # Modifiers
74         modifiers = [self._get_pattern_func(m, contract) for m in contract.modifiers if m.contract == contract]
75         modifiers = ''.join(modifiers)
76         # Public variables
77         public_variables = [self._get_pattern_var(v, contract) for v in contract.variables if
78                             v.visibility in visibilities]
79         public_variables = ''.join(public_variables)
80 
81         private_variables = [self._get_pattern_var(v, contract) for v in contract.variables if
82                              not v.visibility in visibilities]
83         private_variables = ''.join(private_variables)
84 
85         # Build the node label
86         ret += '%s[shape="box"' % contract.name
87         ret += 'label=< <TABLE border="0">'
88         ret += '<TR><TD align="center"><B>%s</B></TD></TR>' % contract.name
89         if public_functions:
90             ret += '<TR><TD align="left"><I>Public Functions:</I></TD></TR>'
91             ret += '%s' % public_functions
92         if private_functions:
93             ret += '<TR><TD align="left"><I>Private Functions:</I></TD></TR>'
94             ret += '%s' % private_functions
95         if modifiers:
96             ret += '<TR><TD align="left"><I>Modifiers:</I></TD></TR>'
97             ret += '%s' % modifiers
98         if public_variables:
99             ret += '<TR><TD align="left"><I>Public Variables:</I></TD></TR>'
100             ret += '%s' % public_variables
101         if private_variables:
102             ret += '<TR><TD align="left"><I>Private Variables:</I></TD></TR>'
103             ret += '%s' % private_variables
104         ret += '</TABLE> >];\n'
105 
106         return ret
107 
108     def output(self, filename):
109         """
110             Output the graph in filename
111             Args:
112                 filename(string)
113         """
114         if filename == '':
115             filename = 'export'
116         if not filename.endswith('.dot'):
117             filename += ".dot"
118         info = 'Inheritance Graph: ' + filename
119         self.info(info)
120         with open(filename, 'w', encoding='utf8') as f:
121             f.write('digraph{\n')
122             for c in self.contracts:
123                 f.write(self._summary(c))
124             f.write('}')
125
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/slither/printers/inheritance/inheritance.py b/slither/printers/inheritance/inheritance.py
--- a/slither/printers/inheritance/inheritance.py
+++ b/slither/printers/inheritance/inheritance.py
@@ -31,16 +31,26 @@
         if not self.contracts:
             return
 
-        info += blue('Child_Contract -> ') + green('Base_Contracts')
+        info += blue('Child_Contract -> ') + green('Immediate_Base_Contracts')
+        info += green(' [Not_Immediate_Base_Contracts]')
         for child in self.contracts:
             info += blue(f'\n+ {child.name}')
             if child.inheritance:
-                info += ' -> ' + green(", ".join(map(str, child.inheritance)))
-
-        info += green('\n\nBase_Contract -> ') + blue('Child_Contracts')
+                immediate = child.immediate_inheritance
+                not_immediate = [i for i in child.inheritance if i not in immediate]
+                info += ' -> ' + green(", ".join(map(str, immediate)))
+                if not_immediate:
+                    info += ", ["+ green(", ".join(map(str, not_immediate))) + "]"
+
+        info += green('\n\nBase_Contract -> ') + blue('Immediate_Child_Contracts')
+        info += blue(' [Not_Immediate_Child_Contracts]')
         for base in self.contracts:
             info += green(f'\n+ {base.name}')
             children = list(self._get_child_contracts(base))
             if children:
-                info += ' -> ' + blue(", ".join(map(str, children)))
+                immediate = [child for child in children if base in child.immediate_inheritance]
+                not_immediate = [child for child in children if not child in immediate]
+                info += ' -> ' + blue(", ".join(map(str, immediate)))
+                if not_immediate:
+                    info += ', [' + blue(", ".join(map(str, not_immediate))) + ']'
         self.info(info)
diff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py
--- a/slither/printers/inheritance/inheritance_graph.py
+++ b/slither/printers/inheritance/inheritance_graph.py
@@ -59,7 +59,7 @@
         """
         ret = ''
         # Add arrows
-        for i in contract.inheritance:
+        for i in contract.immediate_inheritance:
             ret += '%s -> %s;\n' % (contract.name, i)
 
         # Functions

{"golden_diff": "diff --git a/slither/printers/inheritance/inheritance.py b/slither/printers/inheritance/inheritance.py\n--- a/slither/printers/inheritance/inheritance.py\n+++ b/slither/printers/inheritance/inheritance.py\n@@ -31,16 +31,26 @@\n         if not self.contracts:\n             return\n \n-        info += blue('Child_Contract -> ') + green('Base_Contracts')\n+        info += blue('Child_Contract -> ') + green('Immediate_Base_Contracts')\n+        info += green(' [Not_Immediate_Base_Contracts]')\n         for child in self.contracts:\n             info += blue(f'\\n+ {child.name}')\n             if child.inheritance:\n-                info += ' -> ' + green(\", \".join(map(str, child.inheritance)))\n-\n-        info += green('\\n\\nBase_Contract -> ') + blue('Child_Contracts')\n+                immediate = child.immediate_inheritance\n+                not_immediate = [i for i in child.inheritance if i not in immediate]\n+                info += ' -> ' + green(\", \".join(map(str, immediate)))\n+                if not_immediate:\n+                    info += \", [\"+ green(\", \".join(map(str, not_immediate))) + \"]\"\n+\n+        info += green('\\n\\nBase_Contract -> ') + blue('Immediate_Child_Contracts')\n+        info += blue(' [Not_Immediate_Child_Contracts]')\n         for base in self.contracts:\n             info += green(f'\\n+ {base.name}')\n             children = list(self._get_child_contracts(base))\n             if children:\n-                info += ' -> ' + blue(\", \".join(map(str, children)))\n+                immediate = [child for child in children if base in child.immediate_inheritance]\n+                not_immediate = [child for child in children if not child in immediate]\n+                info += ' -> ' + blue(\", \".join(map(str, immediate)))\n+                if not_immediate:\n+                    info += ', [' + blue(\", \".join(map(str, not_immediate))) + ']'\n         self.info(info)\ndiff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py\n--- a/slither/printers/inheritance/inheritance_graph.py\n+++ b/slither/printers/inheritance/inheritance_graph.py\n@@ -59,7 +59,7 @@\n         \"\"\"\n         ret = ''\n         # Add arrows\n-        for i in contract.inheritance:\n+        for i in contract.immediate_inheritance:\n             ret += '%s -> %s;\\n' % (contract.name, i)\n \n         # Functions\n", "issue": "Redundant inheritance lines in inheritance-graph printer\nHey guys! I've been using Slither for some time now and found it quite useful, so thanks for all the effort you put into developing this tool.\r\n\r\nWhile using the `inheritance-graph` printer, I found that the resulting graph contains several redundant inheritance lines that should be better left off the graph. For instance: \r\n~~~solidity\r\npragma solidity ^0.4.25;\r\ncontract Grandparent { }\r\ncontract Parent is Grandparent {}\r\ncontract Child is Parent {}\r\n~~~\r\n\r\nSlither's printer output is:\r\n![inheritance](https://user-images.githubusercontent.com/8171248/52140418-8188f400-2631-11e9-80bf-5466d8d86f8d.png)\r\n\r\nNote that there's a line that goes from `Child` to `Grandparent` which is redundant, as `Child` is already `Parent` and `Parent` is already `Grandparent`. While this example is pretty simple, in far more complex inheritance chains these extra lines add little to no value and the graph ends up being too cluttered with lines pointing everywhere.\r\n\r\nI'm not sure if this is a feature you added on purpose or a bug. If the former, are you considering adding an extra flag to the printer so those extra lines are not included in the final inheritance graph?.\n", "before_files": [{"content": "\"\"\"\n    Module printing the inheritance relation\n\n    The inheritance shows the relation between the contracts\n\"\"\"\n\nfrom slither.printers.abstract_printer import AbstractPrinter\nfrom slither.utils.colors import blue, green\n\n\nclass PrinterInheritance(AbstractPrinter):\n    ARGUMENT = 'inheritance'\n    HELP = 'Print the inheritance relations between contracts'\n\n    def _get_child_contracts(self, base):\n        # Generate function to get all child contracts of a base contract\n        for child in self.contracts:\n            if base in child.inheritance:\n                yield child\n\n    def output(self, filename):\n        \"\"\"\n            Output the inheritance relation\n\n            _filename is not used\n            Args:\n                _filename(string)\n        \"\"\"\n        info = 'Inheritance\\n'\n\n        if not self.contracts:\n            return\n\n        info += blue('Child_Contract -> ') + green('Base_Contracts')\n        for child in self.contracts:\n            info += blue(f'\\n+ {child.name}')\n            if child.inheritance:\n                info += ' -> ' + green(\", \".join(map(str, child.inheritance)))\n\n        info += green('\\n\\nBase_Contract -> ') + blue('Child_Contracts')\n        for base in self.contracts:\n            info += green(f'\\n+ {base.name}')\n            children = list(self._get_child_contracts(base))\n            if children:\n                info += ' -> ' + blue(\", \".join(map(str, children)))\n        self.info(info)\n", "path": "slither/printers/inheritance/inheritance.py"}, {"content": "\"\"\"\n    Module printing the inheritance graph\n\n    The inheritance graph shows the relation between the contracts\n    and their functions/modifiers/public variables.\n    The output is a dot file named filename.dot\n\"\"\"\n\nfrom slither.core.declarations.contract import Contract\nfrom slither.detectors.shadowing.shadowing_functions import ShadowingFunctionsDetection\nfrom slither.printers.abstract_printer import AbstractPrinter\n\nclass PrinterInheritanceGraph(AbstractPrinter):\n    ARGUMENT = 'inheritance-graph'\n    HELP = 'Export the inheritance graph of each contract to a dot file'\n\n    def __init__(self, slither, logger):\n        super(PrinterInheritanceGraph, self).__init__(slither, logger)\n\n        inheritance = [x.inheritance for x in slither.contracts]\n        self.inheritance = set([item for sublist in inheritance for item in sublist])\n\n        shadow = ShadowingFunctionsDetection(slither, None)\n        ret = shadow.detect()\n        functions_shadowed = {}\n        for s in ret:\n            if s['contractShadower'] not in functions_shadowed:\n                functions_shadowed[s['contractShadower']] = []\n            functions_shadowed[s['contractShadower']] += s['functions']\n        self.functions_shadowed = functions_shadowed\n\n    def _get_pattern_func(self, func, contract):\n        # Html pattern, each line is a row in a table\n        func_name = func.full_name\n        pattern = '<TR><TD align=\"left\">    %s</TD></TR>'\n        pattern_shadow = '<TR><TD align=\"left\"><font color=\"#FFA500\">    %s</font></TD></TR>'\n        if contract.name in self.functions_shadowed:\n            if func_name in self.functions_shadowed[contract.name]:\n                return pattern_shadow % func_name\n        return pattern % func_name\n\n    def _get_pattern_var(self, var, contract):\n        # Html pattern, each line is a row in a table\n        var_name = var.name\n        pattern = '<TR><TD align=\"left\">    %s</TD></TR>'\n        pattern_contract = '<TR><TD align=\"left\">    %s<font color=\"blue\" POINT-SIZE=\"10\"> (%s)</font></TD></TR>'\n        # pattern_arrow  = '<TR><TD align=\"left\" PORT=\"%s\"><font color=\"blue\">    %s</font></TD></TR>'\n        if isinstance(var.type, Contract):\n            return pattern_contract % (var_name, str(var.type))\n            # return pattern_arrow%(self._get_port_id(var, contract), var_name)\n        return pattern % var_name\n\n    def _get_port_id(self, var, contract):\n        return \"%s%s\" % (var.name, contract.name)\n\n    def _summary(self, contract):\n        \"\"\"\n            Build summary using HTML\n        \"\"\"\n        ret = ''\n        # Add arrows\n        for i in contract.inheritance:\n            ret += '%s -> %s;\\n' % (contract.name, i)\n\n        # Functions\n        visibilities = ['public', 'external']\n        public_functions = [self._get_pattern_func(f, contract) for f in contract.functions if\n                            not f.is_constructor and f.contract == contract and f.visibility in visibilities]\n        public_functions = ''.join(public_functions)\n        private_functions = [self._get_pattern_func(f, contract) for f in contract.functions if\n                             not f.is_constructor and f.contract == contract and f.visibility not in visibilities]\n        private_functions = ''.join(private_functions)\n        # Modifiers\n        modifiers = [self._get_pattern_func(m, contract) for m in contract.modifiers if m.contract == contract]\n        modifiers = ''.join(modifiers)\n        # Public variables\n        public_variables = [self._get_pattern_var(v, contract) for v in contract.variables if\n                            v.visibility in visibilities]\n        public_variables = ''.join(public_variables)\n\n        private_variables = [self._get_pattern_var(v, contract) for v in contract.variables if\n                             not v.visibility in visibilities]\n        private_variables = ''.join(private_variables)\n\n        # Build the node label\n        ret += '%s[shape=\"box\"' % contract.name\n        ret += 'label=< <TABLE border=\"0\">'\n        ret += '<TR><TD align=\"center\"><B>%s</B></TD></TR>' % contract.name\n        if public_functions:\n            ret += '<TR><TD align=\"left\"><I>Public Functions:</I></TD></TR>'\n            ret += '%s' % public_functions\n        if private_functions:\n            ret += '<TR><TD align=\"left\"><I>Private Functions:</I></TD></TR>'\n            ret += '%s' % private_functions\n        if modifiers:\n            ret += '<TR><TD align=\"left\"><I>Modifiers:</I></TD></TR>'\n            ret += '%s' % modifiers\n        if public_variables:\n            ret += '<TR><TD align=\"left\"><I>Public Variables:</I></TD></TR>'\n            ret += '%s' % public_variables\n        if private_variables:\n            ret += '<TR><TD align=\"left\"><I>Private Variables:</I></TD></TR>'\n            ret += '%s' % private_variables\n        ret += '</TABLE> >];\\n'\n\n        return ret\n\n    def output(self, filename):\n        \"\"\"\n            Output the graph in filename\n            Args:\n                filename(string)\n        \"\"\"\n        if filename == '':\n            filename = 'export'\n        if not filename.endswith('.dot'):\n            filename += \".dot\"\n        info = 'Inheritance Graph: ' + filename\n        self.info(info)\n        with open(filename, 'w', encoding='utf8') as f:\n            f.write('digraph{\\n')\n            for c in self.contracts:\n                f.write(self._summary(c))\n            f.write('}')\n", "path": "slither/printers/inheritance/inheritance_graph.py"}], "after_files": [{"content": "\"\"\"\n    Module printing the inheritance relation\n\n    The inheritance shows the relation between the contracts\n\"\"\"\n\nfrom slither.printers.abstract_printer import AbstractPrinter\nfrom slither.utils.colors import blue, green\n\n\nclass PrinterInheritance(AbstractPrinter):\n    ARGUMENT = 'inheritance'\n    HELP = 'Print the inheritance relations between contracts'\n\n    def _get_child_contracts(self, base):\n        # Generate function to get all child contracts of a base contract\n        for child in self.contracts:\n            if base in child.inheritance:\n                yield child\n\n    def output(self, filename):\n        \"\"\"\n            Output the inheritance relation\n\n            _filename is not used\n            Args:\n                _filename(string)\n        \"\"\"\n        info = 'Inheritance\\n'\n\n        if not self.contracts:\n            return\n\n        info += blue('Child_Contract -> ') + green('Immediate_Base_Contracts')\n        info += green(' [Not_Immediate_Base_Contracts]')\n        for child in self.contracts:\n            info += blue(f'\\n+ {child.name}')\n            if child.inheritance:\n                immediate = child.immediate_inheritance\n                not_immediate = [i for i in child.inheritance if i not in immediate]\n                info += ' -> ' + green(\", \".join(map(str, immediate)))\n                if not_immediate:\n                    info += \", [\"+ green(\", \".join(map(str, not_immediate))) + \"]\"\n\n        info += green('\\n\\nBase_Contract -> ') + blue('Immediate_Child_Contracts')\n        info += blue(' [Not_Immediate_Child_Contracts]')\n        for base in self.contracts:\n            info += green(f'\\n+ {base.name}')\n            children = list(self._get_child_contracts(base))\n            if children:\n                immediate = [child for child in children if base in child.immediate_inheritance]\n                not_immediate = [child for child in children if not child in immediate]\n                info += ' -> ' + blue(\", \".join(map(str, immediate)))\n                if not_immediate:\n                    info += ', [' + blue(\", \".join(map(str, not_immediate))) + ']'\n        self.info(info)\n", "path": "slither/printers/inheritance/inheritance.py"}, {"content": "\"\"\"\n    Module printing the inheritance graph\n\n    The inheritance graph shows the relation between the contracts\n    and their functions/modifiers/public variables.\n    The output is a dot file named filename.dot\n\"\"\"\n\nfrom slither.core.declarations.contract import Contract\nfrom slither.detectors.shadowing.shadowing_functions import ShadowingFunctionsDetection\nfrom slither.printers.abstract_printer import AbstractPrinter\n\nclass PrinterInheritanceGraph(AbstractPrinter):\n    ARGUMENT = 'inheritance-graph'\n    HELP = 'Export the inheritance graph of each contract to a dot file'\n\n    def __init__(self, slither, logger):\n        super(PrinterInheritanceGraph, self).__init__(slither, logger)\n\n        inheritance = [x.inheritance for x in slither.contracts]\n        self.inheritance = set([item for sublist in inheritance for item in sublist])\n\n        shadow = ShadowingFunctionsDetection(slither, None)\n        ret = shadow.detect()\n        functions_shadowed = {}\n        for s in ret:\n            if s['contractShadower'] not in functions_shadowed:\n                functions_shadowed[s['contractShadower']] = []\n            functions_shadowed[s['contractShadower']] += s['functions']\n        self.functions_shadowed = functions_shadowed\n\n    def _get_pattern_func(self, func, contract):\n        # Html pattern, each line is a row in a table\n        func_name = func.full_name\n        pattern = '<TR><TD align=\"left\">    %s</TD></TR>'\n        pattern_shadow = '<TR><TD align=\"left\"><font color=\"#FFA500\">    %s</font></TD></TR>'\n        if contract.name in self.functions_shadowed:\n            if func_name in self.functions_shadowed[contract.name]:\n                return pattern_shadow % func_name\n        return pattern % func_name\n\n    def _get_pattern_var(self, var, contract):\n        # Html pattern, each line is a row in a table\n        var_name = var.name\n        pattern = '<TR><TD align=\"left\">    %s</TD></TR>'\n        pattern_contract = '<TR><TD align=\"left\">    %s<font color=\"blue\" POINT-SIZE=\"10\"> (%s)</font></TD></TR>'\n        # pattern_arrow  = '<TR><TD align=\"left\" PORT=\"%s\"><font color=\"blue\">    %s</font></TD></TR>'\n        if isinstance(var.type, Contract):\n            return pattern_contract % (var_name, str(var.type))\n            # return pattern_arrow%(self._get_port_id(var, contract), var_name)\n        return pattern % var_name\n\n    def _get_port_id(self, var, contract):\n        return \"%s%s\" % (var.name, contract.name)\n\n    def _summary(self, contract):\n        \"\"\"\n            Build summary using HTML\n        \"\"\"\n        ret = ''\n        # Add arrows\n        for i in contract.immediate_inheritance:\n            ret += '%s -> %s;\\n' % (contract.name, i)\n\n        # Functions\n        visibilities = ['public', 'external']\n        public_functions = [self._get_pattern_func(f, contract) for f in contract.functions if\n                            not f.is_constructor and f.contract == contract and f.visibility in visibilities]\n        public_functions = ''.join(public_functions)\n        private_functions = [self._get_pattern_func(f, contract) for f in contract.functions if\n                             not f.is_constructor and f.contract == contract and f.visibility not in visibilities]\n        private_functions = ''.join(private_functions)\n        # Modifiers\n        modifiers = [self._get_pattern_func(m, contract) for m in contract.modifiers if m.contract == contract]\n        modifiers = ''.join(modifiers)\n        # Public variables\n        public_variables = [self._get_pattern_var(v, contract) for v in contract.variables if\n                            v.visibility in visibilities]\n        public_variables = ''.join(public_variables)\n\n        private_variables = [self._get_pattern_var(v, contract) for v in contract.variables if\n                             not v.visibility in visibilities]\n        private_variables = ''.join(private_variables)\n\n        # Build the node label\n        ret += '%s[shape=\"box\"' % contract.name\n        ret += 'label=< <TABLE border=\"0\">'\n        ret += '<TR><TD align=\"center\"><B>%s</B></TD></TR>' % contract.name\n        if public_functions:\n            ret += '<TR><TD align=\"left\"><I>Public Functions:</I></TD></TR>'\n            ret += '%s' % public_functions\n        if private_functions:\n            ret += '<TR><TD align=\"left\"><I>Private Functions:</I></TD></TR>'\n            ret += '%s' % private_functions\n        if modifiers:\n            ret += '<TR><TD align=\"left\"><I>Modifiers:</I></TD></TR>'\n            ret += '%s' % modifiers\n        if public_variables:\n            ret += '<TR><TD align=\"left\"><I>Public Variables:</I></TD></TR>'\n            ret += '%s' % public_variables\n        if private_variables:\n            ret += '<TR><TD align=\"left\"><I>Private Variables:</I></TD></TR>'\n            ret += '%s' % private_variables\n        ret += '</TABLE> >];\\n'\n\n        return ret\n\n    def output(self, filename):\n        \"\"\"\n            Output the graph in filename\n            Args:\n                filename(string)\n        \"\"\"\n        if filename == '':\n            filename = 'export'\n        if not filename.endswith('.dot'):\n            filename += \".dot\"\n        info = 'Inheritance Graph: ' + filename\n        self.info(info)\n        with open(filename, 'w', encoding='utf8') as f:\n            f.write('digraph{\\n')\n            for c in self.contracts:\n                f.write(self._summary(c))\n            f.write('}')\n", "path": "slither/printers/inheritance/inheritance_graph.py"}]}