OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 # | 3 # |
4 # Use of this source code is governed by a BSD-style license | 4 # Use of this source code is governed by a BSD-style license |
5 # that can be found in the LICENSE file in the root of the source | 5 # that can be found in the LICENSE file in the root of the source |
6 # tree. An additional intellectual property rights grant can be found | 6 # tree. An additional intellectual property rights grant can be found |
7 # in the file PATENTS. All contributing project authors may | 7 # in the file PATENTS. All contributing project authors may |
8 # be found in the AUTHORS file in the root of the source tree. | 8 # be found in the AUTHORS file in the root of the source tree. |
9 | 9 |
10 import multiprocessing | 10 import multiprocessing |
11 import os | 11 import os |
12 import subprocess | 12 import subprocess |
13 import sys | 13 import sys |
14 | 14 |
15 _DEFAULT_PADDING = 4 | 15 _DEFAULT_PADDING = 4 |
16 | 16 |
17 | 17 |
18 class HelperError(Exception): | 18 class HelperError(Exception): |
19 """Exception raised for errors in the helper.""" | 19 """Exception raised for errors in the helper.""" |
20 pass | 20 pass |
21 | 21 |
22 | 22 |
23 def zero_pad(number, padding=_DEFAULT_PADDING): | 23 def ZeroPad(number, padding=_DEFAULT_PADDING): |
24 """Converts an int into a zero padded string. | 24 """Converts an int into a zero padded string. |
25 | 25 |
26 Args: | 26 Args: |
27 number(int): The number to convert. | 27 number(int): The number to convert. |
28 padding(int): The number of chars in the output. Note that if you pass for | 28 padding(int): The number of chars in the output. Note that if you pass for |
29 example number=23456 and padding=4, the output will still be '23456', | 29 example number=23456 and padding=4, the output will still be '23456', |
30 i.e. it will not be cropped. If you pass number=2 and padding=4, the | 30 i.e. it will not be cropped. If you pass number=2 and padding=4, the |
31 return value will be '0002'. | 31 return value will be '0002'. |
32 Return: | 32 Return: |
33 (string): The zero padded number converted to string. | 33 (string): The zero padded number converted to string. |
34 """ | 34 """ |
35 return str(number).zfill(padding) | 35 return str(number).zfill(padding) |
36 | 36 |
37 | 37 |
38 def run_shell_command(cmd_list, fail_msg=None): | 38 def RunShellCommand(cmd_list, fail_msg=None): |
39 """Executes a command. | 39 """Executes a command. |
40 | 40 |
41 Args: | 41 Args: |
42 cmd_list(list): Command list to execute. | 42 cmd_list(list): Command list to execute. |
43 fail_msg(string): Message describing the error in case the command fails. | 43 fail_msg(string): Message describing the error in case the command fails. |
44 | 44 |
45 Return: | 45 Return: |
46 (string): The standard output from running the command. | 46 (string): The standard output from running the command. |
47 | 47 |
48 Raise: | 48 Raise: |
49 HelperError: If command fails. | 49 HelperError: If command fails. |
50 """ | 50 """ |
51 process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, | 51 process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, |
52 stderr=subprocess.PIPE) | 52 stderr=subprocess.PIPE) |
53 output, error = process.communicate() | 53 output, error = process.communicate() |
54 if process.returncode != 0: | 54 if process.returncode != 0: |
55 if fail_msg: | 55 if fail_msg: |
56 print >> sys.stderr, fail_msg | 56 print >> sys.stderr, fail_msg |
57 raise HelperError('Failed to run %s: command returned %d and printed ' | 57 raise HelperError('Failed to run %s: command returned %d and printed ' |
58 '%s and %s' % (' '.join(cmd_list), process.returncode, | 58 '%s and %s' % (' '.join(cmd_list), process.returncode, |
59 output, error)) | 59 output, error)) |
60 return output.strip() | 60 return output.strip() |
61 | 61 |
62 | 62 |
63 def perform_action_on_all_files(directory, file_pattern, file_extension, | 63 def PerformActionOnAllFiles(directory, file_pattern, file_extension, |
64 start_number, action, **kwargs): | 64 start_number, action, **kwargs): |
65 """Function that performs a given action on all files matching a pattern. | 65 """Function that performs a given action on all files matching a pattern. |
66 | 66 |
67 It is assumed that the files are named file_patternxxxx.file_extension, where | 67 It is assumed that the files are named file_patternxxxx.file_extension, where |
68 xxxx are digits starting from start_number. | 68 xxxx are digits starting from start_number. |
69 | 69 |
70 Args: | 70 Args: |
71 directory(string): The directory where the files live. | 71 directory(string): The directory where the files live. |
72 file_pattern(string): The name pattern of the files. | 72 file_pattern(string): The name pattern of the files. |
73 file_extension(string): The files' extension. | 73 file_extension(string): The files' extension. |
74 start_number(int): From where to start to count frames. | 74 start_number(int): From where to start to count frames. |
75 action(function): The action to be performed over the files. Must return | 75 action(function): The action to be performed over the files. Must return |
76 False if the action failed, True otherwise. It should take a file name | 76 False if the action failed, True otherwise. It should take a file name |
77 as the first argument and **kwargs as arguments. The function must be | 77 as the first argument and **kwargs as arguments. The function must be |
78 possible to pickle, so it cannot be a bound function (for instance). | 78 possible to pickle, so it cannot be a bound function (for instance). |
79 | 79 |
80 Return: | 80 Return: |
81 (bool): Whether performing the action over all files was successful or not. | 81 (bool): Whether performing the action over all files was successful or not. |
82 """ | 82 """ |
83 file_prefix = os.path.join(directory, file_pattern) | 83 file_prefix = os.path.join(directory, file_pattern) |
84 file_number = start_number | 84 file_number = start_number |
85 | 85 |
86 process_pool = multiprocessing.Pool(processes=multiprocessing.cpu_count()) | 86 process_pool = multiprocessing.Pool(processes=multiprocessing.cpu_count()) |
87 results = [] | 87 results = [] |
88 while True: | 88 while True: |
89 zero_padded_file_number = zero_pad(file_number) | 89 zero_padded_file_number = ZeroPad(file_number) |
90 file_name = file_prefix + zero_padded_file_number + '.' + file_extension | 90 file_name = file_prefix + zero_padded_file_number + '.' + file_extension |
91 if not os.path.isfile(file_name): | 91 if not os.path.isfile(file_name): |
92 break | 92 break |
93 future = process_pool.apply_async(action, args=(file_name,), kwds=kwargs) | 93 future = process_pool.apply_async(action, args=(file_name,), kwds=kwargs) |
94 results.append(future) | 94 results.append(future) |
95 file_number += 1 | 95 file_number += 1 |
96 | 96 |
97 successful = True | 97 successful = True |
98 for result in results: | 98 for result in results: |
99 if not result.get(): | 99 if not result.get(): |
100 print "At least one action %s failed for files %sxxxx.%s." % ( | 100 print "At least one action %s failed for files %sxxxx.%s." % ( |
101 action, file_pattern, file_extension) | 101 action, file_pattern, file_extension) |
102 successful = False | 102 successful = False |
103 | 103 |
104 process_pool.close() | 104 process_pool.close() |
105 return successful | 105 return successful |
OLD | NEW |