def _pygmented_scope_lines(self) -> Optional[Tuple[int, List[str]]]: # noinspection PyUnresolvedReferences from pygments.formatters import HtmlFormatter formatter = self.options.pygments_formatter scope = self.scope assert_(formatter, ValueError("Must set a pygments formatter in Options")) assert_(scope) if isinstance(formatter, HtmlFormatter): formatter.nowrap = True atok = self.source.asttokens() node = self.executing.node if node and getattr(formatter.style, "for_executing_node", False): scope_start = atok.get_text_range(scope)[0] start, end = atok.get_text_range(node) start -= scope_start end -= scope_start ranges = [(start, end)] else: ranges = [] code = atok.get_text(scope) lines = _pygmented_with_ranges(formatter, code, ranges) start_line = line_range(scope)[0] return start_line, lines
def variables_by_lineno(self): result = defaultdict(list) for var in self.variables: for node in var.nodes: for lineno in range(*line_range(node)): result[lineno].append((var, node)) return result
def check_pieces(source): pieces = source.pieces assert pieces == sorted(pieces, key=lambda p: (p.start, p.stop)) stmts = sorted({ line_range(node) for node in ast.walk(source.tree) if isinstance(node, ast.stmt) if not isinstance(getattr(node, 'body', None), list) }) if not stmts: return stmts_iter = iter(stmts) stmt = next(stmts_iter) for piece in pieces: contains_stmt = stmt[0] <= piece.start < piece.stop <= stmt[1] before_stmt = piece.start < piece.stop <= stmt[0] < stmt[1] assert contains_stmt ^ before_stmt if contains_stmt: try: stmt = next(stmts_iter) except StopIteration: break blank_linenos = set(range(1, len(source.lines) + 1)).difference(*pieces) for lineno in blank_linenos: assert not source.lines[lineno - 1].strip(), lineno
def scope_pieces(self): if not self.source.tree: return [] scope_start, scope_end = line_range(self.scope) return [(start, end) for (start, end) in self.source.pieces if scope_start <= start and end <= scope_end]
def range_from_node(self, node: ast.AST, data: Any) -> Optional[RangeInLine]: """ If the given node overlaps with this line, return a RangeInLine with the correct start and end and the given data. Otherwise, return None. """ start, end = line_range(node) end -= 1 if not (start <= self.lineno <= end): return None if start == self.lineno: try: range_start = node.first_token.start[1] except AttributeError: range_start = node.col_offset else: range_start = 0 if end == self.lineno: try: range_end = node.last_token.end[1] except AttributeError: try: range_end = node.end_col_offset except AttributeError: return None else: range_end = len(self.text) return RangeInLine(range_start, range_end, data)
def scope_pieces(self) -> List[range]: """ All the pieces (ranges of lines) contained in this object's .scope. """ if not self.scope: return [] scope_start, scope_end = line_range(self.scope) return [ piece for piece in self.source.pieces if scope_start <= piece.start and piece.stop <= scope_end ]
def variables_by_lineno(self) -> Mapping[int, List[Tuple[Variable, ast.AST]]]: """ A mapping from 1-based line numbers to lists of pairs: - A Variable object - A specific AST node from the variable's .nodes list that's in the line at that line number. """ result = defaultdict(list) for var in self.variables: for node in var.nodes: for lineno in range(*line_range(node)): result[lineno].append((var, node)) return result
def _raw_split_into_pieces(self, stmt): self.asttokens() start, end = line_range(stmt) for name, body in ast.iter_fields(stmt): if isinstance(body, list) and body and isinstance( body[0], (ast.stmt, ast.ExceptHandler)): for sub_stmt in body: for inner_start, inner_end in self._raw_split_into_pieces( sub_stmt): yield start, inner_start yield inner_start, inner_end start = inner_end yield start, end
def variable_ranges(self): result = [] for variable, node in self.frame_info.variables_by_lineno[self.lineno]: start, end = line_range(node) end -= 1 assert start <= self.lineno <= end if start == self.lineno: range_start = node.first_token.start[1] else: range_start = 0 if end == self.lineno: range_end = node.last_token.end[1] else: range_end = len(self.text) result.append(Range( range_start, range_end, (variable, node), )) return result