mbed os with nrf51 internal bandgap enabled to read battery level

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 """
elessair 0:f269e3021894 2 mbed SDK
elessair 0:f269e3021894 3 Copyright (c) 2011-2013 ARM Limited
elessair 0:f269e3021894 4
elessair 0:f269e3021894 5 Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 6 you may not use this file except in compliance with the License.
elessair 0:f269e3021894 7 You may obtain a copy of the License at
elessair 0:f269e3021894 8
elessair 0:f269e3021894 9 http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 10
elessair 0:f269e3021894 11 Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 12 distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 14 See the License for the specific language governing permissions and
elessair 0:f269e3021894 15 limitations under the License.
elessair 0:f269e3021894 16 """
elessair 0:f269e3021894 17 import sys
elessair 0:f269e3021894 18 import inspect
elessair 0:f269e3021894 19 import os
elessair 0:f269e3021894 20 import argparse
elessair 0:f269e3021894 21 import math
elessair 0:f269e3021894 22 from os import listdir, remove, makedirs
elessair 0:f269e3021894 23 from shutil import copyfile
elessair 0:f269e3021894 24 from os.path import isdir, join, exists, split, relpath, splitext, abspath
elessair 0:f269e3021894 25 from os.path import commonprefix, normpath, dirname
elessair 0:f269e3021894 26 from subprocess import Popen, PIPE, STDOUT, call
elessair 0:f269e3021894 27 import json
elessair 0:f269e3021894 28 from collections import OrderedDict
elessair 0:f269e3021894 29 import logging
elessair 0:f269e3021894 30
elessair 0:f269e3021894 31 def remove_if_in(lst, thing):
elessair 0:f269e3021894 32 if thing in lst:
elessair 0:f269e3021894 33 lst.remove(thing)
elessair 0:f269e3021894 34
elessair 0:f269e3021894 35 def compile_worker(job):
elessair 0:f269e3021894 36 """Standard task runner used for compiling
elessair 0:f269e3021894 37
elessair 0:f269e3021894 38 Positional argumets:
elessair 0:f269e3021894 39 job - a dict containing a list of commands and the remaining arguments
elessair 0:f269e3021894 40 to run_cmd
elessair 0:f269e3021894 41 """
elessair 0:f269e3021894 42 results = []
elessair 0:f269e3021894 43 for command in job['commands']:
elessair 0:f269e3021894 44 try:
elessair 0:f269e3021894 45 _, _stderr, _rc = run_cmd(command, work_dir=job['work_dir'],
elessair 0:f269e3021894 46 chroot=job['chroot'])
elessair 0:f269e3021894 47 except KeyboardInterrupt:
elessair 0:f269e3021894 48 raise ToolException
elessair 0:f269e3021894 49
elessair 0:f269e3021894 50 results.append({
elessair 0:f269e3021894 51 'code': _rc,
elessair 0:f269e3021894 52 'output': _stderr,
elessair 0:f269e3021894 53 'command': command
elessair 0:f269e3021894 54 })
elessair 0:f269e3021894 55
elessair 0:f269e3021894 56 return {
elessair 0:f269e3021894 57 'source': job['source'],
elessair 0:f269e3021894 58 'object': job['object'],
elessair 0:f269e3021894 59 'commands': job['commands'],
elessair 0:f269e3021894 60 'results': results
elessair 0:f269e3021894 61 }
elessair 0:f269e3021894 62
elessair 0:f269e3021894 63 def cmd(command, check=True, verbose=False, shell=False, cwd=None):
elessair 0:f269e3021894 64 """A wrapper to run a command as a blocking job"""
elessair 0:f269e3021894 65 text = command if shell else ' '.join(command)
elessair 0:f269e3021894 66 if verbose:
elessair 0:f269e3021894 67 print text
elessair 0:f269e3021894 68 return_code = call(command, shell=shell, cwd=cwd)
elessair 0:f269e3021894 69 if check and return_code != 0:
elessair 0:f269e3021894 70 raise Exception('ERROR %d: "%s"' % (return_code, text))
elessair 0:f269e3021894 71
elessair 0:f269e3021894 72
elessair 0:f269e3021894 73 def run_cmd(command, work_dir=None, chroot=None, redirect=False):
elessair 0:f269e3021894 74 """Run a command in the forground
elessair 0:f269e3021894 75
elessair 0:f269e3021894 76 Positional arguments:
elessair 0:f269e3021894 77 command - the command to run
elessair 0:f269e3021894 78
elessair 0:f269e3021894 79 Keyword arguments:
elessair 0:f269e3021894 80 work_dir - the working directory to run the command in
elessair 0:f269e3021894 81 chroot - the chroot to run the command in
elessair 0:f269e3021894 82 redirect - redirect the stderr to a pipe to be used later
elessair 0:f269e3021894 83 """
elessair 0:f269e3021894 84 if chroot:
elessair 0:f269e3021894 85 # Conventions managed by the web team for the mbed.org build system
elessair 0:f269e3021894 86 chroot_cmd = [
elessair 0:f269e3021894 87 '/usr/sbin/chroot', '--userspec=33:33', chroot
elessair 0:f269e3021894 88 ]
elessair 0:f269e3021894 89 for element in command:
elessair 0:f269e3021894 90 chroot_cmd += [element.replace(chroot, '')]
elessair 0:f269e3021894 91
elessair 0:f269e3021894 92 logging.debug("Running command %s", ' '.join(chroot_cmd))
elessair 0:f269e3021894 93 command = chroot_cmd
elessair 0:f269e3021894 94 work_dir = None
elessair 0:f269e3021894 95
elessair 0:f269e3021894 96 try:
elessair 0:f269e3021894 97 process = Popen(command, stdout=PIPE,
elessair 0:f269e3021894 98 stderr=STDOUT if redirect else PIPE, cwd=work_dir)
elessair 0:f269e3021894 99 _stdout, _stderr = process.communicate()
elessair 0:f269e3021894 100 except OSError:
elessair 0:f269e3021894 101 print "[OS ERROR] Command: "+(' '.join(command))
elessair 0:f269e3021894 102 raise
elessair 0:f269e3021894 103
elessair 0:f269e3021894 104 return _stdout, _stderr, process.returncode
elessair 0:f269e3021894 105
elessair 0:f269e3021894 106
elessair 0:f269e3021894 107 def run_cmd_ext(command):
elessair 0:f269e3021894 108 """ A version of run command that checks if the command exists befor running
elessair 0:f269e3021894 109
elessair 0:f269e3021894 110 Positional arguments:
elessair 0:f269e3021894 111 command - the command line you are trying to invoke
elessair 0:f269e3021894 112 """
elessair 0:f269e3021894 113 assert is_cmd_valid(command[0])
elessair 0:f269e3021894 114 process = Popen(command, stdout=PIPE, stderr=PIPE)
elessair 0:f269e3021894 115 _stdout, _stderr = process.communicate()
elessair 0:f269e3021894 116 return _stdout, _stderr, process.returncode
elessair 0:f269e3021894 117
elessair 0:f269e3021894 118
elessair 0:f269e3021894 119 def is_cmd_valid(command):
elessair 0:f269e3021894 120 """ Verify that a command exists and is executable
elessair 0:f269e3021894 121
elessair 0:f269e3021894 122 Positional arguments:
elessair 0:f269e3021894 123 command - the command to check
elessair 0:f269e3021894 124 """
elessair 0:f269e3021894 125 caller = get_caller_name()
elessair 0:f269e3021894 126 cmd_path = find_cmd_abspath(command)
elessair 0:f269e3021894 127 if not cmd_path:
elessair 0:f269e3021894 128 error("%s: Command '%s' can't be found" % (caller, command))
elessair 0:f269e3021894 129 if not is_exec(cmd_path):
elessair 0:f269e3021894 130 error("%s: Command '%s' resolves to file '%s' which is not executable"
elessair 0:f269e3021894 131 % (caller, command, cmd_path))
elessair 0:f269e3021894 132 return True
elessair 0:f269e3021894 133
elessair 0:f269e3021894 134
elessair 0:f269e3021894 135 def is_exec(path):
elessair 0:f269e3021894 136 """A simple check to verify that a path to an executable exists
elessair 0:f269e3021894 137
elessair 0:f269e3021894 138 Positional arguments:
elessair 0:f269e3021894 139 path - the executable
elessair 0:f269e3021894 140 """
elessair 0:f269e3021894 141 return os.access(path, os.X_OK) or os.access(path+'.exe', os.X_OK)
elessair 0:f269e3021894 142
elessair 0:f269e3021894 143
elessair 0:f269e3021894 144 def find_cmd_abspath(command):
elessair 0:f269e3021894 145 """ Returns the absolute path to a command.
elessair 0:f269e3021894 146 None is returned if no absolute path was found.
elessair 0:f269e3021894 147
elessair 0:f269e3021894 148 Positional arguhments:
elessair 0:f269e3021894 149 command - the command to find the path of
elessair 0:f269e3021894 150 """
elessair 0:f269e3021894 151 if exists(command) or exists(command + '.exe'):
elessair 0:f269e3021894 152 return os.path.abspath(command)
elessair 0:f269e3021894 153 if not 'PATH' in os.environ:
elessair 0:f269e3021894 154 raise Exception("Can't find command path for current platform ('%s')"
elessair 0:f269e3021894 155 % sys.platform)
elessair 0:f269e3021894 156 path_env = os.environ['PATH']
elessair 0:f269e3021894 157 for path in path_env.split(os.pathsep):
elessair 0:f269e3021894 158 cmd_path = '%s/%s' % (path, command)
elessair 0:f269e3021894 159 if exists(cmd_path) or exists(cmd_path + '.exe'):
elessair 0:f269e3021894 160 return cmd_path
elessair 0:f269e3021894 161
elessair 0:f269e3021894 162
elessair 0:f269e3021894 163 def mkdir(path):
elessair 0:f269e3021894 164 """ a wrapped makedirs that only tries to create a directory if it does not
elessair 0:f269e3021894 165 exist already
elessair 0:f269e3021894 166
elessair 0:f269e3021894 167 Positional arguments:
elessair 0:f269e3021894 168 path - the path to maybe create
elessair 0:f269e3021894 169 """
elessair 0:f269e3021894 170 if not exists(path):
elessair 0:f269e3021894 171 makedirs(path)
elessair 0:f269e3021894 172
elessair 0:f269e3021894 173
elessair 0:f269e3021894 174 def copy_file(src, dst):
elessair 0:f269e3021894 175 """ Implement the behaviour of "shutil.copy(src, dst)" without copying the
elessair 0:f269e3021894 176 permissions (this was causing errors with directories mounted with samba)
elessair 0:f269e3021894 177
elessair 0:f269e3021894 178 Positional arguments:
elessair 0:f269e3021894 179 src - the source of the copy operation
elessair 0:f269e3021894 180 dst - the destination of the copy operation
elessair 0:f269e3021894 181 """
elessair 0:f269e3021894 182 if isdir(dst):
elessair 0:f269e3021894 183 _, base = split(src)
elessair 0:f269e3021894 184 dst = join(dst, base)
elessair 0:f269e3021894 185 copyfile(src, dst)
elessair 0:f269e3021894 186
elessair 0:f269e3021894 187
elessair 0:f269e3021894 188 def delete_dir_files(directory):
elessair 0:f269e3021894 189 """ A function that does rm -rf
elessair 0:f269e3021894 190
elessair 0:f269e3021894 191 Positional arguments:
elessair 0:f269e3021894 192 directory - the directory to remove
elessair 0:f269e3021894 193 """
elessair 0:f269e3021894 194 if not exists(directory):
elessair 0:f269e3021894 195 return
elessair 0:f269e3021894 196
elessair 0:f269e3021894 197 for element in listdir(directory):
elessair 0:f269e3021894 198 to_remove = join(directory, element)
elessair 0:f269e3021894 199 if not isdir(to_remove):
elessair 0:f269e3021894 200 remove(file)
elessair 0:f269e3021894 201
elessair 0:f269e3021894 202
elessair 0:f269e3021894 203 def get_caller_name(steps=2):
elessair 0:f269e3021894 204 """
elessair 0:f269e3021894 205 When called inside a function, it returns the name
elessair 0:f269e3021894 206 of the caller of that function.
elessair 0:f269e3021894 207
elessair 0:f269e3021894 208 Keyword arguments:
elessair 0:f269e3021894 209 steps - the number of steps up the stack the calling function is
elessair 0:f269e3021894 210 """
elessair 0:f269e3021894 211 return inspect.stack()[steps][3]
elessair 0:f269e3021894 212
elessair 0:f269e3021894 213
elessair 0:f269e3021894 214 def error(msg):
elessair 0:f269e3021894 215 """Fatal error, abort hard
elessair 0:f269e3021894 216
elessair 0:f269e3021894 217 Positional arguments:
elessair 0:f269e3021894 218 msg - the message to print before crashing
elessair 0:f269e3021894 219 """
elessair 0:f269e3021894 220 print("ERROR: %s" % msg)
elessair 0:f269e3021894 221 sys.exit(1)
elessair 0:f269e3021894 222
elessair 0:f269e3021894 223
elessair 0:f269e3021894 224 def rel_path(path, base, dot=False):
elessair 0:f269e3021894 225 """Relative path calculation that optionaly always starts with a dot
elessair 0:f269e3021894 226
elessair 0:f269e3021894 227 Positional arguments:
elessair 0:f269e3021894 228 path - the path to make relative
elessair 0:f269e3021894 229 base - what to make the path relative to
elessair 0:f269e3021894 230
elessair 0:f269e3021894 231 Keyword arguments:
elessair 0:f269e3021894 232 dot - if True, the path will always start with a './'
elessair 0:f269e3021894 233 """
elessair 0:f269e3021894 234 final_path = relpath(path, base)
elessair 0:f269e3021894 235 if dot and not final_path.startswith('.'):
elessair 0:f269e3021894 236 final_path = './' + final_path
elessair 0:f269e3021894 237 return final_path
elessair 0:f269e3021894 238
elessair 0:f269e3021894 239
elessair 0:f269e3021894 240 class ToolException(Exception):
elessair 0:f269e3021894 241 """A class representing an exception throw by the tools"""
elessair 0:f269e3021894 242 pass
elessair 0:f269e3021894 243
elessair 0:f269e3021894 244 class NotSupportedException(Exception):
elessair 0:f269e3021894 245 """A class a toolchain not supporting a particular target"""
elessair 0:f269e3021894 246 pass
elessair 0:f269e3021894 247
elessair 0:f269e3021894 248 class InvalidReleaseTargetException(Exception):
elessair 0:f269e3021894 249 pass
elessair 0:f269e3021894 250
elessair 0:f269e3021894 251 def split_path(path):
elessair 0:f269e3021894 252 """spilt a file name into it's directory name, base name, and extension
elessair 0:f269e3021894 253
elessair 0:f269e3021894 254 Positional arguments:
elessair 0:f269e3021894 255 path - the file name to split
elessair 0:f269e3021894 256 """
elessair 0:f269e3021894 257 base, has_ext = split(path)
elessair 0:f269e3021894 258 name, ext = splitext(has_ext)
elessair 0:f269e3021894 259 return base, name, ext
elessair 0:f269e3021894 260
elessair 0:f269e3021894 261
elessair 0:f269e3021894 262 def get_path_depth(path):
elessair 0:f269e3021894 263 """ Given a path, return the number of directory levels present.
elessair 0:f269e3021894 264 This roughly translates to the number of path separators (os.sep) + 1.
elessair 0:f269e3021894 265 Ex. Given "path/to/dir", this would return 3
elessair 0:f269e3021894 266 Special cases: "." and "/" return 0
elessair 0:f269e3021894 267
elessair 0:f269e3021894 268 Positional arguments:
elessair 0:f269e3021894 269 path - the path to calculate the depth of
elessair 0:f269e3021894 270 """
elessair 0:f269e3021894 271 normalized_path = normpath(path)
elessair 0:f269e3021894 272 path_depth = 0
elessair 0:f269e3021894 273 head, tail = split(normalized_path)
elessair 0:f269e3021894 274
elessair 0:f269e3021894 275 while tail and tail != '.':
elessair 0:f269e3021894 276 path_depth += 1
elessair 0:f269e3021894 277 head, tail = split(head)
elessair 0:f269e3021894 278
elessair 0:f269e3021894 279 return path_depth
elessair 0:f269e3021894 280
elessair 0:f269e3021894 281
elessair 0:f269e3021894 282 def args_error(parser, message):
elessair 0:f269e3021894 283 """Abort with an error that was generated by the arguments to a CLI program
elessair 0:f269e3021894 284
elessair 0:f269e3021894 285 Positional arguments:
elessair 0:f269e3021894 286 parser - the ArgumentParser object that parsed the command line
elessair 0:f269e3021894 287 message - what went wrong
elessair 0:f269e3021894 288 """
elessair 0:f269e3021894 289 parser.error(message)
elessair 0:f269e3021894 290 sys.exit(2)
elessair 0:f269e3021894 291
elessair 0:f269e3021894 292
elessair 0:f269e3021894 293 def construct_enum(**enums):
elessair 0:f269e3021894 294 """ Create your own pseudo-enums
elessair 0:f269e3021894 295
elessair 0:f269e3021894 296 Keyword arguments:
elessair 0:f269e3021894 297 * - a member of the Enum you are creating and it's value
elessair 0:f269e3021894 298 """
elessair 0:f269e3021894 299 return type('Enum', (), enums)
elessair 0:f269e3021894 300
elessair 0:f269e3021894 301
elessair 0:f269e3021894 302 def check_required_modules(required_modules, verbose=True):
elessair 0:f269e3021894 303 """ Function checks for Python modules which should be "importable"
elessair 0:f269e3021894 304 before test suite can be used.
elessair 0:f269e3021894 305 @return returns True if all modules are installed already
elessair 0:f269e3021894 306 """
elessair 0:f269e3021894 307 import imp
elessair 0:f269e3021894 308 not_installed_modules = []
elessair 0:f269e3021894 309 for module_name in required_modules:
elessair 0:f269e3021894 310 try:
elessair 0:f269e3021894 311 imp.find_module(module_name)
elessair 0:f269e3021894 312 except ImportError:
elessair 0:f269e3021894 313 # We also test against a rare case: module is an egg file
elessair 0:f269e3021894 314 try:
elessair 0:f269e3021894 315 __import__(module_name)
elessair 0:f269e3021894 316 except ImportError as exc:
elessair 0:f269e3021894 317 not_installed_modules.append(module_name)
elessair 0:f269e3021894 318 if verbose:
elessair 0:f269e3021894 319 print "Error: %s" % exc
elessair 0:f269e3021894 320
elessair 0:f269e3021894 321 if verbose:
elessair 0:f269e3021894 322 if not_installed_modules:
elessair 0:f269e3021894 323 print ("Warning: Module(s) %s not installed. Please install " + \
elessair 0:f269e3021894 324 "required module(s) before using this script.")\
elessair 0:f269e3021894 325 % (', '.join(not_installed_modules))
elessair 0:f269e3021894 326
elessair 0:f269e3021894 327 if not_installed_modules:
elessair 0:f269e3021894 328 return False
elessair 0:f269e3021894 329 else:
elessair 0:f269e3021894 330 return True
elessair 0:f269e3021894 331
elessair 0:f269e3021894 332 def dict_to_ascii(dictionary):
elessair 0:f269e3021894 333 """ Utility function: traverse a dictionary and change all the strings in
elessair 0:f269e3021894 334 the dictionary to ASCII from Unicode. Useful when reading ASCII JSON data,
elessair 0:f269e3021894 335 because the JSON decoder always returns Unicode string. Based on
elessair 0:f269e3021894 336 http://stackoverflow.com/a/13105359
elessair 0:f269e3021894 337
elessair 0:f269e3021894 338 Positional arguments:
elessair 0:f269e3021894 339 dictionary - The dict that contains some Unicode that should be ASCII
elessair 0:f269e3021894 340 """
elessair 0:f269e3021894 341 if isinstance(dictionary, dict):
elessair 0:f269e3021894 342 return OrderedDict([(dict_to_ascii(key), dict_to_ascii(value))
elessair 0:f269e3021894 343 for key, value in dictionary.iteritems()])
elessair 0:f269e3021894 344 elif isinstance(dictionary, list):
elessair 0:f269e3021894 345 return [dict_to_ascii(element) for element in dictionary]
elessair 0:f269e3021894 346 elif isinstance(dictionary, unicode):
elessair 0:f269e3021894 347 return dictionary.encode('ascii')
elessair 0:f269e3021894 348 else:
elessair 0:f269e3021894 349 return dictionary
elessair 0:f269e3021894 350
elessair 0:f269e3021894 351 def json_file_to_dict(fname):
elessair 0:f269e3021894 352 """ Read a JSON file and return its Python representation, transforming all
elessair 0:f269e3021894 353 the strings from Unicode to ASCII. The order of keys in the JSON file is
elessair 0:f269e3021894 354 preserved.
elessair 0:f269e3021894 355
elessair 0:f269e3021894 356 Positional arguments:
elessair 0:f269e3021894 357 fname - the name of the file to parse
elessair 0:f269e3021894 358 """
elessair 0:f269e3021894 359 try:
elessair 0:f269e3021894 360 with open(fname, "r") as file_obj:
elessair 0:f269e3021894 361 return dict_to_ascii(json.load(file_obj,
elessair 0:f269e3021894 362 object_pairs_hook=OrderedDict))
elessair 0:f269e3021894 363 except (ValueError, IOError):
elessair 0:f269e3021894 364 sys.stderr.write("Error parsing '%s':\n" % fname)
elessair 0:f269e3021894 365 raise
elessair 0:f269e3021894 366
elessair 0:f269e3021894 367 # Wowza, double closure
elessair 0:f269e3021894 368 def argparse_type(casedness, prefer_hyphen=False):
elessair 0:f269e3021894 369 def middle(lst, type_name):
elessair 0:f269e3021894 370 def parse_type(string):
elessair 0:f269e3021894 371 """ validate that an argument passed in (as string) is a member of
elessair 0:f269e3021894 372 the list of possible arguments. Offer a suggestion if the case of
elessair 0:f269e3021894 373 the string, or the hyphens/underscores do not match the expected
elessair 0:f269e3021894 374 style of the argument.
elessair 0:f269e3021894 375 """
elessair 0:f269e3021894 376 if prefer_hyphen:
elessair 0:f269e3021894 377 newstring = casedness(string).replace("_", "-")
elessair 0:f269e3021894 378 else:
elessair 0:f269e3021894 379 newstring = casedness(string).replace("-", "_")
elessair 0:f269e3021894 380 if string in lst:
elessair 0:f269e3021894 381 return string
elessair 0:f269e3021894 382 elif string not in lst and newstring in lst:
elessair 0:f269e3021894 383 raise argparse.ArgumentTypeError(
elessair 0:f269e3021894 384 "{0} is not a supported {1}. Did you mean {2}?".format(
elessair 0:f269e3021894 385 string, type_name, newstring))
elessair 0:f269e3021894 386 else:
elessair 0:f269e3021894 387 raise argparse.ArgumentTypeError(
elessair 0:f269e3021894 388 "{0} is not a supported {1}. Supported {1}s are:\n{2}".
elessair 0:f269e3021894 389 format(string, type_name, columnate(lst)))
elessair 0:f269e3021894 390 return parse_type
elessair 0:f269e3021894 391 return middle
elessair 0:f269e3021894 392
elessair 0:f269e3021894 393 # short cuts for the argparse_type versions
elessair 0:f269e3021894 394 argparse_uppercase_type = argparse_type(str.upper, False)
elessair 0:f269e3021894 395 argparse_lowercase_type = argparse_type(str.lower, False)
elessair 0:f269e3021894 396 argparse_uppercase_hyphen_type = argparse_type(str.upper, True)
elessair 0:f269e3021894 397 argparse_lowercase_hyphen_type = argparse_type(str.lower, True)
elessair 0:f269e3021894 398
elessair 0:f269e3021894 399 def argparse_force_type(case):
elessair 0:f269e3021894 400 """ validate that an argument passed in (as string) is a member of the list
elessair 0:f269e3021894 401 of possible arguments after converting it's case.
elessair 0:f269e3021894 402 """
elessair 0:f269e3021894 403 def middle(lst, type_name):
elessair 0:f269e3021894 404 """ The parser type generator"""
elessair 0:f269e3021894 405 def parse_type(string):
elessair 0:f269e3021894 406 """ The parser type"""
elessair 0:f269e3021894 407 for option in lst:
elessair 0:f269e3021894 408 if case(string) == case(option):
elessair 0:f269e3021894 409 return option
elessair 0:f269e3021894 410 raise argparse.ArgumentTypeError(
elessair 0:f269e3021894 411 "{0} is not a supported {1}. Supported {1}s are:\n{2}".
elessair 0:f269e3021894 412 format(string, type_name, columnate(lst)))
elessair 0:f269e3021894 413 return parse_type
elessair 0:f269e3021894 414 return middle
elessair 0:f269e3021894 415
elessair 0:f269e3021894 416 # these two types convert the case of their arguments _before_ validation
elessair 0:f269e3021894 417 argparse_force_uppercase_type = argparse_force_type(str.upper)
elessair 0:f269e3021894 418 argparse_force_lowercase_type = argparse_force_type(str.lower)
elessair 0:f269e3021894 419
elessair 0:f269e3021894 420 def argparse_many(func):
elessair 0:f269e3021894 421 """ An argument parser combinator that takes in an argument parser and
elessair 0:f269e3021894 422 creates a new parser that accepts a comma separated list of the same thing.
elessair 0:f269e3021894 423 """
elessair 0:f269e3021894 424 def wrap(string):
elessair 0:f269e3021894 425 """ The actual parser"""
elessair 0:f269e3021894 426 return [func(s) for s in string.split(",")]
elessair 0:f269e3021894 427 return wrap
elessair 0:f269e3021894 428
elessair 0:f269e3021894 429 def argparse_filestring_type(string):
elessair 0:f269e3021894 430 """ An argument parser that verifies that a string passed in corresponds
elessair 0:f269e3021894 431 to a file"""
elessair 0:f269e3021894 432 if exists(string):
elessair 0:f269e3021894 433 return string
elessair 0:f269e3021894 434 else:
elessair 0:f269e3021894 435 raise argparse.ArgumentTypeError(
elessair 0:f269e3021894 436 "{0}"" does not exist in the filesystem.".format(string))
elessair 0:f269e3021894 437
elessair 0:f269e3021894 438 def argparse_profile_filestring_type(string):
elessair 0:f269e3021894 439 """ An argument parser that verifies that a string passed in is either
elessair 0:f269e3021894 440 absolute path or a file name (expanded to
elessair 0:f269e3021894 441 mbed-os/tools/profiles/<fname>.json) of a existing file"""
elessair 0:f269e3021894 442 fpath = join(dirname(__file__), "profiles/{}.json".format(string))
elessair 0:f269e3021894 443 if exists(string):
elessair 0:f269e3021894 444 return string
elessair 0:f269e3021894 445 elif exists(fpath):
elessair 0:f269e3021894 446 return fpath
elessair 0:f269e3021894 447 else:
elessair 0:f269e3021894 448 raise argparse.ArgumentTypeError(
elessair 0:f269e3021894 449 "{0} does not exist in the filesystem.".format(string))
elessair 0:f269e3021894 450
elessair 0:f269e3021894 451 def columnate(strings, separator=", ", chars=80):
elessair 0:f269e3021894 452 """ render a list of strings as a in a bunch of columns
elessair 0:f269e3021894 453
elessair 0:f269e3021894 454 Positional arguments:
elessair 0:f269e3021894 455 strings - the strings to columnate
elessair 0:f269e3021894 456
elessair 0:f269e3021894 457 Keyword arguments;
elessair 0:f269e3021894 458 separator - the separation between the columns
elessair 0:f269e3021894 459 chars - the maximum with of a row
elessair 0:f269e3021894 460 """
elessair 0:f269e3021894 461 col_width = max(len(s) for s in strings)
elessair 0:f269e3021894 462 total_width = col_width + len(separator)
elessair 0:f269e3021894 463 columns = math.floor(chars / total_width)
elessair 0:f269e3021894 464 output = ""
elessair 0:f269e3021894 465 for i, string in zip(range(len(strings)), strings):
elessair 0:f269e3021894 466 append = string
elessair 0:f269e3021894 467 if i != len(strings) - 1:
elessair 0:f269e3021894 468 append += separator
elessair 0:f269e3021894 469 if i % columns == columns - 1:
elessair 0:f269e3021894 470 append += "\n"
elessair 0:f269e3021894 471 else:
elessair 0:f269e3021894 472 append = append.ljust(total_width)
elessair 0:f269e3021894 473 output += append
elessair 0:f269e3021894 474 return output
elessair 0:f269e3021894 475
elessair 0:f269e3021894 476 def argparse_dir_not_parent(other):
elessair 0:f269e3021894 477 """fail if argument provided is a parent of the specified directory"""
elessair 0:f269e3021894 478 def parse_type(not_parent):
elessair 0:f269e3021894 479 """The parser type"""
elessair 0:f269e3021894 480 abs_other = abspath(other)
elessair 0:f269e3021894 481 abs_not_parent = abspath(not_parent)
elessair 0:f269e3021894 482 if abs_not_parent == commonprefix([abs_not_parent, abs_other]):
elessair 0:f269e3021894 483 raise argparse.ArgumentTypeError(
elessair 0:f269e3021894 484 "{0} may not be a parent directory of {1}".format(
elessair 0:f269e3021894 485 not_parent, other))
elessair 0:f269e3021894 486 else:
elessair 0:f269e3021894 487 return not_parent
elessair 0:f269e3021894 488 return parse_type