1- use clap:: builder:: { styling:: AnsiColor , PossibleValue , PossibleValuesParser , Styles } ;
1+ use clap:: builder:: { styling:: AnsiColor , EnumValueParser , Styles } ;
22use clap:: {
33 crate_description, crate_name, crate_version, value_parser, Arg , ArgAction , Command , ValueEnum ,
44} ;
@@ -70,14 +70,6 @@ pub enum FileFormat {
7070 chrometrace,
7171}
7272
73- impl FileFormat {
74- pub fn possible_values ( ) -> impl Iterator < Item = PossibleValue > {
75- FileFormat :: value_variants ( )
76- . iter ( )
77- . filter_map ( ValueEnum :: to_possible_value)
78- }
79- }
80-
8173impl std:: str:: FromStr for FileFormat {
8274 type Err = String ;
8375
@@ -163,7 +155,8 @@ impl Config {
163155 let mut native = Arg :: new ( "native" )
164156 . short ( 'n' )
165157 . long ( "native" )
166- . help ( "Collect stack traces from native extensions written in Cython, C or C++" ) ;
158+ . help ( "Collect stack traces from native extensions written in Cython, C or C++" )
159+ . action ( ArgAction :: SetTrue ) ;
167160
168161 // Only show `--native` on platforms where it's supported
169162 if !cfg ! ( feature = "unwind" ) {
@@ -174,37 +167,43 @@ impl Config {
174167 let nonblocking = Arg :: new ( "nonblocking" )
175168 . long ( "nonblocking" )
176169 . help ( "Don't pause the python process when collecting samples. Setting this option will reduce \
177- the performance impact of sampling, but may lead to inaccurate results") ;
170+ the performance impact of sampling, but may lead to inaccurate results")
171+ . action ( ArgAction :: SetTrue ) ;
178172
179173 let rate = Arg :: new ( "rate" )
180174 . short ( 'r' )
181175 . long ( "rate" )
182176 . value_name ( "rate" )
183177 . help ( "The number of samples to collect per second" )
184178 . default_value ( "100" )
179+ . value_parser ( value_parser ! ( u64 ) )
185180 . action ( ArgAction :: Set ) ;
186181
187182 let subprocesses = Arg :: new ( "subprocesses" )
188183 . short ( 's' )
189184 . long ( "subprocesses" )
190- . help ( "Profile subprocesses of the original process" ) ;
185+ . help ( "Profile subprocesses of the original process" )
186+ . action ( ArgAction :: SetTrue ) ;
191187
192- let full_filenames = Arg :: new ( "full_filenames" ) . long ( "full-filenames" ) . help (
193- "Show full Python filenames, instead of shortening to show only the package part" ,
194- ) ;
188+ let full_filenames = Arg :: new ( "full_filenames" )
189+ . long ( "full-filenames" )
190+ . help ( "Show full Python filenames, instead of shortening to show only the package part" )
191+ . action ( ArgAction :: SetTrue ) ;
195192 let program = Arg :: new ( "python_program" )
196193 . help ( "commandline of a python program to run" )
197194 . action ( ArgAction :: Append ) ;
198195
199196 let idle = Arg :: new ( "idle" )
200197 . short ( 'i' )
201198 . long ( "idle" )
202- . help ( "Include stack traces for idle threads" ) ;
199+ . help ( "Include stack traces for idle threads" )
200+ . action ( ArgAction :: SetTrue ) ;
203201
204202 let gil = Arg :: new ( "gil" )
205203 . short ( 'g' )
206204 . long ( "gil" )
207- . help ( "Only include traces that are holding on to the GIL" ) ;
205+ . help ( "Only include traces that are holding on to the GIL" )
206+ . action ( ArgAction :: SetTrue ) ;
208207
209208 let top_delay = Arg :: new ( "delay" )
210209 . long ( "delay" )
@@ -235,7 +234,7 @@ impl Config {
235234 . value_name ( "format" )
236235 . help ( "Output file format" )
237236 . action ( ArgAction :: Set )
238- . value_parser ( PossibleValuesParser :: new ( FileFormat :: possible_values ( ) ) )
237+ . value_parser ( EnumValueParser :: < FileFormat > :: new ( ) )
239238 . ignore_case ( true )
240239 . default_value ( "flamegraph" ) ,
241240 )
@@ -252,31 +251,35 @@ impl Config {
252251 . arg ( subprocesses. clone ( ) )
253252 . arg ( Arg :: new ( "function" ) . short ( 'F' ) . long ( "function" ) . help (
254253 "Aggregate samples by function's first line number, instead of current line number" ,
255- ) )
254+ ) . action ( ArgAction :: SetTrue ) )
256255 . arg (
257256 Arg :: new ( "nolineno" )
258257 . long ( "nolineno" )
259- . help ( "Do not show line numbers" ) ,
258+ . help ( "Do not show line numbers" )
259+ . action ( ArgAction :: SetTrue ) ,
260260 )
261261 . arg (
262262 Arg :: new ( "threads" )
263263 . short ( 't' )
264264 . long ( "threads" )
265- . help ( "Show thread ids in the output" ) ,
265+ . help ( "Show thread ids in the output" )
266+ . action ( ArgAction :: SetTrue ) ,
266267 )
267268 . arg ( gil. clone ( ) )
268269 . arg ( idle. clone ( ) )
269270 . arg (
270271 Arg :: new ( "capture" )
271272 . long ( "capture" )
272273 . hide ( true )
273- . help ( "Captures output from child process" ) ,
274+ . help ( "Captures output from child process" )
275+ . action ( ArgAction :: SetTrue ) ,
274276 )
275277 . arg (
276278 Arg :: new ( "hideprogress" )
277279 . long ( "hideprogress" )
278280 . hide ( true )
279- . help ( "Hides progress bar (useful for showing error output on record)" ) ,
281+ . help ( "Hides progress bar (useful for showing error output on record)" )
282+ . action ( ArgAction :: SetTrue ) ,
280283 ) ;
281284
282285 let top = Command :: new ( "top" )
@@ -319,7 +322,8 @@ impl Config {
319322 . arg ( Arg :: new ( "json" )
320323 . short ( 'j' )
321324 . long ( "json" )
322- . help ( "Format output as JSON" ) )
325+ . help ( "Format output as JSON" )
326+ . action ( ArgAction :: SetTrue ) )
323327 . arg ( subprocesses. clone ( ) ) ;
324328
325329 let completions = Command :: new ( "completions" )
@@ -368,7 +372,7 @@ impl Config {
368372 let ( subcommand, matches) = matches. subcommand ( ) . unwrap ( ) ;
369373
370374 // Check if `--native` was used on an unsupported platform
371- if !cfg ! ( feature = "unwind" ) && matches. contains_id ( "native" ) {
375+ if !cfg ! ( feature = "unwind" ) && matches. get_flag ( "native" ) {
372376 eprintln ! (
373377 "Collecting stack traces from native extensions (`--native`) is not supported on your platform."
374378 ) ;
@@ -386,27 +390,27 @@ impl Config {
386390 } ;
387391 config. format = matches. get_one ( "format" ) . copied ( ) ;
388392 config. filename = matches. get_one :: < String > ( "output" ) . cloned ( ) ;
389- config. show_line_numbers = !matches. contains_id ( "nolineno" ) ;
390- config. lineno = if matches. contains_id ( "nolineno" ) {
393+ config. show_line_numbers = !matches. get_flag ( "nolineno" ) ;
394+ config. lineno = if matches. get_flag ( "nolineno" ) {
391395 LineNo :: NoLine
392- } else if matches. contains_id ( "function" ) {
396+ } else if matches. get_flag ( "function" ) {
393397 LineNo :: First
394398 } else {
395399 LineNo :: LastInstruction
396400 } ;
397- config. include_thread_ids = matches. contains_id ( "threads" ) ;
398- if matches. contains_id ( "nolineno" ) && matches. contains_id ( "function" ) {
401+ config. include_thread_ids = matches. get_flag ( "threads" ) ;
402+ if matches. get_flag ( "nolineno" ) && matches. get_flag ( "function" ) {
399403 eprintln ! ( "--function & --nolinenos can't be used together" ) ;
400404 std:: process:: exit ( 1 ) ;
401405 }
402- config. hide_progress = matches. contains_id ( "hideprogress" ) ;
406+ config. hide_progress = matches. get_flag ( "hideprogress" ) ;
403407 }
404408 "top" => {
405409 config. sampling_rate = * matches. get_one ( "rate" ) . unwrap ( ) ;
406410 config. refresh_seconds = * matches. get_one :: < f64 > ( "delay" ) . unwrap ( ) ;
407411 }
408412 "dump" => {
409- config. dump_json = matches. contains_id ( "json" ) ;
413+ config. dump_json = matches. get_flag ( "json" ) ;
410414 config. dump_locals = matches. get_count ( "locals" ) . into ( ) ;
411415
412416 #[ cfg( target_os = "linux" ) ]
@@ -428,13 +432,13 @@ impl Config {
428432 config. python_program = matches
429433 . get_many :: < String > ( "python_program" )
430434 . map ( |vals| vals. map ( |v| v. to_owned ( ) ) . collect ( ) ) ;
431- config. gil_only = matches. contains_id ( "gil" ) ;
432- config. include_idle = matches. contains_id ( "idle" ) ;
435+ config. gil_only = matches. get_flag ( "gil" ) ;
436+ config. include_idle = matches. get_flag ( "idle" ) ;
433437 }
434438 _ => { }
435439 }
436440
437- config. subprocesses = matches. contains_id ( "subprocesses" ) ;
441+ config. subprocesses = matches. get_flag ( "subprocesses" ) ;
438442 config. command = subcommand. to_owned ( ) ;
439443
440444 // options that can be shared between subcommands
@@ -446,17 +450,17 @@ impl Config {
446450 }
447451 } ) ;
448452
449- config. full_filenames = matches. contains_id ( "full_filenames" ) ;
453+ config. full_filenames = matches. get_flag ( "full_filenames" ) ;
450454 if cfg ! ( feature = "unwind" ) {
451- config. native = matches. contains_id ( "native" ) ;
455+ config. native = matches. get_flag ( "native" ) ;
452456 }
453457
454- config. capture_output = config. command != "record" || matches. contains_id ( "capture" ) ;
458+ config. capture_output = config. command != "record" || matches. get_flag ( "capture" ) ;
455459 if !config. capture_output {
456460 config. hide_progress = true ;
457461 }
458462
459- if matches. contains_id ( "nonblocking" ) {
463+ if matches. get_flag ( "nonblocking" ) {
460464 // disable native profiling if invalidly asked for
461465 if config. native {
462466 eprintln ! ( "Can't get native stack traces with the --nonblocking option." ) ;
@@ -521,8 +525,8 @@ mod tests {
521525
522526 // missing the --pid argument should fail
523527 assert_eq ! (
524- get_config( "py-spy record -o foo" ) . unwrap_err( ) . kind,
525- clap:: ErrorKind :: MissingRequiredArgument
528+ get_config( "py-spy record -o foo" ) . unwrap_err( ) . kind( ) ,
529+ clap:: error :: ErrorKind :: MissingRequiredArgument
526530 ) ;
527531
528532 // but should work when passed a python program
@@ -537,8 +541,8 @@ mod tests {
537541 assert_eq ! (
538542 get_config( "py-spy r -p 1234 -o foo -f unknown" )
539543 . unwrap_err( )
540- . kind,
541- clap:: ErrorKind :: InvalidValue
544+ . kind( ) ,
545+ clap:: error :: ErrorKind :: InvalidValue
542546 ) ;
543547
544548 // test out overriding these params by setting flags
@@ -565,8 +569,8 @@ mod tests {
565569
566570 // missing the --pid argument should fail
567571 assert_eq ! (
568- get_config( "py-spy dump" ) . unwrap_err( ) . kind,
569- clap:: ErrorKind :: MissingRequiredArgument
572+ get_config( "py-spy dump" ) . unwrap_err( ) . kind( ) ,
573+ clap:: error :: ErrorKind :: MissingRequiredArgument
570574 ) ;
571575 }
572576
@@ -585,8 +589,8 @@ mod tests {
585589 #[ test]
586590 fn test_parse_args ( ) {
587591 assert_eq ! (
588- get_config( "py-spy dude" ) . unwrap_err( ) . kind,
589- clap:: ErrorKind :: UnrecognizedSubcommand
592+ get_config( "py-spy dude" ) . unwrap_err( ) . kind( ) ,
593+ clap:: error :: ErrorKind :: InvalidSubcommand
590594 ) ;
591595 }
592596}
0 commit comments