Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 1 | # Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
Ruben Rodriguez Buchillon | 0902f09 | 2018-09-19 15:03:17 +0800 | [diff] [blame] | 4 | """Common code for servo parsing support.""" |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 5 | |
| 6 | import argparse |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 7 | import logging |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 8 | import os |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 9 | import sys |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 10 | import textwrap |
| 11 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 12 | import client |
| 13 | import servo_logging |
| 14 | import servodutil |
| 15 | |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 16 | if os.getuid(): |
| 17 | DEFAULT_RC_FILE = '/home/%s/.servodrc' % os.getenv('USER', '') |
| 18 | else: |
| 19 | DEFAULT_RC_FILE = '/home/%s/.servodrc' % os.getenv('SUDO_USER', '') |
| 20 | |
| 21 | |
| 22 | class ServodParserHelpFormatter(argparse.RawDescriptionHelpFormatter, |
| 23 | argparse.ArgumentDefaultsHelpFormatter): |
| 24 | """Servod help formatter. |
| 25 | |
| 26 | Combines ability for raw description printing (needed to have control over |
| 27 | how to print examples) and default argument printing, printing the default |
| 28 | which each argument. |
| 29 | """ |
| 30 | pass |
| 31 | |
| 32 | |
| 33 | class ServodParserError(Exception): |
| 34 | """Error class for Servod parsing errors.""" |
| 35 | pass |
| 36 | |
| 37 | |
| 38 | class _BaseServodParser(argparse.ArgumentParser): |
| 39 | """Extension to ArgumentParser that allows for examples in the description. |
| 40 | |
| 41 | _BaseServodParser allows for a list of example tuples, where |
| 42 | element[0]: is the cmdline invocation |
| 43 | element[1]: is a comment to explain what the invocation does. |
| 44 | |
| 45 | For example (loosely based on servod.) |
| 46 | ('-b board', 'Start servod with the configuation for board |board|') |
| 47 | would print the following help message: |
| 48 | ... |
| 49 | |
| 50 | Examples: |
| 51 | > servod -b board |
| 52 | Start servod with the configuration for board |board| |
| 53 | |
| 54 | Optional Arguments... |
| 55 | |
| 56 | see servod, or dut_control for more examples. |
| 57 | """ |
| 58 | |
Ruben Rodriguez Buchillon | 0902f09 | 2018-09-19 15:03:17 +0800 | [diff] [blame] | 59 | def __init__(self, description='', examples=None, **kwargs): |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 60 | """Initialize _BaseServodParser by setting description and formatter. |
| 61 | |
| 62 | Args: |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 63 | description: description of the program |
| 64 | examples: list of tuples where the first element is the cmdline example, |
| 65 | and the second element is a comment explaining the example. |
| 66 | %(prog)s will be prepended to each example if it does not |
| 67 | start with %(prog)s. |
Ruben Rodriguez Buchillon | 0902f09 | 2018-09-19 15:03:17 +0800 | [diff] [blame] | 68 | **kwargs: keyword arguments forwarded to ArgumentParser |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 69 | """ |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 70 | # Initialize logging up here first to ensure log messages from parsing |
| 71 | # can go through. |
| 72 | loglevel, fmt = servo_logging.LOGLEVEL_MAP[servo_logging.DEFAULT_LOGLEVEL] |
| 73 | logging.basicConfig(loglevel=loglevel, format=fmt) |
| 74 | self._logger = logging.getLogger(type(self).__name__) |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 75 | # Generate description. |
| 76 | description_lines = textwrap.wrap(description) |
| 77 | # Setting it into the kwargs here ensures that we overwrite an potentially |
| 78 | # passed in and undesired formatter class. |
| 79 | kwargs['formatter_class'] = ServodParserHelpFormatter |
| 80 | if examples: |
| 81 | # Extra newline to separate description from examples. |
| 82 | description_lines.append('\n') |
| 83 | description_lines.append('Examples:') |
| 84 | for example, comment in examples: |
| 85 | if not example.startswith('%(prog)s'): |
| 86 | example = '%(prog)s ' + example |
| 87 | example_lines = [' > ' + example] |
| 88 | example_lines.extend(textwrap.wrap(comment)) |
| 89 | description_lines.append('\n\t'.join(example_lines)) |
| 90 | description = '\n'.join(description_lines) |
| 91 | kwargs['description'] = description |
Ruben Rodriguez Buchillon | 0902f09 | 2018-09-19 15:03:17 +0800 | [diff] [blame] | 92 | super(_BaseServodParser, self).__init__(**kwargs) |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 93 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 94 | @staticmethod |
| 95 | def _HandleEnvVar(cmdline, env_var, flag, pri_flags, logger, cast_type=None): |
| 96 | """Look for non-defined options in the environment and add to command line. |
| 97 | |
| 98 | If |env_var| is defined in the environment and none of the variables defined |
| 99 | in |pri_flags| are in the command line, then add --|flag| |$(env_var)| to |
| 100 | the command line. |
| 101 | |
| 102 | Notes: |
| 103 | - Modifies cmdline if name needs to be appended and an environment variable |
| 104 | is defined. |
| 105 | |
| 106 | Args: |
| 107 | cmdline: the list of cmdline arguments |
| 108 | env_var: environment variable name to search |
| 109 | flag: flag name to add the environment variable under |
| 110 | pri_flags: list of flags in the cmdline that have priority over the |
| 111 | environment variable. If any found, the environment variable |
| 112 | will not be pulled in. |
| 113 | logger: logger instance to use |
| 114 | cast_type: optional callable to verify the environment flag is castable |
| 115 | to a desired type |
| 116 | Returns: |
| 117 | tuple: (cmdline, flag_added) |
| 118 | cmdline - Reference back to the cmdline passed in |
| 119 | flag_added - True if the flag was added, or if a collision flag was |
| 120 | found, false otherwise |
| 121 | """ |
| 122 | if any(cl_flag in pri_flags for cl_flag in cmdline): |
| 123 | return (cmdline, True) |
| 124 | flag_added = False |
| 125 | # If port is not defined, attempt to retrieve it from the environment. |
| 126 | env_var_val = os.getenv(env_var) |
| 127 | if env_var_val: |
| 128 | try: |
| 129 | # Casting to int first to ensure the value is int-able and suitable |
| 130 | # to be a port option. |
| 131 | if cast_type: |
| 132 | cast_type(env_var_val) |
| 133 | cmdline.extend([flag, env_var_val]) |
| 134 | logger.info("Adding '--%s %s' to the cmdline.", flag, env_var_val) |
| 135 | flag_added = True |
| 136 | except ValueError: |
| 137 | logger.warning('Ignoring environment %r definition %r', env_var, |
| 138 | env_var_val) |
| 139 | return (cmdline, flag_added) |
| 140 | |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 141 | |
| 142 | class BaseServodParser(_BaseServodParser): |
| 143 | """BaseServodParser handling common arguments in the servod cmdline tools.""" |
| 144 | |
Ruben Rodriguez Buchillon | 0902f09 | 2018-09-19 15:03:17 +0800 | [diff] [blame] | 145 | def __init__(self, **kwargs): |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 146 | """Initialize by adding common arguments. |
| 147 | |
| 148 | Adds: |
| 149 | - host/port arguments to find/initialize a servod instance |
| 150 | - debug argument to toggle debug message printing |
| 151 | - name/rcfile arguments to handle servodrc configurations |
| 152 | |
| 153 | Args: |
Ruben Rodriguez Buchillon | 0902f09 | 2018-09-19 15:03:17 +0800 | [diff] [blame] | 154 | **kwargs: keyword arguments forwarded to _BaseServodParser |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 155 | """ |
Ruben Rodriguez Buchillon | 0902f09 | 2018-09-19 15:03:17 +0800 | [diff] [blame] | 156 | super(BaseServodParser, self).__init__(**kwargs) |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 157 | self.add_argument('-d', '--debug', action='store_true', default=False, |
| 158 | help='enable debug messages') |
| 159 | self.add_argument('--host', default='localhost', type=str, |
| 160 | help='hostname of the servod server.') |
| 161 | self.add_argument('-p', '--port', default=None, type=int, |
| 162 | help='port of the servod server.') |
| 163 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 164 | @staticmethod |
| 165 | def HandlePortEnvVar(cmdline=None, pri_flags=None, logger=logging): |
| 166 | """Probe SERVOD_PORT environment variable. |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 167 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 168 | SERVOD_PORT environment variable will be used if defined and port not in |
| 169 | the cmdline |
Ruben Rodriguez Buchillon | 0902f09 | 2018-09-19 15:03:17 +0800 | [diff] [blame] | 170 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 171 | Args: |
| 172 | cmdline: the list of cmdline arguments |
| 173 | pri_flags: list of flags in the cmdline that have priority over the |
| 174 | environment variable. If any found, the environment variable |
| 175 | will not be pulled in. |
| 176 | logger: logger instance to use |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 177 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 178 | Returns: |
| 179 | tuple: (cmdline, port_defined) |
| 180 | cmdline - Reference back to the cmdline passed in |
| 181 | port_defined - bool showing if after this port is now in the cmdline |
| 182 | """ |
| 183 | if not pri_flags: |
| 184 | pri_flags = ['-p', '--port'] |
| 185 | if cmdline is None: |
| 186 | cmdline = sys.argv[1:0] |
| 187 | return _BaseServodParser._HandleEnvVar(cmdline=cmdline, |
| 188 | env_var='SERVOD_PORT', flag='-p', |
| 189 | pri_flags=pri_flags, logger=logger, |
| 190 | cast_type=int) |
| 191 | |
| 192 | |
| 193 | class _ServodRCParser(_BaseServodParser): |
| 194 | """Base class to build Servod parsers to natively handle servorc. |
| 195 | |
| 196 | This class overwrites parse_args & parse_known_args to: |
| 197 | - handle SERVOD_NAME environment variable |
| 198 | - parse & substitute in the servorc file on matches |
| 199 | |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 200 | """ |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 201 | |
| 202 | def __init__(self, **kwargs): |
| 203 | super(_ServodRCParser, self).__init__(**kwargs) |
| 204 | self.add_argument('--rcfile', type=str, default=DEFAULT_RC_FILE, |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 205 | help='servo description file for multi-servo operation.') |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 206 | self.add_argument('-n', '--name', type=str, |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 207 | help='symbolic name of the servo board, ' |
| 208 | 'used as a config shortcut, could also be supplied ' |
| 209 | 'through environment variable SERVOD_NAME') |
| 210 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 211 | @staticmethod |
| 212 | def HandleNameEnvVar(cmdline=None, pri_flags=None, logger=logging): |
| 213 | """Probe SERVOD_NAME environment variable. |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 214 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 215 | SERVOD_NAME environment variables can be used if -s/--serialname |
| 216 | and --name command line switches are not set. |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 217 | |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 218 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 219 | Args: |
| 220 | cmdline: the list of cmdline arguments |
| 221 | pri_flags: list of flags in the cmdline that have priority over the |
| 222 | environment variable. If any found, the environment variable |
| 223 | will not be pulled in. |
| 224 | logger: logger instance to use |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 225 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 226 | Returns: |
| 227 | tuple: (cmdline, name_defined) |
| 228 | cmdline - Reference back to the cmdline passed in |
| 229 | name_defined - bool showing if name or serialname (a unique id) |
| 230 | is now defined in the cmdline |
| 231 | """ |
| 232 | if not pri_flags: |
| 233 | pri_flags = ['-n', '--name', '-s', '--serialname'] |
| 234 | if cmdline is None: |
| 235 | cmdline = sys.argv[1:0] |
| 236 | return _BaseServodParser._HandleEnvVar(cmdline=cmdline, |
| 237 | env_var='SERVOD_NAME', |
| 238 | flag='-n', pri_flags=pri_flags, |
| 239 | logger=logger) |
| 240 | |
| 241 | @staticmethod |
| 242 | def PostProcessRCElements(options, rcpath=None, logger=logging): |
| 243 | """Handle 'name' in |options| by substituting it with the intended config. |
| 244 | |
| 245 | This replaces the name option in the options with the intended serialname |
| 246 | for that name if one can be found. If a board file is also specified in the |
| 247 | rc file it appends that to the options too, which can be ignored if not |
| 248 | needed. |
| 249 | |
| 250 | Note: this function changes the content of options. |
| 251 | |
| 252 | Args: |
| 253 | options: argparse Namespace of options to process. |
| 254 | rcpath: optional rcfile path if it's not stored under options.rcfile |
| 255 | logger: logger instance to use |
| 256 | |
| 257 | Returns: |
| 258 | Reference back to the same options passed in. |
| 259 | |
| 260 | Raises: |
| 261 | ServodParserError: if -n/--name and -s/--serialname both defined |
| 262 | ServodParserError: if name in options doesn't show up in servodrc |
| 263 | """ |
| 264 | if options.name and options.serialname: |
| 265 | # NOTE(coconutruben): This is temporary until the CL that splits |
| 266 | # parsing inside of servod.py removes the need for this. |
| 267 | raise ServodParserError('error: argument -s/--serialname not allowed with' |
| 268 | ' argument -n/--name.') |
| 269 | if not rcpath: |
| 270 | rcpath = options.rcfile |
| 271 | rcd = _ServodRCParser.ParseRC(rcpath, logger=logger) |
| 272 | rc = None |
| 273 | if options.name: |
| 274 | if options.name not in rcd: |
| 275 | raise ServodParserError('Name %r not in rc at %r' % (options.name, |
| 276 | rcpath)) |
| 277 | rc = rcd[options.name] |
| 278 | if 'sn' in rc: |
| 279 | setattr(options, 'serialname', rc['sn']) |
| 280 | elif options.serialname: |
| 281 | # srcs meaning serialname runtime configurations (rcs). |
| 282 | srcs = [(name, rc) for name, rc in rcd.iteritems() if |
| 283 | rc['sn'] == options.serialname] |
| 284 | if srcs: |
| 285 | logger.info('Found servodrc entry %r for serialname %r. Using it.', |
| 286 | srcs[0][0], options.serialname) |
| 287 | rc = srcs[0][1] |
| 288 | if rc: |
| 289 | for elem in ['board', 'model']: |
| 290 | # Unlike serialname explicit overwrites of board and model in the |
| 291 | # cmdline are fine as the name flag is still useful to refer to a |
| 292 | # serialname. |
| 293 | if elem in rc and hasattr(options, elem): |
| 294 | if not getattr(options, elem): |
| 295 | logger.info('Setting %r to %r in the options as indicated by ' |
| 296 | 'servodrc file.', elem, rc[elem]) |
| 297 | setattr(options, elem, rc[elem]) |
| 298 | else: |
| 299 | if getattr(options, elem) != rc[elem]: |
| 300 | logger.warning('Ignoring rc configured %r name %r for servo %r. ' |
| 301 | 'Option already defined on the command line as %r', |
| 302 | elem, rc[elem], rc['sn'], getattr(options, elem)) |
| 303 | return options |
| 304 | |
| 305 | def parse_known_args(self, args=None, namespace=None): |
| 306 | """Overwrite from Argumentparser to handle servo rc. |
| 307 | |
| 308 | Note: this also overwrites parse_args as parse_args just calls |
| 309 | parse_known_args and throws an error if there's anything inside of |
| 310 | xtra. |
| 311 | |
| 312 | Args: |
| 313 | args: list of cmdline elements |
| 314 | namespace: namespace to place the results into |
| 315 | |
| 316 | Returns: |
| 317 | tuple (options, xtra) the result from parsing known args |
| 318 | """ |
| 319 | args, _ = _ServodRCParser.HandleNameEnvVar(args, logger=self._logger) |
| 320 | result = super(_ServodRCParser, self).parse_known_args(args=args, |
| 321 | namespace=namespace) |
| 322 | opts, xtra = result |
| 323 | opts = _ServodRCParser.PostProcessRCElements(opts, logger=self._logger) |
| 324 | return (opts, xtra) |
| 325 | |
| 326 | @staticmethod |
| 327 | def ParseRC(rc_file, logger=logging): |
| 328 | """Parse servodrc configuration file. |
| 329 | |
| 330 | The format of the configuration file is described above in comments to |
| 331 | DEFAULT_RC_FILE. If the file is not found or is mis-formatted, a warning is |
| 332 | printed but the program tries to continue. |
| 333 | |
| 334 | Args: |
| 335 | rc_file: a string, name of the file storing the configuration |
| 336 | logger: logger instance to use |
| 337 | |
| 338 | Returns: |
| 339 | a dictionary, where keys are symbolic servo names, and values are |
| 340 | dictionaries representing servo parameters read from the config file, |
| 341 | keyed by strings 'sn' (for serial number), 'port', 'board', and 'model'. |
| 342 | """ |
| 343 | |
| 344 | if not os.path.isfile(rc_file): |
| 345 | return {} |
| 346 | rcd = {} # Dictionary representing the rc file contents. |
| 347 | other_attributes = ['port', 'board', 'model'] |
| 348 | with open(rc_file) as f: |
| 349 | for rc_line in f: |
| 350 | line = rc_line.split('#')[0].strip() |
| 351 | if not line: |
| 352 | continue |
| 353 | elts = [x.strip() for x in line.split(',')] |
| 354 | name = elts[0] |
| 355 | if not name or len(elts) < 2 or any(' ' in x for x in elts): |
| 356 | logger.warning('ignoring rc line %r', rc_line.rstrip()) |
| 357 | continue |
| 358 | rcd[name] = {'sn': elts[1]} |
| 359 | # Initialize all to None |
| 360 | rcd[name].update({att: None for att in other_attributes}) |
| 361 | rcd[name].update(dict(zip(other_attributes, elts[2:]))) |
| 362 | # +2 comes from name & serialname |
| 363 | if len(elts) > len(other_attributes) + 2: |
| 364 | extra_info = elts[len(other_attributes) + 2:] |
| 365 | logger.warning('discarding %r for for %r', ', '.join(extra_info), |
| 366 | name) |
| 367 | return rcd |
| 368 | |
| 369 | |
| 370 | class BaseServodRCParser(_ServodRCParser): |
| 371 | """BaseServodParser extension to also natively handle servo rc config.""" |
| 372 | |
| 373 | def __init__(self, **kwargs): |
| 374 | """Create a ServodRCParser that has the BaseServodParser args. |
| 375 | |
| 376 | Args: |
| 377 | **kwargs: keyword arguments forwarded to _BaseServodParser |
| 378 | """ |
| 379 | base_parser = BaseServodParser(add_help=False) |
| 380 | if 'parents' not in kwargs: |
| 381 | kwargs['parents'] = [] |
| 382 | kwargs['parents'].append(base_parser) |
| 383 | super(BaseServodRCParser, self).__init__(**kwargs) |
| 384 | |
| 385 | |
| 386 | class ServodClientParser(BaseServodRCParser): |
| 387 | """Parser to use for servod client cmdline tools. |
| 388 | |
| 389 | This parser adds servoscratch serialname<>port conversion to allow |
| 390 | for servod client cmdline tools to address servod using a servo device's |
| 391 | serialname as well. |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 392 | """ |
| 393 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 394 | def __init__(self, **kwargs): |
| 395 | """Create a ServodRCParser that has the BaseServodParser args. |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 396 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 397 | Args: |
| 398 | **kwargs: keyword arguments forwarded to _BaseServodParser |
| 399 | """ |
| 400 | super(ServodClientParser, self).__init__(**kwargs) |
| 401 | self.add_argument('-s', '--serialname', default=None, type=str, |
| 402 | help='device serialname stored in eeprom. Ignored ' |
| 403 | 'if port is already defined.') |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 404 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 405 | def _MapSNToPort(self, opts): |
| 406 | """Helper to map the serialname in opts to the port its running on. |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 407 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 408 | Args: |
| 409 | opts: ArgumentParser Namespace after parsing. |
Ruben Rodriguez Buchillon | 63e3860 | 2018-09-19 10:36:58 +0800 | [diff] [blame] | 410 | |
Ruben Rodriguez Buchillon | 9066239 | 2018-09-19 16:28:38 +0800 | [diff] [blame^] | 411 | Returns: |
| 412 | opts: reference back to passed in opts |
| 413 | |
| 414 | Raises: |
| 415 | Forces a program exit if |opts.serialname| is not found in the servo |
| 416 | scratch |
| 417 | """ |
| 418 | scratch = servodutil.ServoScratch() |
| 419 | try: |
| 420 | entry = scratch.FindById(opts.serialname) |
| 421 | except servodutil.ServodUtilError: |
| 422 | self.error('No servod instance running for device with serialname: %r' % |
| 423 | opts.serialname) |
| 424 | opts.port = int(entry['port']) |
| 425 | return opts |
| 426 | |
| 427 | def parse_known_args(self, args=None, namespace=None): |
| 428 | """Overwrite from Argumentparser to handle servo scratch logic. |
| 429 | |
| 430 | If port is not defined and serialname is defined, and serialname has |
| 431 | no scratch entry, this will raise an error & terminate the program. |
| 432 | |
| 433 | If there was neither a serialname nor a port, set the port to the |
| 434 | default port. |
| 435 | |
| 436 | Note: this also overwrites parse_args as parse_args just calls |
| 437 | parse_known_args and throws an error if there's anything inside of |
| 438 | xtra. |
| 439 | |
| 440 | Args: |
| 441 | args: list of cmdline elements |
| 442 | namespace: namespace to place the results into |
| 443 | |
| 444 | Returns: |
| 445 | tuple (opts, xtra) the result from parsing known args |
| 446 | """ |
| 447 | args, _ = BaseServodParser.HandlePortEnvVar(args, logger=self._logger) |
| 448 | rslt = super(ServodClientParser, self).parse_known_args(args=args, |
| 449 | namespace=namespace) |
| 450 | opts, xtra = rslt |
| 451 | if not opts.port and opts.serialname: |
| 452 | # only overwrite the port if no port explicitly set |
| 453 | opts = self._MapSNToPort(opts) |
| 454 | if not opts.port: |
| 455 | opts.port = client.DEFAULT_PORT |
| 456 | return (opts, xtra) |