1 # Copyright (C) 2014-2018 Intel Corporation. All Rights Reserved.
3 # Permission is hereby granted, free of charge, to any person obtaining a
4 # copy of this software and associated documentation files (the "Software"),
5 # to deal in the Software without restriction, including without limitation
6 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 # and/or sell copies of the Software, and to permit persons to whom the
8 # Software is furnished to do so, subject to the following conditions:
10 # The above copyright notice and this permission notice (including the next
11 # paragraph) shall be included in all copies or substantial portions of the
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 from __future__
import print_function
31 from mako
.template
import Template
32 from mako
.exceptions
import RichTraceback
34 #==============================================================================
35 def ConcatLists(list_of_lists
):
37 for l
in list_of_lists
: output
+= l
40 #==============================================================================
41 def MakeTmpDir(suffix
=''):
43 Create temporary directory for use in codegen scripts.
45 return tempfile
.mkdtemp(suffix
)
47 #==============================================================================
48 def MakeDir(dir_path
):
50 Create a directory if it doesn't exist
52 returns 0 on success, non-zero on failure
54 dir_path
= os
.path
.abspath(dir_path
)
56 if not os
.path
.exists(dir_path
):
59 except OSError as err
:
60 if err
.errno
!= errno
.EEXIST
:
63 if not os
.path
.isdir(dir_path
):
68 #==============================================================================
69 def DeleteDirTree(dir_path
):
71 Delete directory tree.
73 returns 0 on success, non-zero on failure
77 shutil
.rmtree(dir_path
, False)
82 #==============================================================================
83 def CopyFileIfDifferent(src
, dst
, verbose
= False):
85 Copy <src> file to <dst> file if the <dst>
86 file either doesn't contain the file or the file
87 contents are different.
89 returns 0 on success, non-zero on failure
92 assert os
.path
.isfile(src
)
93 assert (False == os
.path
.exists(dst
) or os
.path
.isfile(dst
))
95 need_copy
= not os
.path
.exists(dst
)
97 need_copy
= not filecmp
.cmp(src
, dst
)
101 shutil
.copy2(src
, dst
)
103 print('ERROR: Could not copy %s to %s' % (src
, dst
), file=sys
.stderr
)
107 print(src
, '-->', dst
)
111 #==============================================================================
112 def CopyDirFilesIfDifferent(src
, dst
, recurse
= True, verbose
= False, orig_dst
= None):
114 Copy files <src> directory to <dst> directory if the <dst>
115 directory either doesn't contain the file or the file
116 contents are different.
118 Optionally recurses into subdirectories
120 returns 0 on success, non-zero on failure
123 assert os
.path
.isdir(src
)
124 assert os
.path
.isdir(dst
)
126 src
= os
.path
.abspath(src
)
127 dst
= os
.path
.abspath(dst
)
132 for f
in os
.listdir(src
):
133 src_path
= os
.path
.join(src
, f
)
134 dst_path
= os
.path
.join(dst
, f
)
137 if src_path
== orig_dst
:
140 if os
.path
.isdir(src_path
):
142 if MakeDir(dst_path
):
143 print('ERROR: Could not create directory:', dst_path
, file=sys
.stderr
)
147 print('mkdir', dst_path
)
148 rval
= CopyDirFilesIfDifferent(src_path
, dst_path
, recurse
, verbose
, orig_dst
)
150 rval
= CopyFileIfDifferent(src_path
, dst_path
, verbose
)
157 #==============================================================================
158 class MakoTemplateWriter
:
160 MakoTemplateWriter - Class (namespace) for functions to generate strings
161 or files using the Mako template module.
163 See http://docs.makotemplates.org/en/latest/ for
168 def to_string(template_filename
, **kwargs
):
170 Write template data to a string object and return the string
172 from mako
.template
import Template
173 from mako
.exceptions
import RichTraceback
176 template
= Template(filename
=template_filename
)
177 # Split + Join fixes line-endings for whatever platform you are using
178 return '\n'.join(template
.render(**kwargs
).splitlines())
180 traceback
= RichTraceback()
181 for (filename
, lineno
, function
, line
) in traceback
.traceback
:
182 print('File %s, line %s, in %s' % (filename
, lineno
, function
))
184 print('%s: %s' % (str(traceback
.error
.__class
__.__name
__), traceback
.error
))
188 def to_file(template_filename
, output_filename
, **kwargs
):
190 Write template data to a file
192 if MakeDir(os
.path
.dirname(output_filename
)):
194 with
open(output_filename
, 'w') as outfile
:
195 print(MakoTemplateWriter
.to_string(template_filename
, **kwargs
), file=outfile
)
199 #==============================================================================
200 class ArgumentParser(argparse
.ArgumentParser
):
202 Subclass of argparse.ArgumentParser
204 Allow parsing from command files that start with @
208 Contents of myargs.txt:
212 The below function allows multiple args to be placed on the same text-file line.
213 The default is one token per line, which is a little cumbersome.
215 Also allow all characters after a '#' character to be ignored.
218 #==============================================================================
219 class _HelpFormatter(argparse
.RawTextHelpFormatter
):
220 ''' Better help formatter for argument parser '''
222 def _split_lines(self
, text
, width
):
223 ''' optimized split lines algorighm, indents split lines '''
224 lines
= text
.splitlines()
227 out_lines
.append(lines
[0])
228 for line
in lines
[1:]:
229 out_lines
.append(' ' + line
)
232 #==============================================================================
233 def __init__(self
, *args
, **kwargs
):
234 ''' Constructor. Compatible with argparse.ArgumentParser(),
235 but with some modifications for better usage and help display.
237 super(ArgumentParser
, self
).__init
__(
239 fromfile_prefix_chars
='@',
240 formatter_class
=ArgumentParser
._HelpFormatter
,
243 #==========================================================================
244 def convert_arg_line_to_args(self
, arg_line
):
245 ''' convert one line of parsed file to arguments '''
246 arg_line
= arg_line
.split('#', 1)[0]
247 if sys
.platform
== 'win32':
248 arg_line
= arg_line
.replace('\\', '\\\\')
249 for arg
in shlex
.split(arg_line
):
254 #==========================================================================
255 def _read_args_from_files(self
, arg_strings
):
256 ''' read arguments from files '''
257 # expand arguments referencing files
259 for arg_string
in arg_strings
:
261 # for regular arguments, just add them back into the list
262 if arg_string
[0] not in self
.fromfile_prefix_chars
:
263 new_arg_strings
.append(arg_string
)
265 # replace arguments referencing files with the file content
267 filename
= arg_string
[1:]
270 if not os
.path
.exists(filename
):
271 for path
in sys
.path
:
272 filename
= os
.path
.join(path
, arg_string
[1:])
273 if os
.path
.exists(filename
):
277 args_file
= open(filename
)
280 for arg_line
in args_file
.read().splitlines():
281 for arg
in self
.convert_arg_line_to_args(arg_line
):
282 arg_strings
.append(arg
)
283 arg_strings
= self
._read
_args
_from
_files
(arg_strings
)
284 new_arg_strings
.extend(arg_strings
)
288 err
= sys
.exc_info()[1]
291 # return the modified argument list
292 return new_arg_strings