Skip to content

Commit b798cc2

Browse files
authored
Merge pull request pytest-dev#99 from smarie/master
Fixed SVG file generation on windows (pytest-dev#93)
2 parents 9f267e0 + 47ed118 commit b798cc2

File tree

1 file changed

+43
-6
lines changed

1 file changed

+43
-6
lines changed

pytest-profiling/pytest_profiling.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
import os
77
import cProfile
88
import pstats
9-
import pipes
109
import errno
1110
from hashlib import md5
11+
from subprocess import Popen, PIPE
1212

1313
import six
1414
import pytest
@@ -28,6 +28,9 @@ class Profiling(object):
2828
svg_name = None
2929
profs = []
3030
combined = None
31+
svg_err = None
32+
dot_cmd = None
33+
gprof2dot_cmd = None
3134

3235
def __init__(self, svg, dir=None, element_number=20):
3336
self.svg = svg
@@ -54,17 +57,51 @@ def pytest_sessionfinish(self, session, exitstatus): # @UnusedVariable
5457
combined.dump_stats(self.combined)
5558
if self.svg:
5659
self.svg_name = os.path.abspath(os.path.join(self.dir, "combined.svg"))
57-
t = pipes.Template()
58-
t.append("{} -f pstats $IN".format(self.gprof2dot), "f-")
59-
t.append("dot -Tsvg -o $OUT", "-f")
60-
t.copy(self.combined, self.svg_name)
60+
61+
# convert file <self.combined> into file <self.svg_name> using a pipe of gprof2dot | dot
62+
# gprof2dot -f pstats prof/combined.prof | dot -Tsvg -o prof/combined.svg
63+
64+
# the 2 commands that we wish to execute
65+
gprof2dot_args = [self.gprof2dot, "-f", "pstats", self.combined]
66+
dot_args = ["dot", "-Tsvg", "-o", self.svg_name]
67+
self.dot_cmd = " ".join(dot_args)
68+
self.gprof2dot_cmd = " ".join(gprof2dot_args)
69+
70+
# A handcrafted Popen pipe actually seems to work on both windows and unix:
71+
# do it in 2 subprocesses, with a pipe in between
72+
pdot = Popen(dot_args, stdin=PIPE, shell=True)
73+
pgprof = Popen(gprof2dot_args, stdout=pdot.stdin, shell=True)
74+
(stdoutdata1, stderrdata1) = pgprof.communicate()
75+
(stdoutdata2, stderrdata2) = pdot.communicate()
76+
if stderrdata1 is not None or pgprof.poll() > 0:
77+
# error: gprof2dot
78+
self.svg_err = 1
79+
elif stderrdata2 is not None or pdot.poll() > 0:
80+
# error: dot
81+
self.svg_err = 2
82+
else:
83+
# success
84+
self.svg_err = 0
6185

6286
def pytest_terminal_summary(self, terminalreporter):
6387
if self.combined:
6488
terminalreporter.write("Profiling (from {prof}):\n".format(prof=self.combined))
6589
pstats.Stats(self.combined, stream=terminalreporter).strip_dirs().sort_stats('cumulative').print_stats(self.element_number)
6690
if self.svg_name:
67-
terminalreporter.write("SVG profile in {svg}.\n".format(svg=self.svg_name))
91+
if not self.svg_err:
92+
# 0 - SUCCESS
93+
terminalreporter.write("SVG profile created in {svg}.\n".format(svg=self.svg_name))
94+
else:
95+
if self.svg_err == 1:
96+
# 1 - GPROF2DOT ERROR
97+
terminalreporter.write("Error creating SVG profile in {svg}.\n"
98+
"Command failed: {cmd}".format(svg=self.svg_name, cmd=self.gprof2dot_cmd))
99+
elif self.svg_err == 2:
100+
# 2 - DOT ERROR
101+
terminalreporter.write("Error creating SVG profile in {svg}.\n"
102+
"Command succeeded: {cmd} \n"
103+
"Command failed: {cmd2}".format(svg=self.svg_name, cmd=self.gprof2dot_cmd,
104+
cmd2=self.dot_cmd))
68105

69106
@pytest.hookimpl(hookwrapper=True)
70107
def pytest_runtest_protocol(self, item, nextitem):

0 commit comments

Comments
 (0)