File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 11import glob
22import os
33import os .path as osp
4- import shlex
54import sys
65import re
76import copy
@@ -176,7 +175,10 @@ def clean_action():
176175
177176def get_cmd_line (args ):
178177 """Given a set or arguments, compute command-line."""
179- args = [shlex .quote (s ).replace ('\n ' , '\\ n' ) for s in args ]
178+ # Escape newlines so the CMDLINE record in the .dat file remains on a
179+ # single line and does not break read_mprofile_file() (#210).
180+ blanks = set (' \t \n ' )
181+ args = [s .replace ('\n ' , '\\ n' ) if blanks .isdisjoint (s ) else "'" + s .replace ('\n ' , '\\ n' ) + "'" for s in args ]
180182 return ' ' .join (args )
181183
182184def find_first_process (name ):
Original file line number Diff line number Diff line change @@ -101,6 +101,26 @@ class Options:
101101 finally :
102102 pl .close (fig )
103103
104+ def test_multiline_cmdline_arg_roundtrip (self ):
105+ # Verify that multiline CLI arguments passed to `mprof run` do not
106+ # write raw newlines into the CMDLINE header of the .dat file, which
107+ # previously caused read_mprofile_file() to crash with ValueError
108+ # on blank or single-token continuation lines (Issue #210 / PR #363).
109+ multiline_arg = "hello\n \n world"
110+ cmd_line = mprof .get_cmd_line (["python" , "script.py" , multiline_arg ])
111+ self .assertNotIn ("\n " , cmd_line )
112+
113+ content = (
114+ "CMDLINE %s\n "
115+ "MEM 10.0 100.0\n "
116+ ) % cmd_line
117+ with tempfile .NamedTemporaryFile ('w' , suffix = '.dat' ) as tmp_dat :
118+ tmp_dat .write (content )
119+ tmp_dat .flush ()
120+ parsed = mprof .read_mprofile_file (tmp_dat .name )
121+ self .assertEqual (parsed ["mem_usage" ], [10.0 ])
122+ self .assertIn ("hello\\ n\\ nworld" , parsed ["cmd_line" ])
123+
104124
105125if __name__ == "__main__" :
106126 unittest .main ()
You can’t perform that action at this time.
0 commit comments