peng/functions.py
def remove_extra_delims(expr, ldelim="(", rdelim=")"):
    r"""
    Remove unnecessary delimiters in mathematical expressions.

    Delimiters (parenthesis, brackets, etc.) may be removed either because
    there are multiple consecutive delimiters enclosing a single expressions or
    because the delimiters are implied by operator precedence rules. Function
    names must start with a letter and then can contain alphanumeric characters
    and a maximum of one underscore

    :param expr: Mathematical expression
    :type  expr: string

    :param ldelim: Single character left delimiter
    :type  ldelim: string

    :param rdelim: Single character right delimiter
    :type  rdelim: string

    :rtype: string

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

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

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

     * RuntimeError (Function name `*[function_name]*` is not valid)

     * RuntimeError (Mismatched delimiters)
    """
    op_group = ""
    for item1 in _OP_PREC:
        if isinstance(item1, list):
            for item2 in item1:
                op_group += item2
        else:
            op_group += item1
    iobj = zip([expr, ldelim, rdelim], ["expr", "ldelim", "rdelim"])
    for item, desc in iobj:
        if not isinstance(item, str):
            raise RuntimeError("Argument `{0}` is not valid".format(desc))
    if (len(ldelim) != 1) or ((len(ldelim) == 1) and (ldelim in op_group)):
        raise RuntimeError("Argument `ldelim` is not valid")
    if (len(rdelim) != 1) or ((len(rdelim) == 1) and (rdelim in op_group)):
        raise RuntimeError("Argument `rdelim` is not valid")
    if expr.count(ldelim) != expr.count(rdelim):
        raise RuntimeError("Mismatched delimiters")
    if not expr:
        return expr
    vchars = (
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        ".0123456789"
        r"_()[]\{\}" + rdelim + ldelim + op_group
    )
    if any([item not in vchars for item in expr]) or ("__" in expr):
        raise RuntimeError("Argument `expr` is not valid")
    expr = _remove_consecutive_delims(expr, ldelim=ldelim, rdelim=rdelim)
    expr = expr.replace(ldelim + rdelim, "")
    return _remove_extra_delims(expr, ldelim=ldelim, rdelim=rdelim)
def remove_extra_delims(expr, ldelim="(", rdelim=")"):
    r"""
    Remove unnecessary delimiters in mathematical expressions.

    Delimiters (parenthesis, brackets, etc.) may be removed either because
    there are multiple consecutive delimiters enclosing a single expressions or
    because the delimiters are implied by operator precedence rules. Function
    names must start with a letter and then can contain alphanumeric characters
    and a maximum of one underscore

    :param expr: Mathematical expression
    :type  expr: string

    :param ldelim: Single character left delimiter
    :type  ldelim: string

    :param rdelim: Single character right delimiter
    :type  rdelim: string

    :rtype: string

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

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

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

     * RuntimeError (Function name `*[function_name]*` is not valid)

     * RuntimeError (Mismatched delimiters)
    """
    op_group = ""
    for item1 in _OP_PREC:
        if isinstance(item1, list):
            for item2 in item1:
                op_group += item2
        else:
            op_group += item1
    iobj = zip([expr, ldelim, rdelim], ["expr", "ldelim", "rdelim"])
    for item, desc in iobj:
        if not isinstance(item, str):
            raise RuntimeError("Argument `{0}` is not valid".format(desc))
    if (len(ldelim) != 1) or ((len(ldelim) == 1) and (ldelim in op_group)):
        raise RuntimeError("Argument `ldelim` is not valid")
    if (len(rdelim) != 1) or ((len(rdelim) == 1) and (rdelim in op_group)):
        raise RuntimeError("Argument `rdelim` is not valid")
    if expr.count(ldelim) != expr.count(rdelim):
        raise RuntimeError("Mismatched delimiters")
    if not expr:
        return expr
    vchars = (
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        ".0123456789"
        r"_()[]\{\}" + rdelim + ldelim + op_group
    )
    if any([item not in vchars for item in expr]) or ("__" in expr):
        raise RuntimeError("Argument `expr` is not valid")
    expr = _remove_consecutive_delims(expr, ldelim=ldelim, rdelim=rdelim)
    expr = expr.replace(ldelim + rdelim, "")
    return _remove_extra_delims(expr, ldelim=ldelim, rdelim=rdelim)
r"""
    Remove unnecessary delimiters in mathematical expressions.

    Delimiters (parenthesis, brackets, etc.) may be removed either because
    there are multiple consecutive delimiters enclosing a single expressions or
    because the delimiters are implied by operator precedence rules. Function
    names must start with a letter and then can contain alphanumeric characters
    and a maximum of one underscore

    :param expr: Mathematical expression
    :type  expr: string

    :param ldelim: Single character left delimiter
    :type  ldelim: string

    :param rdelim: Single character right delimiter
    :type  rdelim: string

    :rtype: string

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

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

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

     * RuntimeError (Function name `*[function_name]*` is not valid)

     * RuntimeError (Mismatched delimiters)