Example #1
0
def run_script(path):
  if "benchmark" in path: return

  global passed
  global failed
  global num_skipped

  if (splitext(path)[1] != '.lox'):
    return

  # Check if we are just running a subset of the tests.
  if filter_path:
    this_test = relpath(path, join(REPO_DIR, 'test'))
    if not this_test.startswith(filter_path):
      return

  # Make a nice short path relative to the working directory.

  # Normalize it to use "/" since, among other things, the interpreters expect
  # the argument to use that.
  path = relpath(path).replace("\\", "/")

  # Update the status line.
  term.print_line('Passed: {} Failed: {} Skipped: {} {}'.format(
      term.green(passed),
      term.red(failed),
      term.yellow(num_skipped),
      term.gray('({})'.format(path))))

  # Read the test and parse out the expectations.
  test = Test(path)

  if not test.parse():
    # It's a skipped or non-test file.
    return

  test.run()

  # Display the results.
  if len(test.failures) == 0:
    passed += 1
  else:
    failed += 1
    term.print_line(term.red('FAIL') + ': ' + path)
    print('')
    for failure in test.failures:
      print('      ' + term.pink(failure))
    print('')
Example #2
0
def print_tb(tb, nlines=5, ncols=80):
    """Pretty print the traceback TB.  NLINES of Python source lines are
    displayed.  All output lines are fitted within NCOLS column."""
    f = tb.tb_frame
    lineno = tb.tb_lineno
    co = f.f_code
    filename = co.co_filename
    name = co.co_name

    # display frame header
    name_str = term.blue(name, True)
    filename_str = term.green(filename)
    _print('----', name_str, filename_str)

    # display source lines
    linecache.checkcache(filename)
    errline = ''
    for n in range(lineno - nlines + 1, lineno + 1):
        line = linecache.getline(filename, n, f.f_globals).rstrip()
        if line is not None:
            lineno_str = term.gray('{:5} '.format(n))
            _print(lineno_str, end='')
            if n == lineno:
                line_str = term.red(line)
                errline = line
            else:
                line_str = term.reset(line)
            _print(line_str)

    def _by_location(key):
        pos = errline.find(key)
        if 0 <= pos <= 255:
            # keys matching the error line come first
            return chr(pos)
        elif key.startswith('__'):
            # keys starting with __ come last
            return '~' + key
        else:
            # sorted in the alphabetical order
            return key

    # dump all local variables in the frame
    keys = sorted(f.f_locals.keys(), key=_by_location)
    for key in keys:
        key_str = term.yellow('{:>20}'.format(key))
        if key in set([
                'linecache', 'pdb', 'sys', 'os', 're', 'term', 'traceback',
                '__builtins__'
        ]):
            _print(key_str, '= ...')
            continue
        else:
            val_str = trimmed_str(repr(f.f_locals[key]), ncols - 20)
            _print(key_str, '=', val_str)

        # dump all attributes for objects
        attr = getattr(f.f_locals[key], '__dict__', None)
        if attr:
            keys = sorted(attr.keys(), key=_by_location)
            for key in keys:
                key_str = term.cyan('{:>28}'.format(key))
                val_str = trimmed_str(repr(attr[key]), ncols - 28)
                _print(key_str, val_str)
Example #3
0
File: build.py Project: zyeri/clox
def format_file(path, skip_up_to_date, dependencies_mod):
    basename = os.path.basename(path)
    basename = basename.split('.')[0]

    output_path = "site/" + basename + ".html"

    # See if the HTML is up to date.
    if skip_up_to_date:
        source_mod = max(os.path.getmtime(path), dependencies_mod)
        dest_mod = os.path.getmtime(output_path)

        if source_mod < dest_mod:
            return

    title = ''
    title_html = ''
    part = None
    template_file = 'page'

    errors = []
    sections = []
    header_index = 0
    subheader_index = 0
    has_challenges = False
    design_note = None
    snippets = None

    # Read the markdown file and preprocess it.
    contents = ''
    with open(path, 'r') as input:
        # Read each line, preprocessing the special codes.
        for line in input:
            stripped = line.lstrip()
            indentation = line[:len(line) - len(stripped)]

            if line.startswith('^'):
                command, _, arg = stripped.rstrip('\n').lstrip('^').partition(
                    ' ')
                arg = arg.strip()

                if command == 'title':
                    title = arg
                    title_html = title

                    # Remove any discretionary hyphens from the title.
                    title = title.replace('&shy;', '')

                    # Load the code snippets now that we know the title.
                    snippets = source_code.find_all(title)

                    # If there were any errors loading the code, include them.
                    if title in book.CODE_CHAPTERS:
                        errors.extend(source_code.errors[title])
                elif command == 'part':
                    part = arg
                elif command == 'template':
                    template_file = arg
                elif command == 'code':
                    contents = insert_snippet(snippets, arg, contents, errors)
                else:
                    raise Exception('Unknown command "^{} {}"'.format(
                        command, arg))

            elif stripped.startswith('## Challenges'):
                has_challenges = True
                contents += '<h2><a href="#challenges" name="challenges">Challenges</a></h2>\n'

            elif stripped.startswith('## Design Note:'):
                has_design_note = True
                design_note = stripped[len('## Design Note:') + 1:]
                contents += '<h2><a href="#design-note" name="design-note">Design Note: {}</a></h2>\n'.format(
                    design_note)

            elif stripped.startswith('# ') or stripped.startswith(
                    '## ') or stripped.startswith('### '):
                # Build the section navigation from the headers.
                index = stripped.find(" ")
                header_type = stripped[:index]
                header = pretty(stripped[index:].strip())
                anchor = book.get_file_name(header)
                anchor = re.sub(r'[.?!:/"]', '', anchor)

                # Add an anchor to the header.
                contents += indentation + header_type

                if len(header_type) == 2:
                    header_index += 1
                    subheader_index = 0
                    page_number = book.chapter_number(title)
                    number = '{0}&#8202;.&#8202;{1}'.format(
                        page_number, header_index)
                elif len(header_type) == 3:
                    subheader_index += 1
                    page_number = book.chapter_number(title)
                    number = '{0}&#8202;.&#8202;{1}&#8202;.&#8202;{2}'.format(
                        page_number, header_index, subheader_index)

                header_line = '<a href="#{0}" name="{0}"><small>{1}</small> {2}</a>\n'.format(
                    anchor, number, header)
                contents += header_line

                # Build the section navigation.
                if len(header_type) == 2:
                    sections.append([header_index, header])

            else:
                contents += pretty(line)

    # Validate that every snippet for the chapter is included.
    for name, snippet in snippets.items():
        if name != 'not-yet' and name != 'omit' and snippet != False:
            errors.append("Unused snippet {}".format(name))

    # Show any errors at the top of the file.
    if errors:
        error_markdown = ""
        for error in errors:
            error_markdown += "**Error: {}**\n\n".format(error)
        contents = error_markdown + contents

    # Fix up em dashes. We do this on the entire contents instead of in pretty()
    # so that we can handle surrounding whitespace even when the "--" is at the
    # beginning of end of a line in Markdown.
    contents = EM_DASH_PATTERN.sub('<span class="em">&mdash;</span>', contents)

    # Allow processing markdown inside some tags.
    contents = contents.replace('<aside', '<aside markdown="1"')
    contents = contents.replace('<div class="challenges">',
                                '<div class="challenges" markdown="1">')
    contents = contents.replace('<div class="design-note">',
                                '<div class="design-note" markdown="1">')
    body = markdown.markdown(contents,
                             extensions=['extra', 'codehilite', 'smarty'])

    # Turn aside markers in code into spans. In the empty span case, insert a
    # zero-width space because Chrome seems to lose the span's position if it has
    # no content.
    # <span class="c1">// [repl]</span>
    body = ASIDE_COMMENT_PATTERN.sub(r'<span name="\1">&#8203;</span>', body)
    body = ASIDE_WITH_COMMENT_PATTERN.sub(
        r'<span class="c1" name="\2">// \1</span>', body)

    up = 'Table of Contents'
    if part:
        up = part
    elif title == 'Table of Contents':
        up = 'Crafting Interpreters'

    data = {
        'title': title,
        'part': part,
        'body': body,
        'sections': sections,
        'chapters': get_part_chapters(title),
        'design_note': design_note,
        'has_challenges': has_challenges,
        'number': book.chapter_number(title),
        'prev': book.adjacent_page(title, -1),
        'prev_type': book.adjacent_type(title, -1),
        'next': book.adjacent_page(title, 1),
        'next_type': book.adjacent_type(title, 1),
        'up': up,
        'toc': book.TOC
    }

    template = environment.get_template(template_file + '.html')
    output = template.render(data)

    # Write the output.
    with codecs.open(output_path, "w", encoding="utf-8") as out:
        out.write(output)

    global total_words
    global num_chapters
    global empty_chapters

    word_count = len(contents.split(None))
    num = book.chapter_number(title)
    if num:
        num = '{}. '.format(num)

    # Non-chapter pages aren't counted like regular chapters.
    if part:
        num_chapters += 1
        if word_count < 50:
            empty_chapters += 1
            print("    " + term.gray("{}{}".format(num, title)))
        elif part != "Backmatter" and word_count < 2000:
            empty_chapters += 1
            print("  {} {}{} ({} words)".format(term.yellow("-"), num, title,
                                                word_count))
        else:
            total_words += word_count
            print("  {} {}{} ({} words)".format(term.green("✓"), num, title,
                                                word_count))
    elif title in ["Crafting Interpreters", "Table of Contents"]:
        print("{} {}{}".format(term.green("•"), num, title))
    else:
        if word_count < 50:
            print("    " + term.gray("{}{}".format(num, title)))
        else:
            print("{} {}{} ({} words)".format(term.green("✓"), num, title,
                                              word_count))