def update_doctests(infilename, outfile):
    """
    Updates a file with doctests in it but no results to have "correct" results.
    """
    module = import_by_filename(infilename)
    if isinstance(outfile, str):
        outfile = open(outfile, 'w')

    perf_log = []

    with open(infilename, 'r') as infile, cache():
        for line in infile:
            # pylint: disable=cell-var-from-loop
            m = re.match(r'\s*>>> (.*)\n', line)
            if m:
                cmd = m.group(1)
            else:
                outfile.write(("%s" % line).encode('utf-8'))
                continue

            if line.endswith(' # remove-if-false\n'):
                line = line.replace(' # remove-if-false\n', '\n')
                remove_if_false = True
            else:
                remove_if_false = False

            # At the end of this result[0] will either be "statement", "falsey",
            # "truey" or "exception":
            result = ["statement"]

            # This lets us know if anything was printed excluding the
            # value/exception produced by running the code.  It counts toward
            # our measure of interestingness
            did_print = [None]

            # doctest can't cope with printing unicode strings with unicode
            # codepoints in them.  This detects if we're going to fall into this
            # trap.
            would_unicode_fail = [False]

            oldstdout = sys.stdout
            io = StringIO.StringIO()
            real_write = io.write

            def io_write(text, *args, **kwargs):
                if isinstance(text, unicode):
                    try:
                        text = text.encode('ascii')
                    except UnicodeEncodeError:
                        would_unicode_fail[0] = True
                        text = text.encode('ascii', 'backslashreplace')
                return real_write(text, *args, **kwargs)

            io.write = io_write

            def displayhook(value):
                result[0] = "truthy" if bool(value) else "falsey"
                did_print[0] = (io.tell() != 0)
                if value is not None:
                    print repr(value)

            try:
                start_time = time.time()
                sys.stdout = io
                old_displayhook, sys.displayhook = sys.displayhook, displayhook
                exec compile(cmd, "<string>", "single") in module.__dict__  # pylint: disable=exec-used
                if did_print[0] is None:
                    did_print[0] = (io.tell() != 0)
            except Exception:  # pylint: disable=broad-except
                did_print[0] = (io.tell() != 0)
                result[0] = "exception"
                traceback.print_exc(0, io)
            finally:
                perf_log.append((cmd, time.time() - start_time))

                interesting = (did_print[0] or
                               result[0] in ["exception", "truthy"])
                sys.displayhook = old_displayhook
                sys.stdout = oldstdout
                if interesting or not remove_if_false:
                    if would_unicode_fail[0]:
                        line = re.sub(r"\n$", "  # doctest: +SKIP\n", line)
                    outfile.write("%s" % line)
                    io.seek(0)
                    for output_line in io:
                        if output_line.strip() == '':
                            outfile.write('    <BLANKLINE>\n')
                        else:
                            outfile.write('    ' + output_line)

    return perf_log
Esempio n. 2
0
def update_doctests(infilename, outfile):
    """
    Updates a file with doctests in it but no results to have "correct" results.
    """
    module = import_by_filename(infilename)
    if isinstance(outfile, str):
        outfile = open(outfile, 'w')

    perf_log = []

    with open(infilename, 'r') as infile, cache():
        for line in infile:
            # pylint: disable=cell-var-from-loop
            m = re.match(r'\s*>>> (.*)\n', line)
            if m:
                cmd = m.group(1)
            else:
                outfile.write(("%s" % line).encode('utf-8'))
                continue

            if line.endswith(' # remove-if-false\n'):
                line = line.replace(' # remove-if-false\n', '\n')
                remove_if_false = True
            else:
                remove_if_false = False

            # At the end of this result[0] will either be "statement", "falsey",
            # "truey" or "exception":
            result = ["statement"]

            # This lets us know if anything was printed excluding the
            # value/exception produced by running the code.  It counts toward
            # our measure of interestingness
            did_print = [None]

            # doctest can't cope with printing unicode strings with unicode
            # codepoints in them.  This detects if we're going to fall into this
            # trap.
            would_unicode_fail = [False]

            oldstdout = sys.stdout
            io = StringIO.StringIO()
            real_write = io.write

            def io_write(text, *args, **kwargs):
                if isinstance(text, unicode):
                    try:
                        text = text.encode('ascii')
                    except UnicodeEncodeError:
                        would_unicode_fail[0] = True
                        text = text.encode('ascii', 'backslashreplace')
                return real_write(text, *args, **kwargs)

            io.write = io_write

            def displayhook(value):
                result[0] = "truthy" if bool(value) else "falsey"
                did_print[0] = (io.tell() != 0)
                if value is not None:
                    print repr(value)

            try:
                start_time = time.time()
                sys.stdout = io
                old_displayhook, sys.displayhook = sys.displayhook, displayhook
                exec compile(cmd, "<string>", "single") in module.__dict__  # pylint: disable=exec-used
                if did_print[0] is None:
                    did_print[0] = (io.tell() != 0)
            except Exception:  # pylint: disable=broad-except
                did_print[0] = (io.tell() != 0)
                result[0] = "exception"
                traceback.print_exc(0, io)
            finally:
                perf_log.append((cmd, time.time() - start_time))

                interesting = (did_print[0]
                               or result[0] in ["exception", "truthy"])
                sys.displayhook = old_displayhook
                sys.stdout = oldstdout
                if interesting or not remove_if_false:
                    if would_unicode_fail[0]:
                        line = re.sub(r"\n$", "  # doctest: +SKIP\n", line)
                    outfile.write("%s" % line)
                    io.seek(0)
                    for output_line in io:
                        if output_line.strip() == '':
                            outfile.write('    <BLANKLINE>\n')
                        else:
                            outfile.write('    ' + output_line)

    return perf_log