def ast2str(expr, level=<NUM_LIT:0>, names=None):
if isinstance(expr, Expression):<EOL><INDENT>return ast2str(expr.body, <NUM_LIT:0>, names)if hasattr(expr, "<STR_LIT:body>") else "<STR_LIT>"<EOL><DEDENT>elif isinstance(expr, Name):<EOL><INDENT>return names.get(expr.id, expr.id) if names else expr.id<EOL><DEDENT>elif isinstance(expr, BoolOp):<EOL><INDENT>op = expr.op<EOL>if isinstance(op, Or):<EOL><INDENT>str_exp = "<STR_LIT>".join(ast2str(i, level + <NUM_LIT:1>, names)<EOL>for i in expr.values)<EOL><DEDENT>elif isinstance(op, And):<EOL><INDENT>str_exp = "<STR_LIT>".join(ast2str(i, level + <NUM_LIT:1>, names)<EOL>for i in expr.values)<EOL><DEDENT>else:<EOL><INDENT>raise TypeError("<STR_LIT>" + op.__class__.__name)<EOL><DEDENT>return "<STR_LIT:(>" + str_exp + "<STR_LIT:)>" if level else str_exp<EOL><DEDENT>elif expr is None:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>raise TypeError("<STR_LIT>" + repr(expr))<EOL><DEDENT>
convert compiled ast to gene_reaction_rule str

    Parameters
    ----------
    expr : str
        string for a gene reaction rule, e.g "a and b"
    level : int
        internal use only
    names : dict
        Dict where each element id a gene identifier and the value is the
        gene name. Use this to get a rule str which uses names instead. This
        should be done for display purposes only. All gene_reaction_rule
        strings which are computed with should use the id.

    Returns
    ------
    string
        The gene reaction rule