Index: native_client_sdk/src/tools/oshelpers.py |
diff --git a/native_client_sdk/src/tools/oshelpers.py b/native_client_sdk/src/tools/oshelpers.py |
index aa67cff1365f819de6667be79417d63cd39a2049..ff9bd091a053444bcc5bd84cff97debdd8faa1b6 100755 |
--- a/native_client_sdk/src/tools/oshelpers.py |
+++ b/native_client_sdk/src/tools/oshelpers.py |
@@ -3,9 +3,13 @@ |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
+"""Utility script for emulating common unix commands.""" |
+ |
+from __future__ import print_function |
+ |
import fnmatch |
import glob |
-import optparse |
+import argparse |
import os |
import posixpath |
import shutil |
@@ -23,7 +27,8 @@ def IncludeFiles(filters, files): |
"""Filter files based on inclusion lists |
Return a list of files which match and of the Unix shell-style wildcards |
- provided, or return all the files if no filter is provided.""" |
+ provided, or return all the files if no filter is provided. |
+ """ |
if not filters: |
return files |
match = set() |
@@ -36,7 +41,8 @@ def ExcludeFiles(filters, files): |
"""Filter files based on exclusions lists |
Return a list of files which do not match any of the Unix shell-style |
- wildcards provided, or return all the files if no filter is provided.""" |
+ wildcards provided, or return all the files if no filter is provided. |
+ """ |
if not filters: |
return files |
match = set() |
@@ -52,7 +58,8 @@ def CopyPath(options, src, dst): |
Copy a fully specified src to a fully specified dst. If src and dst are |
both files, the dst file is removed first to prevent error. If and include |
or exclude list are provided, the destination is first matched against that |
- filter.""" |
+ filter. |
+ """ |
if options.includes: |
if not IncludeFiles(options.includes, [src]): |
return |
@@ -62,7 +69,7 @@ def CopyPath(options, src, dst): |
return |
if options.verbose: |
- print 'cp %s %s' % (src, dst) |
+ print('cp %s %s' % (src, dst)) |
# If the source is a single file, copy it individually |
if os.path.isfile(src): |
@@ -82,7 +89,7 @@ def CopyPath(options, src, dst): |
# Otherwise it's a directory, ignore it unless allowed |
if os.path.isdir(src): |
if not options.recursive: |
- print "cp: omitting directory '%s'" % src |
+ print("cp: omitting directory '%s'" % src) |
return |
# We can not copy over a file with a directory. |
@@ -107,31 +114,31 @@ def Copy(args): |
Copies multiple sources to a single destination using the normal cp |
semantics. In addition, it support inclusion and exclusion filters which |
- allows the copy to skip certain types of files.""" |
- parser = optparse.OptionParser(usage='usage: cp [Options] sources... dest') |
- parser.add_option( |
+ allows the copy to skip certain types of files. |
+ """ |
+ parser = argparse.ArgumentParser(usage='cp [Options] sources... dest', |
+ description=Copy.__doc__) |
+ parser.add_argument( |
'-R', '-r', '--recursive', dest='recursive', action='store_true', |
default=False, |
help='copy directories recursively.') |
- parser.add_option( |
+ parser.add_argument( |
'-v', '--verbose', dest='verbose', action='store_true', |
default=False, |
help='verbose output.') |
- parser.add_option( |
+ parser.add_argument( |
'--include', dest='includes', action='append', default=[], |
help='include files matching this expression.') |
- parser.add_option( |
+ parser.add_argument( |
'--exclude', dest='excludes', action='append', default=[], |
help='exclude files matching this expression.') |
- options, files = parser.parse_args(args) |
- if len(files) < 2: |
- parser.error('ERROR: expecting SOURCE(s) and DEST.') |
+ parser.add_argument('srcs', nargs='+', help='files to copy') |
+ parser.add_argument('dest', help='destination') |
- srcs = files[:-1] |
- dst = files[-1] |
+ options = parser.parse_args(args) |
src_list = [] |
- for src in srcs: |
+ for src in options.srcs: |
files = glob.glob(src) |
if not files: |
raise OSError('cp: no such file or directory: ' + src) |
@@ -141,31 +148,31 @@ def Copy(args): |
for src in src_list: |
# If the destination is a directory, then append the basename of the src |
# to the destination. |
- if os.path.isdir(dst): |
- CopyPath(options, src, os.path.join(dst, os.path.basename(src))) |
+ if os.path.isdir(options.dest): |
+ CopyPath(options, src, os.path.join(options.dest, os.path.basename(src))) |
else: |
- CopyPath(options, src, dst) |
+ CopyPath(options, src, options.dest) |
def Mkdir(args): |
- """A Unix style mkdir""" |
- parser = optparse.OptionParser(usage='usage: mkdir [Options] DIRECTORY...') |
- parser.add_option( |
+ """A Unix style mkdir.""" |
+ parser = argparse.ArgumentParser(usage='mkdir [Options] DIRECTORY...', |
+ description=Mkdir.__doc__) |
+ parser.add_argument( |
'-p', '--parents', dest='parents', action='store_true', |
default=False, |
help='ignore existing parents, create parents as needed.') |
- parser.add_option( |
+ parser.add_argument( |
'-v', '--verbose', dest='verbose', action='store_true', |
default=False, |
help='verbose output.') |
+ parser.add_argument('dirs', nargs='+', help='directory(s) to create') |
- options, dsts = parser.parse_args(args) |
- if len(dsts) < 1: |
- parser.error('ERROR: expecting DIRECTORY...') |
+ options = parser.parse_args(args) |
- for dst in dsts: |
+ for dst in options.dirs: |
if options.verbose: |
- print 'mkdir ' + dst |
+ print('mkdir %s' % dst) |
try: |
os.makedirs(dst) |
except OSError: |
@@ -179,12 +186,13 @@ def Mkdir(args): |
def MovePath(options, src, dst): |
- """MovePath from src to dst |
+ """MovePath from src to dst. |
Moves the src to the dst much like the Unix style mv command, except it |
only handles one source at a time. Because of possible temporary failures |
do to locks (such as anti-virus software on Windows), the function will retry |
- up to five times.""" |
+ up to five times. |
+ """ |
# if the destination is not an existing directory, then overwrite it |
if os.path.isdir(dst): |
dst = os.path.join(dst, os.path.basename(src)) |
@@ -200,36 +208,38 @@ def MovePath(options, src, dst): |
for _ in range(5): |
try: |
os.rename(src, dst) |
- return |
+ break |
except OSError as error: |
- print 'Failed on %s with %s, retrying' % (src, error) |
+ print('Failed on %s with %s, retrying' % (src, error)) |
time.sleep(5) |
- print 'Gave up.' |
- raise OSError('mv: ' + error) |
+ else: |
+ print('Gave up.') |
+ raise OSError('mv: ' + error) |
def Move(args): |
- parser = optparse.OptionParser(usage='usage: mv [Options] sources... dest') |
- parser.add_option( |
+ """A Unix style mv.""" |
+ |
+ parser = argparse.ArgumentParser(usage='mv [Options] sources... dest', |
+ description=Move.__doc__) |
+ parser.add_argument( |
'-v', '--verbose', dest='verbose', action='store_true', |
default=False, |
help='verbose output.') |
- parser.add_option( |
+ parser.add_argument( |
'-f', '--force', dest='force', action='store_true', |
default=False, |
help='force, do not error it files already exist.') |
- options, files = parser.parse_args(args) |
- if len(files) < 2: |
- parser.error('ERROR: expecting SOURCE... and DEST.') |
+ parser.add_argument('srcs', nargs='+') |
+ parser.add_argument('dest') |
- srcs = files[:-1] |
- dst = files[-1] |
+ options = parser.parse_args(args) |
if options.verbose: |
- print 'mv %s %s' % (' '.join(srcs), dst) |
+ print('mv %s %s' % (' '.join(options.srcs), options.dest)) |
- for src in srcs: |
- MovePath(options, src, dst) |
+ for src in options.srcs: |
+ MovePath(options, src, options.dest) |
return 0 |
@@ -238,26 +248,27 @@ def Remove(args): |
Removes the list of paths. Because of possible temporary failures do to locks |
(such as anti-virus software on Windows), the function will retry up to five |
- times.""" |
- parser = optparse.OptionParser(usage='usage: rm [Options] PATHS...') |
- parser.add_option( |
+ times. |
+ """ |
+ parser = argparse.ArgumentParser(usage='rm [Options] PATHS...', |
+ description=Remove.__doc__) |
+ parser.add_argument( |
'-R', '-r', '--recursive', dest='recursive', action='store_true', |
default=False, |
help='remove directories recursively.') |
- parser.add_option( |
+ parser.add_argument( |
'-v', '--verbose', dest='verbose', action='store_true', |
default=False, |
help='verbose output.') |
- parser.add_option( |
+ parser.add_argument( |
'-f', '--force', dest='force', action='store_true', |
default=False, |
help='force, do not error it files does not exist.') |
- options, files = parser.parse_args(args) |
- if len(files) < 1: |
- parser.error('ERROR: expecting FILE...') |
+ parser.add_argument('files', nargs='+') |
+ options = parser.parse_args(args) |
try: |
- for pattern in files: |
+ for pattern in options.files: |
dst_files = glob.glob(pattern) |
if not dst_files: |
# Ignore non existing files when using force |
@@ -267,10 +278,10 @@ def Remove(args): |
for dst in dst_files: |
if options.verbose: |
- print 'rm ' + dst |
+ print('rm ' + dst) |
if os.path.isfile(dst) or os.path.islink(dst): |
- for i in range(5): |
+ for _ in range(5): |
try: |
# Check every time, since it may have been deleted after the |
# previous failed attempt. |
@@ -278,27 +289,28 @@ def Remove(args): |
os.remove(dst) |
break |
except OSError as error: |
- if i == 5: |
- print 'Gave up.' |
- raise OSError('rm: ' + str(error)) |
- print 'Failed remove with %s, retrying' % error |
+ print('Failed remove with %s, retrying' % error) |
time.sleep(5) |
+ else: |
+ print('Gave up.') |
+ raise OSError('rm: ' + str(error)) |
if options.recursive: |
- for i in range(5): |
+ for _ in range(5): |
try: |
if os.path.isdir(dst): |
shutil.rmtree(dst) |
break |
except OSError as error: |
- if i == 5: |
- print 'Gave up.' |
- raise OSError('rm: ' + str(error)) |
- print 'Failed rmtree with %s, retrying' % error |
+ print('Failed rmtree with %s, retrying' % error) |
time.sleep(5) |
+ else: |
+ print('Gave up.') |
+ raise OSError('rm: ' + str(error)) |
except OSError as error: |
- print error |
+ print(error) |
+ |
return 0 |
@@ -342,29 +354,27 @@ def OSMakeZipPath(os_path): |
def Zip(args): |
"""A Unix style zip. |
- Compresses the listed files.""" |
- parser = optparse.OptionParser(usage='usage: zip [Options] zipfile list') |
- parser.add_option( |
+ Compresses the listed files. |
+ """ |
+ parser = argparse.ArgumentParser(description=Zip.__doc__) |
+ parser.add_argument( |
'-r', dest='recursive', action='store_true', |
default=False, |
help='recurse into directories') |
- parser.add_option( |
+ parser.add_argument( |
'-q', dest='quiet', action='store_true', |
default=False, |
help='quiet operation') |
- options, files = parser.parse_args(args) |
- if len(files) < 2: |
- parser.error('ERROR: expecting ZIPFILE and LIST.') |
- |
- dest_zip = files[0] |
- src_args = files[1:] |
+ parser.add_argument('zipfile') |
+ parser.add_argument('filenames', nargs='+') |
+ options = parser.parse_args(args) |
src_files = [] |
- for src_arg in src_args: |
- globbed_src_args = glob.glob(src_arg) |
+ for filename in options.filenames: |
+ globbed_src_args = glob.glob(filename) |
if not globbed_src_args: |
if not options.quiet: |
- print 'zip warning: name not matched: %s' % (src_arg,) |
+ print('zip warning: name not matched: %s' % filename) |
for src_file in globbed_src_args: |
src_file = os.path.normpath(src_file) |
@@ -376,7 +386,6 @@ def Zip(args): |
for filename in files: |
src_files.append(os.path.join(root, filename)) |
- zip_stream = None |
# zip_data represents a list of the data to be written or appended to the |
# zip_stream. It is a list of tuples: |
# (OS file path, zip path/zip file info, and file data) |
@@ -389,39 +398,37 @@ def Zip(args): |
zip_path_to_os_path_dict = dict((new_files_to_add[i], src_files[i]) |
for i in range(len(src_files))) |
write_mode = 'a' |
- try: |
- zip_stream = zipfile.ZipFile(dest_zip, 'r') |
- files_to_update = set(new_files_to_add).intersection( |
- set(zip_stream.namelist())) |
- if files_to_update: |
- # As far as I can tell, there is no way to update a zip entry using |
- # zipfile; the best you can do is rewrite the archive. |
- # Iterate through the zipfile to maintain file order. |
- write_mode = 'w' |
- for zip_path in zip_stream.namelist(): |
- if zip_path in files_to_update: |
- os_path = zip_path_to_os_path_dict[zip_path] |
- zip_data.append((os_path, zip_path, None)) |
- new_files_to_add.remove(zip_path) |
- else: |
- file_bytes = zip_stream.read(zip_path) |
- file_info = zip_stream.getinfo(zip_path) |
- zip_data.append((None, file_info, file_bytes)) |
- except IOError: |
- pass |
- finally: |
- if zip_stream: |
- zip_stream.close() |
+ if os.path.exists(options.zipfile): |
+ with zipfile.ZipFile(options.zipfile, 'r') as zip_stream: |
+ try: |
+ files_to_update = set(new_files_to_add).intersection( |
+ set(zip_stream.namelist())) |
+ if files_to_update: |
+ # As far as I can tell, there is no way to update a zip entry using |
+ # zipfile; the best you can do is rewrite the archive. |
+ # Iterate through the zipfile to maintain file order. |
+ write_mode = 'w' |
+ for zip_path in zip_stream.namelist(): |
+ if zip_path in files_to_update: |
+ os_path = zip_path_to_os_path_dict[zip_path] |
+ zip_data.append((os_path, zip_path, None)) |
+ new_files_to_add.remove(zip_path) |
+ else: |
+ file_bytes = zip_stream.read(zip_path) |
+ file_info = zip_stream.getinfo(zip_path) |
+ zip_data.append((None, file_info, file_bytes)) |
+ except IOError: |
+ pass |
for zip_path in new_files_to_add: |
zip_data.append((zip_path_to_os_path_dict[zip_path], zip_path, None)) |
if not zip_data: |
- print 'zip error: Nothing to do! (%s)' % (dest_zip,) |
+ print('zip error: Nothing to do! (%s)' % options.zipfile) |
return 1 |
- try: |
- zip_stream = zipfile.ZipFile(dest_zip, write_mode, zipfile.ZIP_DEFLATED) |
+ with zipfile.ZipFile(options.zipfile, write_mode, |
+ zipfile.ZIP_DEFLATED) as zip_stream: |
for os_path, file_info_or_zip_path, file_bytes in zip_data: |
if isinstance(file_info_or_zip_path, zipfile.ZipInfo): |
zip_path = file_info_or_zip_path.filename |
@@ -458,12 +465,10 @@ def Zip(args): |
zip_info = zip_stream.getinfo(zip_path) |
if (zip_info.compress_type == zipfile.ZIP_STORED or |
zip_info.file_size == 0): |
- print ' %s: %s (stored 0%%)' % (operation, zip_path) |
+ print(' %s: %s (stored 0%%)' % (operation, zip_path)) |
elif zip_info.compress_type == zipfile.ZIP_DEFLATED: |
- print ' %s: %s (deflated %d%%)' % (operation, zip_path, |
- 100 - zip_info.compress_size * 100 / zip_info.file_size) |
- finally: |
- zip_stream.close() |
+ print(' %s: %s (deflated %d%%)' % (operation, zip_path, |
+ 100 - zip_info.compress_size * 100 / zip_info.file_size)) |
return 0 |
@@ -494,16 +499,15 @@ def Which(args): |
Note: If you pass an argument with a path to which, it will just test if it |
is executable, not if it is in the path. |
""" |
- parser = optparse.OptionParser(usage='usage: which args...') |
- _, files = parser.parse_args(args) |
- if not files: |
- return 0 |
+ parser = argparse.ArgumentParser(description=Which.__doc__) |
+ parser.add_argument('files', nargs='+') |
+ options = parser.parse_args(args) |
retval = 0 |
- for filename in files: |
+ for filename in options.files: |
fullname = FindExeInPath(filename) |
if fullname: |
- print fullname |
+ print(fullname) |
else: |
retval = 1 |
@@ -522,19 +526,19 @@ FuncMap = { |
def main(args): |
if not args: |
- print 'No command specified' |
- print 'Available commands: %s' % ' '.join(FuncMap) |
+ print('No command specified') |
+ print('Available commands: %s' % ' '.join(FuncMap)) |
return 1 |
func_name = args[0] |
func = FuncMap.get(func_name) |
if not func: |
- print 'Do not recognize command: %s' % func_name |
- print 'Available commands: %s' % ' '.join(FuncMap) |
+ print('Do not recognize command: %s' % func_name) |
+ print('Available commands: %s' % ' '.join(FuncMap)) |
return 1 |
try: |
return func(args[1:]) |
except KeyboardInterrupt: |
- print '%s: interrupted' % func_name |
+ print('%s: interrupted' % func_name) |
return 1 |
if __name__ == '__main__': |