aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2017-10-19 16:14:58 +0200
committerMattias Andrée <maandree@kth.se>2017-10-19 16:14:58 +0200
commitb147896d43c04c79f66c0352eb53a99614d1a976 (patch)
tree0be1cf838463e6279f7074e003235298c5295a16
downloadpython-arg-cec75f4d1a4de7949ff5225c72adb3ef5f2a5196.tar.gz
python-arg-cec75f4d1a4de7949ff5225c72adb3ef5f2a5196.tar.bz2
python-arg-cec75f4d1a4de7949ff5225c72adb3ef5f2a5196.tar.xz
First commit1.0
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--.gitignore5
-rw-r--r--LICENSE15
-rw-r--r--Makefile26
-rw-r--r--README42
-rw-r--r--arg.py307
-rwxr-xr-xtest.py536
6 files changed, 931 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8a0b878
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*~
+*\#*
+__pycache__/
+*.pyc
+*.pyo
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..2553a69
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+© 2017 Mattias Andrée <maandree@kth.se>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..50ede37
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,26 @@
+.POSIX:
+
+PREFIX = /usr/local
+
+PYTHON_MAJOR = $$(python --version 2>&1 | cut -d . -f 1 | cut -d ' ' -f 2)
+PYTHON_MINOR = $$(python$(PYTHON_MAJOR) --version 2>&1 | cut -d . -f 2)
+
+all:
+ @true
+
+check:
+ python$(PYTHON_MAJOR) ./test.py
+
+install:
+ mkdir -p -- "$(DESTDIR)$(PREFIX)/lib/python$(PYTHON_MAJOR).$(PYTHON_MINOR)/site-packages"
+ cp -- arg.py "$(DESTDIR)$(PREFIX)/lib/python$(PYTHON_MAJOR).$(PYTHON_MINOR)/site-packages/"
+
+uninstall:
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/python$(PYTHON_MAJOR).$(PYTHON_MINOR)/site-packages/arg.py"
+
+clean:
+ -rm -rf -- *.pyc *.pyo __pycache__
+
+.SUFFIXES:
+
+.PHONY: all check install uninstall clean
diff --git a/README b/README
new file mode 100644
index 0000000..dd091db
--- /dev/null
+++ b/README
@@ -0,0 +1,42 @@
+A simple argument parser for Python
+
+Example usage:
+ import sys
+ import arg
+
+ def usage():
+ print('usage: %s [-v value] [-xy]' % sys.argv[0], file = sys.stderr)
+ sys.exit(1)
+
+ xflag = False
+ yflag = False
+ vflag = None
+
+ parser = arg.Parser(usage = usage)
+ for c in parser.flags:
+ if c == 'x':
+ xflag = True
+ elif c == 'y':
+ yflag = True
+ elif c == 'v':
+ vflag = parser.arg
+ else:
+ usage()
+
+Supports:
+ Short flags without arguments
+ Short flags with optionally attached arguments
+ Joined short flags
+ Long flags with optional arguments
+ Long flags with mandatory arguments
+ Long flags with mandatory attached arguments
+ Long flags with mandatory detached arguments
+ Long flags with without arguments
+ Long flags with only one dash
+ Flags not starting with a dash
+ Numeral flags
+ Stop parsing flags at --
+ Mixing flags and arguments
+ Stop parsing flags at first argument
+ Returning -- as an argument
+ Not returning -- as an argument
diff --git a/arg.py b/arg.py
new file mode 100644
index 0000000..bb83df1
--- /dev/null
+++ b/arg.py
@@ -0,0 +1,307 @@
+# See LICENSE file for copyright and license details.
+# -*- coding: utf-8 -*-
+
+from __future__ import print_function
+import sys as _sys
+import os as _os
+import errno as _errno
+
+MAY_HAVE_ATTACHED_ARGUMENT = 0
+NEED_ARGUMENT = 1
+NEED_ATTACHED_ARGUMENT = 2
+NEED_DETACHED_ARGUMENT = 3
+NEED_NO_ARGUMENT = 4
+
+class UsageError(Exception):
+ pass
+
+class Parser(object):
+ '''
+ Command line parser
+
+ Example usage:
+ import sys
+ import arg
+
+ def usage():
+ print('usage: %s [-v value] [-xy]' % sys.argv[0], file = sys.stderr)
+ sys.exit(1)
+
+ xflag = False
+ yflag = False
+ vflag = None
+
+ parser = arg.Parser(usage = usage)
+ for c in parser.flags:
+ if c == 'x':
+ xflag = True
+ elif c == 'y':
+ yflag = True
+ elif c == 'v':
+ vflag = parser.arg
+ else:
+ usage()
+ '''
+
+ def __init__(self, argv = None, symbols = '-', keep_dashdash = False, store_nonflags = False, usage = None):
+ '''
+ @param argv A list with the arguments to parse, if `None`, `sys.argv[1:]` is used
+ @param symbols A string or list contain the characters that will cause an argument
+ to be parsed as being a flag, multicharacter strings will be ignored
+ @param keep_dashdash If `True`, `--` will be returned in `self.argv`
+ @param keep_nonflags During parsing, non-flag arguments are ignored, and after the last
+ flag has been parsed, `self.argv` will have the ignored arguments at
+ the beginning
+ @param usage Function (without arguments) that is to be called if parsing fails
+ due to usage error, if `None`, `UsageError` will be raised instead
+ on usage error
+ '''
+ if argv is None:
+ argv = _sys.argv[1:]
+ self._argv = list(argv)
+ self._usage_func = usage
+ self._symbols = symbols
+ self._keep_ddash = keep_dashdash
+ self._stored = [] if store_nonflags else None
+
+ def _usage(self):
+ if self._usage_func is None:
+ raise UsageError()
+ else:
+ self._usage_func()
+
+ @property
+ def flags(self):
+ '''
+ Return a generator that returns the flags in the command line
+
+ Properties and functions in `self` can be used to after each
+ time a flag is returned
+
+ Each returned value is a single character
+ '''
+ self._brk = False
+ self._accept_none_arg = False
+ while len(self._argv):
+ if len(self._argv[0]) < 2:
+ if self._stored is not None:
+ self._stored.append(self._argv[0])
+ self._argv = self._argv[1:]
+ continue
+ break
+ self._symbol = self._argv[0][0]
+ self._lflag = self._argv[0]
+ if self._symbol not in self._symbols:
+ if self._stored is not None:
+ self._stored.append(self._argv[0])
+ self._argv = self._argv[1:]
+ continue
+ break
+ if self._argv[0] == 2 * self._symbol:
+ if self._symbol == '-':
+ if not self._keep_ddash:
+ self._argv = self._argv[1:]
+ elif self._stored is not None:
+ self._stored.append(self._argv[0])
+ self._argv = self._argv[1:]
+ continue
+ break
+ self._i = 1
+ n = len(self._argv[0])
+ while self._i < n:
+ self._flag = self._argv[0][self._i]
+ if self._flag == self._symbol and self._i != 1:
+ self._usage()
+ if self._i + 1 < n:
+ self._arg = self._argv[0][self._i + 1:]
+ elif len(self._argv) > 1:
+ self._arg = self._argv[1]
+ else:
+ self._arg = None
+ yield self._flag
+ self._lflag = None
+ self._accept_none_arg = False
+ if self._brk:
+ if len(self._argv) > 1 and self._arg is self._argv[1]:
+ self._argv = self._argv[1:]
+ self._brk = False
+ break
+ self._i += 1
+ self._argv = self._argv[1:]
+ if self._stored:
+ self._argv = self._stored + self._argv
+ self._stored = None
+
+ @property
+ def flag(self):
+ '''
+ Return the current short flag, for example '-a',
+ this string is always two characters long
+ '''
+ return self._symbol + self._flag
+
+ @property
+ def symbol(self):
+ '''
+ Get the first character in the flag, normally '-'
+ '''
+ return self._symbol
+
+ @property
+ def lflag(self):
+ '''
+ Get the entire current argument, for example
+ '--mode=755', `None` not at the beginning
+ '''
+ return self._lflag
+
+ @property
+ def argv(self):
+ '''
+ Return a list of all remaining arguments
+ '''
+ return self._argv
+
+ @property
+ def argc(self):
+ '''
+ Return the number of remaining arguments
+ '''
+ return len(self._argv)
+
+ @property
+ def arg(self):
+ '''
+ Get the argument specified for the flag, can only be
+ `None` (no argument) if `self.testlong` has returned
+ `True` with `MAY_HAVE_ATTACHED_ARGUMENT` as the second
+ argument for the currnet flag
+
+ Reading this property will cause the parser to assume
+ that the flag should have an argument, if these is
+ no argument UsageError will be raised (or the specified
+ usage function will be called) unless `self.testlong`
+ has returned `True` with `MAY_HAVE_ATTACHED_ARGUMENT`
+ as the second argument for the currnet flag
+ '''
+ if self._arg is None and not self._accept_none_arg:
+ self._usage()
+ self._brk = True
+ return self._arg
+
+ @property
+ def arghere(self):
+ '''
+ Return the current argument with an offset such that the
+ first character is the character associated with the
+ current flag, for example, if the current argument is
+ '-123' and the current flag is '1', '123' is returned
+
+ Reading this property will cause the parser to continue
+ with the next argument when getting the next flag
+ '''
+ self._brk = True
+ self._arg = None
+ return self._argv[0][self._i:]
+
+ @property
+ def isargnum(self):
+ '''
+ Check whether the value returned by `arghere` will be a number
+
+ Calling this function does not affect the parser
+ '''
+ return self._argv[0][self._i:].isdigit()
+
+ @property
+ def argnum(self):
+ '''
+ Identical to `arghere`, except the returned value will
+ be converted to an integer
+
+ If the value returned by `self.arghere` is not a
+ number, UsageError will be raised (or the specified
+ usage function will be called)
+ '''
+ if not self.isargnum:
+ self._usage()
+ return int(self.arghere)
+
+ def consume(self):
+ '''
+ Cause the parser to skip the rest of current argument
+ and continue with the next argument
+
+ If `self.arg` has been read and returned the next argument,
+ the parser will still read that argument
+ '''
+ self._arg = None
+ self._brk = True
+
+ def testlong(self, flag, argument = 0):
+ '''
+ Check whether the current flag is specific long flag
+
+ It is important to use this function, because it will
+ set the parser's state appropriately whe it finds a match
+
+ If the flag is the specified long flag, but its argument
+ status does not match `argument`, UsageError will be raised
+ (or the specified usage function will be called)
+
+ @param flag The long flag, should start with its symbol prefix (usually '--')
+ @param argument arg.MAY_HAVE_ATTACHED_ARGUMENT (default):
+ The flag may have an argument attached to the flag
+ separated by a '=', for example '--value=2', but
+ it is not necessary, so just '--value' is also accepted,
+ but the next argument may not be parsed as a value
+ associated with the flag
+ arg.NEED_ARGUMENT:
+ The flag must have an attached argument or a detached
+ argument, for example '--value=2' is accepted, but
+ '--value' is only accepted if it is not the last argument,
+ if the current argument does not contain a '='
+ arg.NEED_ATTACHED_ARGUMENT:
+ The flag must have an attached argument, for example
+ '--value=2' is accepted but '--value' is not
+ arg.NEED_DETACHED_ARGUMENT:
+ The flag must have a detached argument, for example
+ '--value' is accepted, but only if it is not the last
+ argument, but '--value=2' is not accepted
+ arg.NEED_NO_ARGUMENT:
+ The flag must not have an argument, for example
+ '--value' is accepted but '--value=2' is not
+ '''
+ if self._lflag is None:
+ return False
+ attached = self._lflag.startswith(flag + '=')
+ if attached:
+ arg = self._lflag[self._lflag.index('=') + 1:]
+ lflag = self._lflag[:self._lflag.index('=')]
+ else:
+ arg = self._argv[1] if len(self._argv) > 1 else None
+ lflag = self._lflag
+ if lflag != flag:
+ return False
+ elif argument == MAY_HAVE_ATTACHED_ARGUMENT:
+ if not attached:
+ arg = None
+ self._accept_none_arg = True
+ elif argument == NEED_ARGUMENT:
+ if arg is None:
+ self._usage()
+ elif argument == NEED_ATTACHED_ARGUMENT:
+ if not attached:
+ self._usage()
+ elif argument == NEED_DETACHED_ARGUMENT:
+ if attached or arg is None:
+ self._usage()
+ elif argument == NEED_NO_ARGUMENT:
+ arg = None
+ if attached:
+ self._usage()
+ else:
+ raise OSError(_os.strerror(_errno.EINVAL), _errno.EINVAL)
+ self._arg = arg
+ self._brk = True
+ return True
diff --git a/test.py b/test.py
new file mode 100755
index 0000000..a58eaaa
--- /dev/null
+++ b/test.py
@@ -0,0 +1,536 @@
+#!/usr/bin/env python
+# See LICENSE file for copyright and license details.
+# -*- coding: utf-8 -*-
+
+import sys
+import arg
+
+
+parser = arg.Parser()
+assert parser.argv == sys.argv[1:]
+
+
+parser = arg.Parser(argv = ['-a', '-aa', '-aaa'])
+n = 0
+for c in parser.flags:
+ assert c == 'a'
+ n += 1
+assert n == 6
+assert type(parser.argv) is list
+assert len(parser.argv) == 0
+assert type(parser.argc) is int
+assert parser.argc == 0
+
+
+parser = arg.Parser(argv = ['-abc', '-xyz'])
+flags = parser.flags
+assert next(flags) == 'a'
+assert parser.flag == '-a'
+assert parser.symbol == '-'
+assert next(flags) == 'b'
+assert parser.flag == '-b'
+assert next(flags) == 'c'
+assert parser.flag == '-c'
+assert next(flags) == 'x'
+assert parser.flag == '-x'
+assert parser.lflag == '-xyz'
+assert next(flags) == 'y'
+assert parser.flag == '-y'
+assert parser.lflag is None
+assert next(flags) == 'z'
+assert parser.flag == '-z'
+assert parser.symbol == '-'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 0
+assert type(parser.argc) is int
+assert parser.argc == 0
+
+
+for mid in ('', '-', 'x'):
+ parser = arg.Parser(argv = ['-abc', mid, '-xyz'])
+ flags = parser.flags
+ assert next(flags) == 'a'
+ assert parser.flag == '-a'
+ assert parser.symbol == '-'
+ assert next(flags) == 'b'
+ assert parser.flag == '-b'
+ assert next(flags) == 'c'
+ assert parser.flag == '-c'
+ try:
+ next(flags)
+ assert False
+ except StopIteration:
+ pass
+ assert type(parser.argv) is list
+ assert len(parser.argv) == 2
+ assert type(parser.argc) is int
+ assert parser.argc == 2
+ assert parser.argv == [mid, '-xyz']
+
+
+parser = arg.Parser(argv = ['-abc', '--', '-xyz'])
+flags = parser.flags
+assert next(flags) == 'a'
+assert parser.flag == '-a'
+assert parser.symbol == '-'
+assert next(flags) == 'b'
+assert parser.flag == '-b'
+assert next(flags) == 'c'
+assert parser.flag == '-c'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 1
+assert type(parser.argc) is int
+assert parser.argc == 1
+assert parser.argv == ['-xyz']
+
+
+parser = arg.Parser(argv = ['-abc', '--', '-xyz'], keep_dashdash = True)
+flags = parser.flags
+assert next(flags) == 'a'
+assert parser.flag == '-a'
+assert parser.symbol == '-'
+assert next(flags) == 'b'
+assert parser.flag == '-b'
+assert next(flags) == 'c'
+assert parser.flag == '-c'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 2
+assert type(parser.argc) is int
+assert parser.argc == 2
+assert parser.argv == ['--', '-xyz']
+
+
+parser = arg.Parser(argv = ['a', '--', 'b'], keep_dashdash = True, store_nonflags = True)
+flags = parser.flags
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 3
+assert type(parser.argc) is int
+assert parser.argc == 3
+assert parser.argv == ['a', '--', 'b']
+
+
+parser = arg.Parser(argv = ['a', '--', 'b'], keep_dashdash = False, store_nonflags = True)
+flags = parser.flags
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 2
+assert type(parser.argc) is int
+assert parser.argc == 2
+assert parser.argv == ['a', 'b']
+
+
+parser = arg.Parser(argv = ['-a-b'])
+flags = parser.flags
+assert next(flags) == 'a'
+assert parser.flag == '-a'
+try:
+ next(flags)
+ assert False
+except arg.UsageError:
+ pass
+
+
+parser = arg.Parser(argv = ['-123', '-xyz'])
+flags = parser.flags
+assert next(flags) == '1'
+assert parser.flag == '-1'
+assert next(flags) == '2'
+assert parser.flag == '-2'
+assert next(flags) == '3'
+assert parser.flag == '-3'
+assert next(flags) == 'x'
+assert parser.flag == '-x'
+assert next(flags) == 'y'
+assert parser.flag == '-y'
+assert next(flags) == 'z'
+assert parser.flag == '-z'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 0
+assert type(parser.argc) is int
+assert parser.argc == 0
+
+
+parser = arg.Parser(argv = ['-123', '-xyz'])
+flags = parser.flags
+assert next(flags) == '1'
+assert parser.flag == '-1'
+assert parser.arghere == '123'
+assert parser.isargnum
+assert parser.argnum == 123
+assert next(flags) == 'x'
+assert parser.flag == '-x'
+assert next(flags) == 'y'
+assert parser.flag == '-y'
+assert next(flags) == 'z'
+assert parser.flag == '-z'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 0
+assert type(parser.argc) is int
+assert parser.argc == 0
+
+
+parser = arg.Parser(argv = ['-1', '-xyz'])
+flags = parser.flags
+assert next(flags) == '1'
+assert parser.flag == '-1'
+assert parser.arghere == '1'
+assert parser.isargnum
+assert parser.argnum == 1
+assert next(flags) == 'x'
+assert parser.flag == '-x'
+assert next(flags) == 'y'
+assert parser.flag == '-y'
+assert next(flags) == 'z'
+assert parser.flag == '-z'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 0
+assert type(parser.argc) is int
+assert parser.argc == 0
+
+
+parser = arg.Parser(argv = ['-ab', '--', '-xyz'], store_nonflags = True)
+flags = parser.flags
+assert next(flags) == 'a'
+assert parser.flag == '-a'
+assert next(flags) == 'b'
+assert parser.flag == '-b'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 1
+assert type(parser.argc) is int
+assert parser.argc == 1
+assert parser.argv == ['-xyz']
+
+
+parser = arg.Parser(argv = ['-ab', '--', '-xyz'], keep_dashdash = True, store_nonflags = True)
+flags = parser.flags
+assert next(flags) == 'a'
+assert parser.flag == '-a'
+assert next(flags) == 'b'
+assert parser.flag == '-b'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 2
+assert type(parser.argc) is int
+assert parser.argc == 2
+assert parser.argv == ['--', '-xyz']
+
+
+for mid in ('o', 'oo'):
+ parser = arg.Parser(argv = ['-ab', mid, '-xyz'], store_nonflags = True)
+ flags = parser.flags
+ assert next(flags) == 'a'
+ assert parser.flag == '-a'
+ assert next(flags) == 'b'
+ assert parser.flag == '-b'
+ assert next(flags) == 'x'
+ assert parser.flag == '-x'
+ assert next(flags) == 'y'
+ assert parser.flag == '-y'
+ assert next(flags) == 'z'
+ assert parser.flag == '-z'
+ try:
+ next(flags)
+ assert False
+ except StopIteration:
+ pass
+ assert type(parser.argv) is list
+ assert len(parser.argv) == 1
+ assert type(parser.argc) is int
+ assert parser.argc == 1
+ assert parser.argv == [mid]
+
+
+parser = arg.Parser(argv = ['-abc'], symbols = '+')
+flags = parser.flags
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 1
+assert type(parser.argc) is int
+assert parser.argc == 1
+assert parser.argv == ['-abc']
+
+
+parser = arg.Parser(argv = ['+xyz', '-abc'], symbols = '+')
+flags = parser.flags
+assert next(flags) == 'x'
+assert parser.flag == '+x'
+assert parser.symbol == '+'
+assert next(flags) == 'y'
+assert parser.flag == '+y'
+assert next(flags) == 'z'
+assert parser.flag == '+z'
+assert parser.symbol == '+'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 1
+assert type(parser.argc) is int
+assert parser.argc == 1
+assert parser.argv == ['-abc']
+
+
+parser = arg.Parser(argv = ['+xyz', '-abc'], symbols = '-+')
+flags = parser.flags
+assert next(flags) == 'x'
+assert parser.flag == '+x'
+assert parser.symbol == '+'
+assert next(flags) == 'y'
+assert parser.flag == '+y'
+assert next(flags) == 'z'
+assert parser.flag == '+z'
+assert parser.symbol == '+'
+assert next(flags) == 'a'
+assert parser.flag == '-a'
+assert parser.symbol == '-'
+assert next(flags) == 'b'
+assert parser.flag == '-b'
+assert next(flags) == 'c'
+assert parser.flag == '-c'
+assert parser.symbol == '-'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 0
+assert type(parser.argc) is int
+assert parser.argc == 0
+
+
+parser = arg.Parser(argv = ['+xyz', '++', '-abc'], symbols = '-+')
+flags = parser.flags
+assert next(flags) == 'x'
+assert parser.flag == '+x'
+assert parser.symbol == '+'
+assert next(flags) == 'y'
+assert parser.flag == '+y'
+assert next(flags) == 'z'
+assert parser.flag == '+z'
+assert parser.symbol == '+'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 2
+assert type(parser.argc) is int
+assert parser.argc == 2
+assert parser.argv == ['++', '-abc']
+
+
+parser = arg.Parser(argv = ['-123', '-xyz'])
+flags = parser.flags
+assert next(flags) == '1'
+assert parser.arg == '23'
+assert next(flags) == 'x'
+assert parser.flag == '-x'
+assert parser.arg == 'yz'
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 0
+assert type(parser.argc) is int
+assert parser.argc == 0
+
+
+for a in ('', '-x'):
+ parser = arg.Parser(argv = ['-1', a])
+ flags = parser.flags
+ assert next(flags) == '1'
+ assert parser.arg == a
+ try:
+ next(flags)
+ assert False
+ except StopIteration:
+ pass
+ assert type(parser.argv) is list
+ assert len(parser.argv) == 0
+ assert type(parser.argc) is int
+ assert parser.argc == 0
+
+
+parser = arg.Parser(argv = ['-123', '-xyz'])
+flags = parser.flags
+assert next(flags) == '1'
+parser.consume()
+assert next(flags) == 'x'
+parser.consume()
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 0
+assert type(parser.argc) is int
+assert parser.argc == 0
+
+
+parser = arg.Parser(argv = ['--123', 'x'])
+flags = parser.flags
+assert next(flags) == '-'
+assert not parser.testlong('--abc')
+assert parser.testlong('--123', arg.NEED_NO_ARGUMENT)
+try:
+ next(flags)
+ assert False
+except StopIteration:
+ pass
+assert type(parser.argv) is list
+assert len(parser.argv) == 1
+assert type(parser.argc) is int
+assert parser.argc == 1
+assert parser.argv == ['x']
+
+
+for check_arg in (True, False):
+ for arg_need in (arg.NEED_ARGUMENT, arg.NEED_DETACHED_ARGUMENT):
+ parser = arg.Parser(argv = ['--123', 'x'])
+ flags = parser.flags
+ assert next(flags) == '-'
+ assert not parser.testlong('--abc')
+ assert parser.testlong('--123', arg_need)
+ if check_arg:
+ assert parser.arg == 'x'
+ try:
+ next(flags)
+ assert False
+ except StopIteration:
+ pass
+ assert type(parser.argv) is list
+ assert len(parser.argv) == 0
+ assert type(parser.argc) is int
+ assert parser.argc == 0
+
+
+for check_arg in (True, False):
+ parser = arg.Parser(argv = ['--123=x'])
+ flags = parser.flags
+ assert next(flags) == '-'
+ assert not parser.testlong('--abc')
+ assert parser.testlong('--123', arg.NEED_ATTACHED_ARGUMENT)
+ if check_arg:
+ assert parser.arg == 'x'
+ try:
+ next(flags)
+ assert False
+ except StopIteration:
+ pass
+ assert type(parser.argv) is list
+ assert len(parser.argv) == 0
+ assert type(parser.argc) is int
+ assert parser.argc == 0
+
+
+parser = arg.Parser(argv = ['--123', 'x'])
+flags = parser.flags
+assert next(flags) == '-'
+assert not parser.testlong('--abc')
+try:
+ parser.testlong('--123', arg.NEED_ATTACHED_ARGUMENT)
+ assert False
+except arg.UsageError:
+ pass
+
+
+for a in ('x', ''):
+ parser = arg.Parser(argv = ['--123=' + a])
+ flags = parser.flags
+ assert next(flags) == '-'
+ assert not parser.testlong('--abc')
+ assert parser.testlong('--123', arg.MAY_HAVE_ATTACHED_ARGUMENT)
+ assert parser.arg == a
+ try:
+ next(flags)
+ assert False
+ except StopIteration:
+ pass
+ assert type(parser.argv) is list
+ assert len(parser.argv) == 0
+ assert type(parser.argc) is int
+ assert parser.argc == 0
+
+ parser = arg.Parser(argv = ['--123', a])
+ flags = parser.flags
+ assert next(flags) == '-'
+ assert not parser.testlong('--abc')
+ assert parser.testlong('--123', arg.MAY_HAVE_ATTACHED_ARGUMENT)
+ assert parser.arg == None
+ try:
+ next(flags)
+ assert False
+ except StopIteration:
+ pass
+ assert type(parser.argv) is list
+ assert len(parser.argv) == 1
+ assert type(parser.argc) is int
+ assert parser.argc == 1
+ assert parser.argv == [a]
+
+
+parser = arg.Parser(argv = ['-a-'], usage = lambda : sys.exit(0))
+flags = parser.flags
+assert next(flags) == 'a'
+assert parser.flag == '-a'
+next(flags)
+assert False