Skip to content

Instantly share code, notes, and snippets.

@podhmo
Created July 13, 2019 03:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save podhmo/95a2e445787c4574573b74fc0c8852d5 to your computer and use it in GitHub Desktop.
Save podhmo/95a2e445787c4574573b74fc0c8852d5 to your computer and use it in GitHub Desktop.
class A:
def f(self, x):
if x is None:
return "[]"
class A:
def f(self, x):
if x is None:
# ...
def g(self, x):
if x is None:
do_something()
# ...
def closure0(y):
return f"[{y}]" # <- ここを指定(18行目)
import linecache
from pycomment.parse import parse_string, node_name, PyTreeVisitor, token
from handofcats import as_command
from lib2to3.pytree import Node
class Visitor(PyTreeVisitor):
def __init__(self, lineno):
self.lineno = lineno
self.r = []
# todo: performance
def visit(self, node):
if node.get_lineno() == self.lineno and node.type != token.INDENT:
self.r.append(node)
return
super().visit(node)
def select_node(t: Node, *, lineno: int) -> Node:
visitor = Visitor(lineno)
visitor.visit(t)
return next(iter(visitor.r)) # xxx:
def find_parents(node: Node) -> Node:
r = [node]
seen = set()
target = node
while target:
if id(target) in seen:
break
if node_name(target) in ("funcdef", "classdef"):
r.append(target)
elif target.parent is None:
break
seen.add(id(target))
target = target.parent
return reversed(r)
@as_command
def run(filename, *, lineno: int, n: int = 2, show_lineno: bool = False):
t = parse_string("".join(linecache.getlines(filename)))
seen = []
targets = list(find_parents(select_node(t, lineno=lineno)))
for i, node in enumerate(targets):
target_lineno = node.get_lineno()
if i == 0:
start_lineno = target_lineno
elif i == len(targets) - 1:
start_lineno = max(1, target_lineno - n)
else:
start_lineno = target_lineno
if i == len(targets) - 1:
end_lineno = target_lineno + 1
else:
end_lineno = min(
len(linecache.getlines(filename)) + 1, target_lineno + n + 1
)
if seen and start_lineno - seen[-1] > 1:
if show_lineno:
print(f"...")
else:
print("# ...")
for lineno in range(start_lineno, end_lineno):
if seen and lineno <= seen[-1]:
continue
seen.append(lineno)
if show_lineno:
print(f"{lineno:03d}: {linecache.getline(filename, lineno)}", end="")
else:
print(linecache.getline(filename, lineno), end="")
00:
python 00*.py | tee 00.output
01:
python 01*.py | tee 01.output
02:
python 02*.py target00.py --lineno=4 | tee 0200.output
python 02*.py target01.py --lineno=18 | tee 0201.output
class A:
def f(self, x):
if x is None:
return "[]"
else:
return f"[{x}]"
from something import do_something
class A:
def f(self, x):
if x is None:
return "[]"
else:
return f"[{x}]"
def g(self, x):
if x is None:
do_something()
do_something()
do_something()
def closure0(y):
return f"[{y}]" # <- ここを指定(18行目)
return closure0
else:
do_something()
do_something()
do_something()
def closure1(y):
return f"[{x}, {y}]"
return closure1
def h(self, x):
if x is None:
return "[]"
else:
return f"[{x}]"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment