262 |
262 |
263 def applyActionToFiles(action, action_args, |
263 def applyActionToFiles(action, action_args, |
264 start_path='', abs_path=False, files_pattern='', |
264 start_path='', abs_path=False, files_pattern='', |
265 recurse_dirs=False, dirs_pattern='', |
265 recurse_dirs=False, dirs_pattern='', |
266 follow_symlinks=False, quiet_output=False, |
266 follow_symlinks=False, quiet_output=False, |
267 hide_paths=False, **action_options): |
267 hide_paths=False, hide_text=False, **action_options): |
268 """Applies a callable action to files, based on options and arguments. |
268 """Applies a callable action to files, based on options and arguments. |
269 |
269 |
270 Args: |
270 Args: |
271 action: callable that expects a file path argument, positional arguments |
271 action: callable that expects a file path argument, positional arguments |
272 (action_args), and keyword options from the command-line options dict; |
272 (action_args), and keyword options from the command-line options dict; |
281 dirs_pattern: Python regex (object or pattern) which selects which |
281 dirs_pattern: Python regex (object or pattern) which selects which |
282 subdirectories to traverse if recurse_dirs is True |
282 subdirectories to traverse if recurse_dirs is True |
283 follow_symlinks: boolean indicating if symlinks should be traversed |
283 follow_symlinks: boolean indicating if symlinks should be traversed |
284 quiet_output: optional boolean indicating if output should be suppressed |
284 quiet_output: optional boolean indicating if output should be suppressed |
285 hide_paths: optional boolean indicating to omit file paths from output |
285 hide_paths: optional boolean indicating to omit file paths from output |
|
286 hide_text: optional boolean indicating to omit find/replace text from |
|
287 output |
286 **action_options: remaining keyword arguments that are passed unchanged |
288 **action_options: remaining keyword arguments that are passed unchanged |
287 to the action callable |
289 to the action callable |
288 |
290 |
289 Returns: |
291 Returns: |
290 two-tuple containing an exit code and a (possibly empty) list of |
292 two-tuple containing an exit code and a (possibly empty) list of |
332 if recurse_dirs: |
334 if recurse_dirs: |
333 if dirs_regex.match(item): |
335 if dirs_regex.match(item): |
334 sub_paths.append(item_path) |
336 sub_paths.append(item_path) |
335 continue |
337 continue |
336 |
338 |
337 if files_regex.match(item): |
339 if os.path.isfile(item_path) and files_regex.match(item): |
338 try: |
340 try: |
339 matched, found_output = action(item_path, *action_args, |
341 matched, found_output = action(item_path, *action_args, |
340 **action_options) |
342 **action_options) |
341 except (IOError, OSError), error: |
343 except (IOError, OSError), error: |
342 raise Error(error.args[0], '%s: %s' % ( |
344 raise Error(error.args[0], '%s: %s' % ( |
346 exit_code = 0 # at least one matched file has now been found |
348 exit_code = 0 # at least one matched file has now been found |
347 |
349 |
348 if (not quiet_output) and (not hide_paths): |
350 if (not quiet_output) and (not hide_paths): |
349 output.append(item_path) |
351 output.append(item_path) |
350 |
352 |
351 if not quiet_output: |
353 if (not quiet_output) and (not hide_text): |
352 output.extend(found_output) |
354 output.extend(found_output) |
353 |
355 |
354 paths = sub_paths |
356 paths = sub_paths |
355 |
357 |
356 return exit_code, output |
358 return exit_code, output |
418 '-a', '--abspath', dest='abs_path', default=False, action='store_true', |
420 '-a', '--abspath', dest='abs_path', default=False, action='store_true', |
419 help=('output absolute paths instead of relative paths' |
421 help=('output absolute paths instead of relative paths' |
420 ' [default: %default]')) |
422 ' [default: %default]')) |
421 |
423 |
422 output_group.add_option( |
424 output_group.add_option( |
423 '-p', '--nopaths', dest='hide_paths', default=False, action='store_true', |
425 '', '--nopaths', dest='hide_paths', default=False, action='store_true', |
424 help=('suppress printing of file path names for successfully matched' |
426 help=('suppress printing of file path names for successfully matched' |
425 ' files to stdout [default: %default]')) |
427 ' files to stdout [default: %default]')) |
|
428 |
|
429 output_group.add_option( |
|
430 '', '--notext', dest='hide_text', default=False, action='store_true', |
|
431 help=('suppress find/replace text output to stdout (but still print' |
|
432 ' paths if not --nopath, and still perform replacements if' |
|
433 ' specified) [default: %default]')) |
426 |
434 |
427 output_group.add_option( |
435 output_group.add_option( |
428 '-q', '--quiet', dest='quiet_output', default=False, action='store_true', |
436 '-q', '--quiet', dest='quiet_output', default=False, action='store_true', |
429 help=('suppress *all* printed output to stdout (but still perform' |
437 help=('suppress *all* printed output to stdout (but still perform' |
430 ' replacements if specified) [default: %default]')) |
438 ' replacements if specified) [default: %default]')) |
509 |
517 |
510 Returns: |
518 Returns: |
511 exit code suitable for sys.exit() |
519 exit code suitable for sys.exit() |
512 """ |
520 """ |
513 options = {} # empty options, used if _parseArgs() fails |
521 options = {} # empty options, used if _parseArgs() fails |
|
522 parser = None |
514 |
523 |
515 try: |
524 try: |
516 action, options, args, parser = _parseArgs(argv[1:]) |
525 action, options, args, parser = _parseArgs(argv[1:]) |
517 exit_code, output = applyActionToFiles(action, args, **options) |
526 exit_code, output = applyActionToFiles(action, args, **options) |
518 |
527 |
520 |
529 |
521 except Error, error: |
530 except Error, error: |
522 if not options.get('quiet_output'): |
531 if not options.get('quiet_output'): |
523 print >>sys.stderr, '\nERROR: (%s: %s) %s\n' % ( |
532 print >>sys.stderr, '\nERROR: (%s: %s) %s\n' % ( |
524 error.args[0], os.strerror(error.args[0]), error.args[1]) |
533 error.args[0], os.strerror(error.args[0]), error.args[1]) |
525 print >>sys.stderr, parser.get_usage() |
534 |
|
535 if parser: |
|
536 print >>sys.stderr, parser.get_usage() |
526 |
537 |
527 exit_code = error.args[0] |
538 exit_code = error.args[0] |
528 |
539 |
529 return exit_code |
540 return exit_code |
530 |
541 |