def parse(self, raw_args=None):
        """Parse the raw arguments.

        :param raw_args: raw arguments
        :type raw_args: a list or a str
        :rtype: double-tuple: (pargs, kargs)

        .. versionadded:: 0.1.5

        Here are examples:

        >>> def repeat(message, times=2, count=False):
        ...     '''It repeats the message.
        ...
        ...     -m=<str>, --message=<str>  The description of this option.
        ...     -t=<int>, --times=<int>
        ...     -c, --count
        ...     '''
        ...     s = message * times
        ...     return len(s) if count else s
        ...
        >>> repeat('string', 3)
        'stringstringstring'

        Make a :class:`~clime.core.Command` instance:

        >>> repeat_cmd = Command(repeat)
        >>> repeat_cmd.build_usage()
        'repeat [-t <int> | --times=<int>] [-c | --count] <message>'
        >>> repeat_cmd.execute('Hi!')
        'Hi!Hi!'

        You can also use options (keyword arguments) to assign arguments
        (positional arguments):

        >>> repeat_cmd.execute('--message=Hi!')
        'Hi!Hi!'
        >>> repeat_cmd.execute('--message Hi!')
        'Hi!Hi!'

        The short version defined in docstring:

        >>> repeat_cmd.execute('-mHi!')
        'Hi!Hi!'
        >>> repeat_cmd.execute('-m=Hi!')
        'Hi!Hi!'
        >>> repeat_cmd.execute('-m Hi!')
        'Hi!Hi!'

        It counts how many times options appear, if you don't specify a value:

        >>> repeat_cmd.execute('--times=4 Hi!')
        'Hi!Hi!Hi!Hi!'
        >>> repeat_cmd.execute('Hi! -tttt')
        'Hi!Hi!Hi!Hi!'
        >>> repeat_cmd.execute('-ttttm Hi!')
        'Hi!Hi!Hi!Hi!'

        However, if a default value is a boolean, it just switches the boolean
        value and does it only one time.

        Mix them all:

        >>> repeat_cmd.execute('-tttt --count Hi!')
        12
        >>> repeat_cmd.execute('-ttttc Hi!')
        12
        >>> repeat_cmd.execute('-ttttcc Hi!')
        12
        >>> repeat_cmd.execute('-ttccttm Hi!')
        12

        It is also supported to collect arbitrary arguments:

        >>> def everything(*args, **kargs):
        ...     return args, kargs

        >>> everything_cmd = Command(everything)
        >>> everything_cmd.build_usage()
        'everything [--<key>=<value>...] [<args>...]'

        >>> everything_cmd.execute('1 2 3')
        ((1, 2, 3), {})

        >>> everything_cmd.execute('--x=1 --y=2 --z=3')
        ((), {'y': 2, 'x': 1, 'z': 3})
        """

        if raw_args is None:
            raw_args = sys.argv[1:]
        elif isinstance(raw_args, str):
            raw_args = raw_args.split()

        # collect arguments from the raw arguments

        pargs = []
        kargs = defaultdict(list)

        # consume raw_args
        while raw_args:

            # try to find `arg_name` and `val`
            arg_name = None
            val = Empty

            # '-a...', '--arg...', but no '-'
            if raw_args[0].startswith('-') and len(raw_args[0]) >= 2:

                # partition by eq sign
                # -m=hello
                # --message=hello -> val='hello'
                # --message=      -> val=''
                # --bool          -> val=Empty
                before_eq_str, eq_str, val = raw_args.pop(0).partition('=')
                if not eq_str:
                    val = Empty

                if before_eq_str.startswith('--'):
                    arg_name = self.dealias(before_eq_str[2:].replace('-', '_'))
                else:

                    # if it starts with only '-', it may be various

                    # find the start index (sep) of val
                    # '-nnn'       -> sep=4 (the length of this str)
                    # '-nnnmhello' -> sep=5 (the char 'h')
                    sep = 1
                    for c in before_eq_str[1:]:
                        if c in self.arg_name_set or c in self.alias_arg_map:
                            sep += 1
                        else:
                            break

                    # handle the bool option sequence
                    # '-nnn'       -> 'nn'
                    # '-nnnmhello' -> 'nnn'
                    for c in before_eq_str[1:sep-1]:
                        arg_name = self.dealias(c)
                        kargs[arg_name].append(Empty)

                    # handle the last option
                    # '-nnn'       -> 'n' (the 3rd n)
                    # '-nnnmhello' -> 'm'
                    arg_name = self.dealias(before_eq_str[sep-1])

                    if val is Empty:
                        val = before_eq_str[sep:] or Empty

                # handle if the val is next raw_args
                # --message hello
                # --bool hello (note the hello shall be a pargs)
                # -nnnm hello
                # -nnnb hello
                if (
                    # didn't get val
                    val is Empty and
                    # this arg_name need a explicit val
                    not isinstance(self.arg_default_map.get(arg_name), bool) and
                    # we have thing to take
                    raw_args and not raw_args[0].startswith('-')
                ):
                    val = raw_args.pop(0)
            else:
                val = raw_args.pop(0)

            if arg_name:
                kargs[arg_name].append(val)
            else:
                pargs.append(val)

        # compact the collected kargs
        kargs = dict(kargs)
        for arg_name, collected_vals in kargs.items():
            default = self.arg_default_map.get(arg_name)
            if isinstance(default, bool):
                # switch the boolean value if default is a bool
                kargs[arg_name] = not default
            elif all(val is Empty for val in collected_vals):
                if isinstance(default, int):
                    kargs[arg_name] = len(collected_vals)
                else:
                    kargs[arg_name] = None
            else:
                # take the last value
                val = next(val for val in reversed(collected_vals) if val is not Empty)
                # cast this key arg
                if not self.keyarg_name or arg_name in self.arg_meta_map:
                    kargs[arg_name] = self.cast(arg_name, val)
                else:
                    kargs[arg_name] = self.cast(self.keyarg_name, val)

        # add the defaults to kargs
        for arg_name, default in self.arg_default_map.items():
            if arg_name not in kargs:
                kargs[arg_name] = default

        # keyword-first resolving
        isbuiltin = inspect.isbuiltin(self.func)
        for pos, name in enumerate(self.arg_names):
            if name in kargs and (pos < len(pargs) or isbuiltin):
                pargs.insert(pos, kargs.pop(name))

        # cast the pos args
        for i, parg in enumerate(pargs):
            if i < self.no_defult_args_len:
                pargs[i] = self.cast(self.arg_names[i], parg)
            elif self.vararg_name:
                pargs[i] = self.cast(self.vararg_name, parg)

        return (pargs, kargs)
dataset/ETHPy150Open moskytw/clime/clime/core.py/Command.parse/original