/circuits/tools/__init__.py

https://bitbucket.org/prologic/circuits/ · Python · 167 lines · 138 code · 18 blank · 11 comment · 18 complexity · 96032ea6746b7586e72ce55f0390728f MD5 · raw file

  1. # Module: __init__
  2. # Date: 8th November 2008
  3. # Author: James Mills, prologic at shortcircuit dot net dot au
  4. """Circuits Tools
  5. circuits.tools contains a standard set of tools for circuits. These
  6. tools are installed as executables with a prefix of "circuits."
  7. """
  8. from functools import wraps
  9. from warnings import warn, warn_explicit
  10. from circuits.six import _func_code
  11. def tryimport(modules, obj=None, message=None):
  12. modules = (modules,) if isinstance(modules, str) else modules
  13. for module in modules:
  14. try:
  15. m = __import__(module, globals(), locals())
  16. return getattr(m, obj) if obj is not None else m
  17. except:
  18. pass
  19. if message is not None:
  20. warn(message)
  21. def walk(x, f, d=0, v=None):
  22. if not v:
  23. v = set()
  24. yield f(d, x)
  25. for c in x.components.copy():
  26. if c not in v:
  27. v.add(c)
  28. for r in walk(c, f, d + 1, v):
  29. yield r
  30. def edges(x, e=None, v=None, d=0):
  31. if not e:
  32. e = set()
  33. if not v:
  34. v = []
  35. d += 1
  36. for c in x.components.copy():
  37. e.add((x, c, d))
  38. edges(c, e, v, d)
  39. return e
  40. def findroot(x):
  41. if x.parent == x:
  42. return x
  43. else:
  44. return findroot(x.parent)
  45. def kill(x):
  46. for c in x.components.copy():
  47. kill(c)
  48. if x.parent is not x:
  49. x.unregister()
  50. def graph(x, name=None):
  51. """Display a directed graph of the Component structure of x
  52. :param x: A Component or Manager to graph
  53. :type x: Component or Manager
  54. :param name: A name for the graph (defaults to x's name)
  55. :type name: str
  56. @return: A directed graph representing x's Component structure.
  57. @rtype: str
  58. """
  59. networkx = tryimport("networkx")
  60. pygraphviz = tryimport("pygraphviz")
  61. plt = tryimport("matplotlib.pyplot", "pyplot")
  62. if networkx is not None and pygraphviz is not None and plt is not None:
  63. graph_edges = []
  64. for (u, v, d) in edges(x):
  65. graph_edges.append((u.name, v.name, float(d)))
  66. g = networkx.DiGraph()
  67. g.add_weighted_edges_from(graph_edges)
  68. elarge = [(u, v) for (u, v, d) in g.edges(data=True)
  69. if d["weight"] > 3.0]
  70. esmall = [(u, v) for (u, v, d) in g.edges(data=True)
  71. if d["weight"] <= 3.0]
  72. pos = networkx.spring_layout(g) # positions for all nodes
  73. # nodes
  74. networkx.draw_networkx_nodes(g, pos, node_size=700)
  75. # edges
  76. networkx.draw_networkx_edges(g, pos, edgelist=elarge, width=1)
  77. networkx.draw_networkx_edges(
  78. g, pos, edgelist=esmall, width=1,
  79. alpha=0.5, edge_color="b", style="dashed"
  80. )
  81. # labels
  82. networkx.draw_networkx_labels(
  83. g, pos, font_size=10, font_family="sans-serif"
  84. )
  85. plt.axis("off")
  86. plt.savefig("{0:s}.png".format(name or x.name))
  87. networkx.write_dot(g, "{0:s}.dot".format(name or x.name))
  88. plt.clf()
  89. def printer(d, x):
  90. return "%s* %s" % (" " * d, x)
  91. return "\n".join(walk(x, printer))
  92. def inspect(x):
  93. """Display an inspection report of the Component or Manager x
  94. :param x: A Component or Manager to graph
  95. :type x: Component or Manager
  96. @return: A detailed inspection report of x
  97. @rtype: str
  98. """
  99. s = []
  100. write = s.append
  101. write(" Components: %d\n" % len(x.components))
  102. for component in x.components:
  103. write(" %s\n" % component)
  104. write("\n")
  105. from circuits import reprhandler
  106. write(" Event Handlers: %d\n" % len(x._handlers.values()))
  107. for event, handlers in x._handlers.items():
  108. write(" %s; %d\n" % (event, len(x._handlers[event])))
  109. for handler in x._handlers[event]:
  110. write(" %s\n" % reprhandler(handler))
  111. return "".join(s)
  112. def deprecated(f):
  113. @wraps(f)
  114. def wrapper(*args, **kwargs):
  115. warn_explicit(
  116. "Call to deprecated function {0:s}".format(f.__name__),
  117. category=DeprecationWarning,
  118. filename=getattr(f, _func_code).co_filename,
  119. lineno=getattr(f, _func_code).co_firstlineno + 1
  120. )
  121. return f(*args, **kwargs)
  122. return wrapper