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('')
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)
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('­', '') # 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} . {1}'.format( page_number, header_index) elif len(header_type) == 3: subheader_index += 1 page_number = book.chapter_number(title) number = '{0} . {1} . {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">—</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">​</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))