def add_exception(self, exname, extype, exmsg):
if not isinstance(exname, str):<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>number = True<EOL>try:<EOL><INDENT>int(exname)<EOL><DEDENT>except ValueError:<EOL><INDENT>number = False<EOL><DEDENT>if number:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>if not isinstance(exmsg, str):<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>msg = "<STR_LIT>"<EOL>try:<EOL><INDENT>raise extype(exmsg)<EOL><DEDENT>except Exception as eobj:<EOL><INDENT>msg = _get_ex_msg(eobj)<EOL><DEDENT>if msg != exmsg:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>func_id, func_name = self._get_ex_data()<EOL>if func_id not in self._ex_dict:<EOL><INDENT>self._ex_dict[func_id] = {}<EOL><DEDENT>key = (extype, exmsg)<EOL>exname = "<STR_LIT>".format(func_id, self._callables_separator, exname)<EOL>entry = self._ex_dict[func_id].get(<EOL>key, {"<STR_LIT>": [], "<STR_LIT:name>": exname, "<STR_LIT>": []}<EOL>)<EOL>if func_name not in entry["<STR_LIT>"]:<EOL><INDENT>entry["<STR_LIT>"].append(func_name)<EOL>entry["<STR_LIT>"].append(False)<EOL><DEDENT>self._ex_dict[func_id][key] = entry<EOL>return (func_id, key, func_name)<EOL>
r"""
        Add an exception to the handler.

        :param exname: Exception name; has to be unique within the namespace,
                       duplicates are eliminated
        :type  exname: non-numeric string

        :param extype: Exception type; *must* be derived from the `Exception
                       <https://docs.python.org/2/library/exceptions.html#
                       exceptions.Exception>`_ class
        :type  extype: Exception type object, i.e. RuntimeError, TypeError,
                       etc.

        :param exmsg: Exception message; it can contain fields to be replaced
                      when the exception is raised via
                      :py:meth:`pexdoc.ExHandle.raise_exception_if`.
                      A field starts with the characters :code:`'\*['` and
                      ends with the characters :code:`']\*'`, the field name
                      follows the same rules as variable names and is between
                      these two sets of characters. For example,
                      :code:`'\*[fname]\*'` defines the fname field
        :type  exmsg: string

        :rtype: tuple

        The returned tuple has the following items:

          * **callable id** (string) first returned item, identification (as
            reported by the `id
            <https://docs.python.org/2/library/functions.html#id>`_ built-in
            function) of the callable where the exception was added

          * **exception definition** (tuple), second returned item, first item
            is the exception type and the second item is the exception message

          * **callable name** (string), third returned item, callable full
            name (encoded with the :py:meth:`ExHandle.encode_call` method

        :raises:
         * RuntimeError (Argument \`exmsg\` is not valid)

         * RuntimeError (Argument \`exname\` is not valid)

         * RuntimeError (Argument \`extype\` is not valid)