def consume_indented_code_block(groups): """Consume all indented lines in groups and return the source string.""" source = [] lines = CommentDeque() for lines in groups: go = True while lines: idx, line = lines.popleft() if line and line[0].isspace(): source.append(line) else: lines.appendleft((idx, line)) go = False break if not go: break if lines: groups.send(lines) return '\n'.join(source)
def group_blocks(line_iter): """Groups lines of each session block together. The input is a list of (line_index, line) pairs. Return an iterator over a list of lines in each group.""" session = CommentDeque() lines = deque(line_iter) lines.append((None, '')) comments = [] while lines: idx, line = lines.popleft() # Whitespace and comments divide chunks if (not line) or line.isspace() or line.startswith('#'): comments.append((idx, line)) if not session: continue if comments: data = '\n'.join(line for (_, line) in comments) data = data.strip() if data: comment_idx = comments[0][0] session.comment = Comment(data, lineno=comment_idx) comments = [] data = yield session while data is not None: yield data data = yield session session = CommentDeque() else: session.append((idx, line))
def parse_error_block(self, lines): lineno, line = lines.popleft() error_types = ('@timeout-error', '@runtime-error', '@build-error', '@earlytermination-error') if line.strip() not in error_types: raise SyntaxError(lineno) error_type = line.strip()[1:-6] self.groups.send(lines) data = consume_indented_code_block(self.groups) data = strip_columns(data) body_lines = data.splitlines() if any(line.startswith('@error') for line in body_lines): for i, line in enumerate(lines): if line.startswith('@error'): if line.strip() != '@error': raise SyntaxError(line) body_lines = lines[:i] error = '\n'.join(lines[i + 1:]) break else: raise RuntimeError else: error = '' body_lines = CommentDeque(enumerate(body_lines, lineno + 1)) cases = self.parse_regular_block(body_lines) return ErrorTestCase( list(cases), error_type=error_type, error_message=error, lineno=lineno, comment=lines.comment, )