diff --git a/linesman/__init__.py b/linesman/__init__.py
index e87a5a6..93d8e5b 100644
--- a/linesman/__init__.py
+++ b/linesman/__init__.py
@@ -18,6 +18,7 @@
from inspect import getmodule
import networkx as nx
+import networkx.drawing.nx_agraph
log = logging.getLogger(__name__)
@@ -48,7 +49,7 @@ def draw_graph(graph, output_path):
``output_path``:
Location to store the rendered output.
"""
- nx.to_agraph(graph).draw(output_path, prog="dot")
+ networkx.drawing.nx_agraph.to_agraph(graph).draw(output_path, prog="dot")
log.info("Wrote output to `%s'" % output_path)
@@ -85,7 +86,7 @@ def create_graph(stats):
'reccallcount': stat.reccallcount,
'totaltime': stat.totaltime,
}
- g.add_node(caller_key, attr_dict=attrs)
+ g.add_node(caller_key, **attrs)
# Add all the calls as edges
for call in stat.calls or []:
@@ -102,7 +103,7 @@ def create_graph(stats):
g.add_edge(caller_key, callee_key,
weight=call.totaltime,
label=call.totaltime,
- attr_dict=call_attrs)
+ **call_attrs)
return g
diff --git a/linesman/backends/pickle.py b/linesman/backends/pickle.py
index 77038ab..8d73bc4 100644
--- a/linesman/backends/pickle.py
+++ b/linesman/backends/pickle.py
@@ -13,9 +13,9 @@
# You should have received a copy of the GNU General Public License along
# with linesman. If not, see .
#
-import cPickle
import logging
+from six.moves import cPickle
from linesman.backends.base import Backend
diff --git a/linesman/backends/sqlite.py b/linesman/backends/sqlite.py
index 8f996a1..7c028cd 100644
--- a/linesman/backends/sqlite.py
+++ b/linesman/backends/sqlite.py
@@ -13,11 +13,11 @@
# You should have received a copy of the GNU General Public License along
# with linesman. If not, see .
#
-import cPickle
import logging
import sqlite3
import time
+from six.moves import cPickle
from linesman.backends.base import Backend
diff --git a/linesman/middleware.py b/linesman/middleware.py
index 58bdbe7..16a2ac5 100644
--- a/linesman/middleware.py
+++ b/linesman/middleware.py
@@ -20,6 +20,7 @@
from tempfile import gettempdir
from PIL import Image
+from networkx.classes.reportviews import InDegreeView
import networkx as nx
from mako.lookup import TemplateLookup
from paste.urlparser import StaticURLParser
@@ -30,6 +31,13 @@
from linesman import ProfilingSession, draw_graph
+_pil_major = int(Image.__version__.split(".")[0])
+if _pil_major >= 10:
+ ANTIALIAS = Image.Resampling.LANCZOS
+else:
+ ANTIALIAS = Image.ANTIALIAS
+
+
log = logging.getLogger(__name__)
# Graphs
@@ -250,7 +258,7 @@ def render_graph(self, req):
log.debug("Creating thumbnail for %s at %s.", session_uuid,
thumbnail_path)
im = Image.open(path, 'r')
- im.thumbnail((600, 600), Image.ANTIALIAS)
+ im.thumbnail((600, 600), ANTIALIAS)
im.save(thumbnail_path)
return StaticURLParser(GRAPH_DIR)
@@ -438,13 +446,19 @@ def prepare_graph(source_graph, cutoff_time, break_cycles=False):
# Break cycles
if break_cycles:
for cycle in nx.simple_cycles(graph):
- u, v = cycle[0], cycle[1]
- if graph.has_edge(u, v):
- graph.remove_edge(u, v)
- cyclic_breaks.append((u, v))
+ end = len(cycle) - 1 if len(cycle) > 1 else 1
+ for i in range(end):
+ u = cycle[i]
+ if len(cycle) == 1:
+ v = u
+ else:
+ v = cycle[i + 1]
+ if graph.has_edge(u, v):
+ graph.remove_edge(u, v)
+ cyclic_breaks.append((u, v))
root_nodes = [node
- for node, degree in graph.in_degree_iter()
+ for node, degree in InDegreeView(graph)
if degree == 0]
return graph, root_nodes, cyclic_breaks
diff --git a/linesman/templates/tree.tmpl b/linesman/templates/tree.tmpl
index 22193d5..3848d73 100644
--- a/linesman/templates/tree.tmpl
+++ b/linesman/templates/tree.tmpl
@@ -1,6 +1,6 @@
<%def name="print_tree(node)">
<%
- node_obj = graph.node[node]
+ node_obj = graph._node[node]
total_time_percentage = round(node_obj.get('totaltime') / session.duration * 100, 2)
inline_time_percentage = round(node_obj.get('inlinetime') / session.duration * 100, 2)
open_or_leaf = 'open' if graph.neighbors(node) else 'leaf'
diff --git a/linesman/tests/test_graphs.py b/linesman/tests/test_graphs.py
index 4d93f0a..c8bb383 100644
--- a/linesman/tests/test_graphs.py
+++ b/linesman/tests/test_graphs.py
@@ -9,7 +9,7 @@
class TestGraphUtils(unittest.TestCase):
- @patch("networkx.to_agraph")
+ @patch("networkx.drawing.nx_agraph.to_agraph")
def test_draw_graph(self, mock_to_agraph):
""" Test that the graph gets converted to an agraph """
mock_draw = Mock()
diff --git a/setup.py b/setup.py
index 1b19344..b42d28c 100644
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@
import sys
-install_requires = ["mako", "networkx==1.7", "pillow", "pygraphviz", 'Paste', 'WebOb']
+install_requires = ["mako", "networkx>=2.0", "pillow", "pygraphviz", 'Paste', 'WebOb', 'six']
# ordereddict is required for versions < 2.7; its included in collections in
# versions 2.7+ and 3.0+