2 ''''export SCRIPT_PATH="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)" # '''
3 ''''export PY_PATH=${SCRIPT_PATH}/venv/bin/python # '''
4 ''''test -f ${PY_PATH} && exec ${PY_PATH} "$0" "$@" # '''
5 ''''echo "Error: Virtual environment not found. Please run 'one-prepare-venv' command." # '''
8 # Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
10 # Licensed under the Apache License, Version 2.0 (the "License");
11 # you may not use this file except in compliance with the License.
12 # You may obtain a copy of the License at
14 # http://www.apache.org/licenses/LICENSE-2.0
16 # Unless required by applicable law or agreed to in writing, software
17 # distributed under the License is distributed on an "AS IS" BASIS,
18 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 # See the License for the specific language governing permissions and
20 # limitations under the License.
29 from types import SimpleNamespace
31 import onelib.utils as oneutils
33 # TODO Find better way to suppress trackback on error
34 sys.tracebacklimit = 0
37 def _get_backends_list():
48 The list where `one-profile` finds its backends
49 - `bin` folder where `one-profile` exists
52 NOTE If there are backends of the same name in different places,
53 the closer to the top in the list, the higher the priority.
55 dir_path = os.path.dirname(os.path.realpath(__file__))
59 files = [f for f in glob.glob(dir_path + '/*-profile')]
62 f for f in glob.glob(dir_path + '/../backends/**/*-profile', recursive=True)
64 # TODO find backends in `$PATH`
68 base = ntpath.basename(cand)
69 if not base in backend_set and os.path.isfile(cand) and os.access(cand, os.X_OK):
71 backends_list.append(cand)
76 def _get_parser(backends_list):
77 profile_usage = 'one-profile [-h] [-v] [-C CONFIG] [-b BACKEND] [--] [COMMANDS FOR BACKEND]'
78 parser = argparse.ArgumentParser(
79 description='command line tool for profiling backend model', usage=profile_usage)
81 oneutils.add_default_arg(parser)
83 # get backend list in the directory
84 backends_name = [ntpath.basename(f) for f in backends_list]
86 backends_name_message = '(There is no available backend drivers)'
88 backends_name_message = '(available backend drivers: ' + ', '.join(
90 backend_help_message = 'backend name to use ' + backends_name_message
91 parser.add_argument('-b', '--backend', type=str, help=backend_help_message)
96 def _verify_arg(parser, args, cfg_args, backend_args, unknown_args):
97 """verify given arguments"""
98 cmd_backend_exist = oneutils.is_valid_attr(args, 'backend')
99 cfg_backend_exist = oneutils.is_valid_attr(cfg_args, 'backend')
100 cfg_backends_exist = oneutils.is_valid_attr(cfg_args, 'backends')
102 # check if required arguments is given
104 if not cmd_backend_exist and not cfg_backend_exist and not cfg_backends_exist:
105 missing.append('-b/--backend')
107 parser.error('the following arguments are required: ' + ' '.join(missing))
109 if not oneutils.is_valid_attr(args, 'config'):
110 if not backend_args and not unknown_args:
111 parser.error('commands for the backend is missing.')
113 if cfg_backend_exist and cfg_backends_exist:
115 '\'backend\' option and \'backends\' option cannot be used simultaneously.')
117 # Check if given backend from command line exists in the configuration file
118 if cmd_backend_exist and cfg_backend_exist:
119 if args.backend != cfg_args.backend:
120 parser.error('Not found the command of given backend')
122 if cfg_backend_exist and not oneutils.is_valid_attr(cfg_args, 'command'):
123 parser.error('\'command\' key is missing in the configuration file.')
125 if cfg_backends_exist:
126 cfg_backends = getattr(cfg_args, 'backends').split(',')
127 # check if commands of given backends exist
128 for b in cfg_backends:
129 if not oneutils.is_valid_attr(cfg_args, b):
130 parser.error('Not found the command for ' + b)
131 # Check if given backend from command line exists in the configuration file
132 if cmd_backend_exist:
133 if args.backend not in cfg_backends:
134 parser.error('Not found the command of given backend')
137 def _parse_arg(parser):
141 argv = copy.deepcopy(sys.argv)
145 args = [list(y) for x, y in itertools.groupby(argv, lambda z: z == '--') if not x]
147 profile_args = parser.parse_args(profile_args)
148 # one-profile has two interfaces
149 # 1. one-profile [-h] [-v] [-C CONFIG] [-b BACKEND] [COMMANDS FOR BACKEND]
151 profile_args = args[0]
152 profile_args, unknown_args = parser.parse_known_args(profile_args)
153 # 2. one-profile [-h] [-v] [-C CONFIG] [-b BACKEND] -- [COMMANDS FOR BACKEND]
155 profile_args = args[0]
156 backend_args = args[1]
157 profile_args = parser.parse_args(profile_args)
159 if len(args) and profile_args.version:
160 oneutils.print_version_and_exit(__file__)
162 return profile_args, backend_args, unknown_args
167 backends_list = _get_backends_list()
170 parser = _get_parser(backends_list)
171 args, backend_args, unknown_args = _parse_arg(parser)
173 # parse configuration file
174 cfg_args = SimpleNamespace()
175 oneutils.parse_cfg(args.config, 'one-profile', cfg_args)
178 _verify_arg(parser, args, cfg_args, backend_args, unknown_args)
180 one-profile defines its behavior for below cases.
184 [3] one-profile -C ${cfg} (backend, command key in cfg)
185 [4] one-profile -C ${cfg} (backends key in cfg)
186 [5] one-profile -b ${backend} ${command}
187 [6] one-profile -b ${backend} -- ${command}
188 [7] one-profile -b ${backend} -C {cfg} (backend, command key in cfg)
189 [8] one-profile -b ${backend} -C {cfg} (backends key in cfg) (Only 'backend' is invoked,
190 even though cfg file has multiple backends)
191 [9] one-profile -b ${backend} -C ${cfg} -- ${command} (backend, command key in cfg)
192 [10] one-profile -b ${backend} -C ${cfg} -- ${command} (backends key in cfg) (Only 'backend' is invoked,
193 even though cfg file has multiple backends)
195 All other cases are not allowed or an undefined behavior.
197 cmd_overwrite = False
198 if oneutils.is_valid_attr(args, 'config'):
200 if backend_args and not unknown_args:
201 given_backends = [args.backend]
205 if oneutils.is_valid_attr(args, 'backend'):
206 given_backends = [args.backend]
207 if oneutils.is_valid_attr(cfg_args, 'backend'):
208 assert (oneutils.is_valid_attr(cfg_args, 'command'))
209 setattr(cfg_args, args.backend, cfg_args.command)
212 if oneutils.is_valid_attr(cfg_args, 'backend'):
213 assert (oneutils.is_valid_attr(cfg_args, 'command'))
214 given_backends = [cfg_args.backend]
215 setattr(cfg_args, cfg_args.backend, cfg_args.command)
217 if oneutils.is_valid_attr(cfg_args, 'backends'):
218 given_backends = cfg_args.backends.split(',')
221 assert (backend_args or unknown_args)
222 given_backends = [args.backend]
224 for given_backend in given_backends:
225 # make a command to run given backend driver
227 backend_base = given_backend + '-profile'
228 for cand in backends_list:
229 if ntpath.basename(cand) == backend_base:
232 raise FileNotFoundError(backend_base + ' not found')
234 profile_cmd = [profile_path]
235 if not cmd_overwrite and oneutils.is_valid_attr(cfg_args, given_backend):
236 profile_cmd += getattr(cfg_args, given_backend).split()
238 profile_cmd += backend_args
239 profile_cmd += unknown_args
242 oneutils.run(profile_cmd, err_prefix=backend_base)
245 if __name__ == '__main__':