8th day of python challenges 111-117
This commit is contained in:
212
venv/lib/python3.6/site-packages/pylint/pyreverse/writer.py
Normal file
212
venv/lib/python3.6/site-packages/pylint/pyreverse/writer.py
Normal file
@@ -0,0 +1,212 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2008-2010, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||
# Copyright (c) 2014 Arun Persaud <arun@nubati.net>
|
||||
# Copyright (c) 2015-2017 Claudiu Popa <pcmanticore@gmail.com>
|
||||
# Copyright (c) 2015 Mike Frysinger <vapier@gentoo.org>
|
||||
# Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
|
||||
# Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
|
||||
# Copyright (c) 2018 ssolanki <sushobhitsolanki@gmail.com>
|
||||
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
|
||||
|
||||
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
|
||||
|
||||
"""Utilities for creating VCG and Dot diagrams"""
|
||||
|
||||
from pylint.pyreverse.utils import is_exception
|
||||
from pylint.pyreverse.vcgutils import VCGPrinter
|
||||
from pylint.graph import DotBackend
|
||||
|
||||
|
||||
class DiagramWriter:
|
||||
"""base class for writing project diagrams
|
||||
"""
|
||||
|
||||
def __init__(self, config, styles):
|
||||
self.config = config
|
||||
self.pkg_edges, self.inh_edges, self.imp_edges, self.association_edges = styles
|
||||
self.printer = None # defined in set_printer
|
||||
|
||||
def write(self, diadefs):
|
||||
"""write files for <project> according to <diadefs>
|
||||
"""
|
||||
for diagram in diadefs:
|
||||
basename = diagram.title.strip().replace(" ", "_")
|
||||
file_name = "%s.%s" % (basename, self.config.output_format)
|
||||
self.set_printer(file_name, basename)
|
||||
if diagram.TYPE == "class":
|
||||
self.write_classes(diagram)
|
||||
else:
|
||||
self.write_packages(diagram)
|
||||
self.close_graph()
|
||||
|
||||
def write_packages(self, diagram):
|
||||
"""write a package diagram"""
|
||||
# sorted to get predictable (hence testable) results
|
||||
for i, obj in enumerate(sorted(diagram.modules(), key=lambda x: x.title)):
|
||||
self.printer.emit_node(i, label=self.get_title(obj), shape="box")
|
||||
obj.fig_id = i
|
||||
# package dependencies
|
||||
for rel in diagram.get_relationships("depends"):
|
||||
self.printer.emit_edge(
|
||||
rel.from_object.fig_id, rel.to_object.fig_id, **self.pkg_edges
|
||||
)
|
||||
|
||||
def write_classes(self, diagram):
|
||||
"""write a class diagram"""
|
||||
# sorted to get predictable (hence testable) results
|
||||
for i, obj in enumerate(sorted(diagram.objects, key=lambda x: x.title)):
|
||||
self.printer.emit_node(i, **self.get_values(obj))
|
||||
obj.fig_id = i
|
||||
# inheritance links
|
||||
for rel in diagram.get_relationships("specialization"):
|
||||
self.printer.emit_edge(
|
||||
rel.from_object.fig_id, rel.to_object.fig_id, **self.inh_edges
|
||||
)
|
||||
# implementation links
|
||||
for rel in diagram.get_relationships("implements"):
|
||||
self.printer.emit_edge(
|
||||
rel.from_object.fig_id, rel.to_object.fig_id, **self.imp_edges
|
||||
)
|
||||
# generate associations
|
||||
for rel in diagram.get_relationships("association"):
|
||||
self.printer.emit_edge(
|
||||
rel.from_object.fig_id,
|
||||
rel.to_object.fig_id,
|
||||
label=rel.name,
|
||||
**self.association_edges
|
||||
)
|
||||
|
||||
def set_printer(self, file_name, basename):
|
||||
"""set printer"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_title(self, obj):
|
||||
"""get project title"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_values(self, obj):
|
||||
"""get label and shape for classes."""
|
||||
raise NotImplementedError
|
||||
|
||||
def close_graph(self):
|
||||
"""finalize the graph"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class DotWriter(DiagramWriter):
|
||||
"""write dot graphs from a diagram definition and a project
|
||||
"""
|
||||
|
||||
def __init__(self, config):
|
||||
styles = [
|
||||
dict(arrowtail="none", arrowhead="open"),
|
||||
dict(arrowtail="none", arrowhead="empty"),
|
||||
dict(arrowtail="node", arrowhead="empty", style="dashed"),
|
||||
dict(
|
||||
fontcolor="green", arrowtail="none", arrowhead="diamond", style="solid"
|
||||
),
|
||||
]
|
||||
DiagramWriter.__init__(self, config, styles)
|
||||
|
||||
def set_printer(self, file_name, basename):
|
||||
"""initialize DotWriter and add options for layout.
|
||||
"""
|
||||
layout = dict(rankdir="BT")
|
||||
self.printer = DotBackend(basename, additional_param=layout)
|
||||
self.file_name = file_name
|
||||
|
||||
def get_title(self, obj):
|
||||
"""get project title"""
|
||||
return obj.title
|
||||
|
||||
def get_values(self, obj):
|
||||
"""get label and shape for classes.
|
||||
|
||||
The label contains all attributes and methods
|
||||
"""
|
||||
label = obj.title
|
||||
if obj.shape == "interface":
|
||||
label = "«interface»\\n%s" % label
|
||||
if not self.config.only_classnames:
|
||||
label = r"%s|%s\l|" % (label, r"\l".join(obj.attrs))
|
||||
for func in obj.methods:
|
||||
label = r"%s%s()\l" % (label, func.name)
|
||||
label = "{%s}" % label
|
||||
if is_exception(obj.node):
|
||||
return dict(fontcolor="red", label=label, shape="record")
|
||||
return dict(label=label, shape="record")
|
||||
|
||||
def close_graph(self):
|
||||
"""print the dot graph into <file_name>"""
|
||||
self.printer.generate(self.file_name)
|
||||
|
||||
|
||||
class VCGWriter(DiagramWriter):
|
||||
"""write vcg graphs from a diagram definition and a project
|
||||
"""
|
||||
|
||||
def __init__(self, config):
|
||||
styles = [
|
||||
dict(arrowstyle="solid", backarrowstyle="none", backarrowsize=0),
|
||||
dict(arrowstyle="solid", backarrowstyle="none", backarrowsize=10),
|
||||
dict(
|
||||
arrowstyle="solid",
|
||||
backarrowstyle="none",
|
||||
linestyle="dotted",
|
||||
backarrowsize=10,
|
||||
),
|
||||
dict(arrowstyle="solid", backarrowstyle="none", textcolor="green"),
|
||||
]
|
||||
DiagramWriter.__init__(self, config, styles)
|
||||
|
||||
def set_printer(self, file_name, basename):
|
||||
"""initialize VCGWriter for a UML graph"""
|
||||
self.graph_file = open(file_name, "w+")
|
||||
self.printer = VCGPrinter(self.graph_file)
|
||||
self.printer.open_graph(
|
||||
title=basename,
|
||||
layoutalgorithm="dfs",
|
||||
late_edge_labels="yes",
|
||||
port_sharing="no",
|
||||
manhattan_edges="yes",
|
||||
)
|
||||
self.printer.emit_node = self.printer.node
|
||||
self.printer.emit_edge = self.printer.edge
|
||||
|
||||
def get_title(self, obj):
|
||||
"""get project title in vcg format"""
|
||||
return r"\fb%s\fn" % obj.title
|
||||
|
||||
def get_values(self, obj):
|
||||
"""get label and shape for classes.
|
||||
|
||||
The label contains all attributes and methods
|
||||
"""
|
||||
if is_exception(obj.node):
|
||||
label = r"\fb\f09%s\fn" % obj.title
|
||||
else:
|
||||
label = r"\fb%s\fn" % obj.title
|
||||
if obj.shape == "interface":
|
||||
shape = "ellipse"
|
||||
else:
|
||||
shape = "box"
|
||||
if not self.config.only_classnames:
|
||||
attrs = obj.attrs
|
||||
methods = [func.name for func in obj.methods]
|
||||
# box width for UML like diagram
|
||||
maxlen = max(len(name) for name in [obj.title] + methods + attrs)
|
||||
line = "_" * (maxlen + 2)
|
||||
label = r"%s\n\f%s" % (label, line)
|
||||
for attr in attrs:
|
||||
label = r"%s\n\f08%s" % (label, attr)
|
||||
if attrs:
|
||||
label = r"%s\n\f%s" % (label, line)
|
||||
for func in methods:
|
||||
label = r"%s\n\f10%s()" % (label, func)
|
||||
return dict(label=label, shape=shape)
|
||||
|
||||
def close_graph(self):
|
||||
"""close graph and file"""
|
||||
self.printer.close_graph()
|
||||
self.graph_file.close()
|
||||
Reference in New Issue
Block a user