def __compute_mode_from_string(self, path, mode_string):
Char_to_perm_byte = {'<STR_LIT:r>': <NUM_LIT:4>, '<STR_LIT:w>': <NUM_LIT:2>, '<STR_LIT:x>': <NUM_LIT:1>}<EOL>Fields = (('<STR_LIT:u>', <NUM_LIT:6>), ('<STR_LIT:g>', <NUM_LIT:3>), ('<STR_LIT:o>', <NUM_LIT:0>))<EOL>m = re.match(r"<STR_LIT>", mode_string)<EOL>if not m:<EOL><INDENT>raise ValueError("<STR_LIT>" % mode_string)<EOL><DEDENT>who = m.group(<NUM_LIT:1>)<EOL>what_op = m.group(<NUM_LIT:2>)<EOL>which_perm = m.group(<NUM_LIT:3>)<EOL>old_mode = self.fs.get_path_info(path)['<STR_LIT>']<EOL>op_perm = [<EOL>reduce(ops.ior, [Char_to_perm_byte[c] for c in which_perm])<EOL>] * <NUM_LIT:3><EOL>if '<STR_LIT:a>' in who:<EOL><INDENT>who = '<STR_LIT>'<EOL><DEDENT>elif who == '<STR_LIT>':<EOL><INDENT>who = '<STR_LIT>'<EOL>inverted_umask = ~self.__get_umask()<EOL>for i, field in enumerate(Fields):<EOL><INDENT>op_perm[i] &= (inverted_umask >> field[<NUM_LIT:1>]) & <NUM_LIT><EOL><DEDENT><DEDENT>new_mode = <NUM_LIT:0><EOL>for i, tpl in enumerate(Fields):<EOL><INDENT>field, shift = tpl<EOL>old = (old_mode >> shift) & <NUM_LIT><EOL>if field in who:<EOL><INDENT>if what_op == '<STR_LIT:->':<EOL><INDENT>new = old & ~op_perm[i]<EOL><DEDENT>elif what_op == '<STR_LIT:=>':<EOL><INDENT>new = op_perm[i]<EOL><DEDENT>elif what_op == '<STR_LIT:+>':<EOL><INDENT>new = old | op_perm[i]<EOL><DEDENT>else:<EOL><INDENT>raise RuntimeError(<EOL>"<STR_LIT>" % what_op<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>new = old<EOL><DEDENT>new_mode |= new << shift<EOL><DEDENT>return new_mode<EOL>
Scan a unix-style mode string and apply it to ``path``.

:type mode_string: str
:param mode_string: see ``man chmod`` for details. ``X``, ``s``
  and ``t`` modes are not supported.  The string should match the
  following regular expression: ``[ugoa]*[-+=]([rwx]*)``.
:rtype: int
:return: a new mode integer resulting from applying ``mode_string``
  to ``path``.
:raises: :exc:`~exceptions.ValueError` if ``mode_string`` is invalid.