25 from robot.errors import DataError, Information, FrameworkError
28 from .encoding
import console_decode, system_decode
29 from .filereader
import FileReader
30 from .misc
import plural_or_not
31 from .robottypes
import is_falsy, is_integer, is_string
35 lexer = shlex.shlex(args, posix=
True)
38 lexer.escapedquotes =
'"\''
40 lexer.whitespace_split =
True
43 except ValueError
as err:
44 raise ValueError(
"Parsing '%s' failed: %s" % (args, err))
51 _opt_line_re = re.compile(
r'''
52 ^\s{1,4} # 1-4 spaces in the beginning of the line
53 ((-\S\s)*) # all possible short options incl. spaces (group 1)
54 --(\S{2,}) # required long option (group 3)
55 (\s\S+)? # optional value (group 4)
56 (\s\*)? # optional '*' telling option allowed multiple times (group 5)
64 def __init__(self, usage, name=None, version=None, arg_limits=None,
65 validator=None, env_options=None, auto_help=True,
66 auto_version=True, auto_pythonpath='DEPRECATED',
67 auto_argumentfile=True):
70 self.
namename = name
or usage.splitlines()[0].split(
' -- ')[0].strip()
78 if auto_pythonpath ==
'DEPRECATED':
79 auto_pythonpath =
False
81 warnings.warn(
"ArgumentParser option 'auto_pythonpath' is deprecated "
82 "since Robot Framework 5.0.", DeprecationWarning)
141 raise DataError(
"Using '--argumentfile' option in shortened format "
142 "like '--argumentf' is not supported.")
146 opts, args = self.
_validator_validator(opts, args)
157 if self.
_auto_help_auto_help
and opts.get(
'help'):
162 sys.path = self.
_get_pythonpath_get_pythonpath(opts[
'pythonpath']) + sys.path
163 for auto, opt
in [(self.
_auto_help_auto_help,
'help'),
167 if auto
and opt
in opts:
175 except getopt.GetoptError
as err:
180 if not opt.startswith(
'--'):
184 opt, value = opt.split(
'=', 1)
185 return '%s=%s' % (opt.lower(), value)
188 options = [
'--argumentfile']
189 for short_opt, long_opt
in self.
_short_to_long_short_to_long.items():
190 if long_opt ==
'argumentfile':
191 options.append(
'-'+short_opt)
196 for name, value
in opt_tuple:
199 opts[name].append(value)
202 elif name.startswith(
'no')
and name[2:]
in self.
_flag_opts_flag_opts:
203 opts[name[2:]] =
False
211 opt = opt.rstrip(
'=')
212 if opt.startswith(
'no')
and opt[2:]
in self.
_flag_opts_flag_opts:
214 defaults[opt] = []
if opt
in self.
_multi_opts_multi_opts
else None
220 paths = sorted(glob.glob(path))
228 name = name.lstrip(
'-')
235 for line
in usage.splitlines():
238 self.
_create_option_create_option(short_opts=[o[1]
for o
in res.group(1).split()],
239 long_opt=res.group(3).lower(),
240 takes_arg=bool(res.group(4)),
241 is_multi=bool(res.group(5)))
245 for sopt
in short_opts:
253 short_opts = [sopt+
':' for sopt
in short_opts]
255 if long_opt.startswith(
'no'):
256 long_opt = long_opt[2:]
257 self.
_long_opts_long_opts.append(
'no' + long_opt)
260 self.
_short_opts_short_opts += (
''.join(short_opts))
264 if opt.startswith(
'no'):
268 elif opt
in [o.rstrip(
'=')
for o
in self.
_long_opts_long_opts]:
276 temp.extend(glob.glob(path))
277 return [os.path.abspath(path)
for path
in temp
if path]
281 tokens =
':'.join(paths).split(
':')
288 item = item.replace(
'/',
'\\')
289 if drive
and item.startswith(
'\\'):
290 ret.append(
'%s:%s' % (drive, item))
296 if len(item) == 1
and item
in string.ascii_letters:
307 usage = usage.replace(
'<VERSION>', self.
versionversion)
323 if arg_limits
is None:
324 return 0, sys.maxsize
326 return arg_limits, arg_limits
327 if len(arg_limits) == 1:
328 return arg_limits[0], sys.maxsize
329 return arg_limits[0], arg_limits[1]
332 if not (self._min_args <= len(args) <= self.
_max_args_max_args):
337 if min_args == max_args:
338 expectation =
"%d argument%s" % (min_args, min_end)
339 elif max_args != sys.maxsize:
340 expectation =
"%d to %d arguments" % (min_args, max_args)
342 expectation =
"at least %d argument%s" % (min_args, min_end)
343 raise DataError(
"Expected %s, got %d." % (expectation, arg_count))
353 path, replace = self.
_get_index_get_index(args)
356 args[replace] = self.
_get_args_get_args(path)
361 start = opt +
'=' if opt.startswith(
'--')
else opt
362 for index, arg
in enumerate(args):
363 normalized_arg = arg.lower()
if opt.startswith(
'--')
else arg
365 if normalized_arg == opt
and index + 1 < len(args):
366 return args[index+1], slice(index, index+2)
368 if normalized_arg.startswith(start):
369 return arg[len(start):], slice(index, index+1)
373 if path.upper() !=
'STDIN':
383 except (IOError, UnicodeError)
as err:
384 raise DataError(
"Opening argument file '%s' failed: %s"
392 for line
in content.splitlines():
394 if line.startswith(
'-'):
396 elif line
and not line.startswith(
'#'):
404 option, value = line.split(separator, 1)
406 value = value.strip()
407 return [option, value]
410 if ' ' not in line
and '=' not in line:
416 return ' ' if line.index(
' ') < line.index(
'=')
else '='
Can be used when the core framework goes to unexpected state.
def _read_from_stdin(self)
def _read_from_file(self, path)
def _process_file(self, content)
def __init__(self, options)
def _get_index(self, args)
def _get_args(self, path)
def _get_option_separator(self, line)
def _split_option(self, line)
def _raise_invalid_args(self, min_args, max_args, arg_count)
def __init__(self, arg_limits)
def _parse_arg_limits(self, arg_limits)
def _split_pythonpath(self, paths)
def _create_options(self, usage)
def _verify_long_not_already_used(self, opt, flag=False)
def _parse_args(self, args)
def _create_option(self, short_opts, long_opt, takes_arg, is_multi)
def _get_name(self, name)
def parse_args(self, args)
Parse given arguments and return options and positional arguments.
def _glob_args(self, args)
def _process_opts(self, opt_tuple)
def _get_pythonpath(self, paths)
def _raise_option_multiple_times_in_usage(self, opt)
def _get_default_opts(self)
def _handle_special_options(self, opts, args)
def _lowercase_long_option(self, opt)
def _get_env_options(self)
def __init__(self, usage, name=None, version=None, arg_limits=None, validator=None, env_options=None, auto_help=True, auto_version=True, auto_pythonpath='DEPRECATED', auto_argumentfile=True)
Available options and tool name are read from the usage.
def _process_possible_argfile(self, args)
Utility to ease reading different kind of files.
def cmdline2list(args, escaping=False)
def console_decode(string, encoding=CONSOLE_ENCODING)
Decodes bytes from console encoding to Unicode.
def system_decode(string)
def is_falsy(item)
Opposite of :func:is_truthy.
def get_full_version(program=None, naked=False)