Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions nodpy/ast_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
import libcst as cst
from libcst.display import dump
import libcst.matchers as m
from libcst.metadata import PositionProvider, ParentNodeProvider
from libcst.metadata import (
PositionProvider,
ParentNodeProvider,
WhitespaceInclusivePositionProvider,
)
from libcst.metadata import CodePosition, CodeRange

_log = logging.getLogger(__name__)
Expand All @@ -16,10 +20,12 @@ class FunctionFinder(m.MatcherDecoratableTransformer):
METADATA_DEPENDENCIES = (
ParentNodeProvider,
PositionProvider,
WhitespaceInclusivePositionProvider,
)
parent_node: cst.CSTNode
parent_pos: CodeRange
body_indent: CodeRange
body_indent_whitespace: CodeRange
target_function: str

def __init__(self, target_function: str, line_no: int):
Expand All @@ -32,12 +38,18 @@ def __init__(self, target_function: str, line_no: int):
def visit_function(self, node: cst.FunctionDef):
if m.matches(node, m.FunctionDef(m.Name(self.target_function))):
body_indent = self.get_metadata(PositionProvider, node.body)
if isinstance(body_indent, CodeRange):
body_indent_whitespace = self.get_metadata(
WhitespaceInclusivePositionProvider, node.body
)
if isinstance(body_indent, CodeRange) and isinstance(
body_indent_whitespace, CodeRange
):
if (
body_indent.start.line <= self.line_no
and body_indent.end.line >= self.line_no
):
self.body_indent = body_indent
self.body_indent_whitespace = body_indent_whitespace
self.parent_node = node
parent_pos = self.get_metadata(PositionProvider, node)
if isinstance(parent_pos, CodeRange):
Expand All @@ -48,17 +60,20 @@ class NodFinder(m.MatcherDecoratableTransformer):
METADATA_DEPENDENCIES = (
ParentNodeProvider,
PositionProvider,
WhitespaceInclusivePositionProvider,
)
parent_node: cst.CSTNode
parent_pos: CodeRange
body_indent: CodeRange
body_indent_whitespace: CodeRange
indent_block: cst.IndentedBlock | None
indent_pos: CodeRange | None
indent_pos_whitespace: CodeRange | None

def __init__(self, lineno: int, zoom_out: int):
super(__class__, self).__init__() # type: ignore
self.lineno = lineno
self.indent_stack: List[Tuple[cst.IndentedBlock, CodeRange]] = []
self.indent_stack: List[Tuple[cst.IndentedBlock, CodeRange, CodeRange]] = []
self.def_stack: List[cst.FunctionDef] = []
self.zoom_out = zoom_out

Expand All @@ -81,8 +96,14 @@ def visit_notebook_call(self, node: cst.Call):
parent_node = self.get_metadata(ParentNodeProvider, indent_block)
if isinstance(parent_node, cst.CSTNode):
body_indent = self.get_metadata(PositionProvider, indent_block)
if isinstance(body_indent, CodeRange):
body_indent_whitespace = self.get_metadata(
WhitespaceInclusivePositionProvider, indent_block
)
if isinstance(body_indent, CodeRange) and isinstance(
body_indent_whitespace, CodeRange
):
self.body_indent = body_indent
self.body_indent_whitespace = body_indent_whitespace
self.parent_node = parent_node
parent_pos = self.get_metadata(
PositionProvider, parent_node
Expand All @@ -96,6 +117,7 @@ def visit_notebook_call(self, node: cst.Call):
stack_entry = self.indent_stack[-1 * (self.zoom_out + 1)]
self.indent_block = stack_entry[0]
self.indent_pos = stack_entry[1]
self.indent_pos_whitespace = stack_entry[2]
# _log.warning(
# f"indent_block: {self.indent_block}, {self.indent_pos}"
# )
Expand All @@ -105,9 +127,18 @@ def visit_notebook_call(self, node: cst.Call):

def visit_IndentedBlock(self, node):
indent_pos = self.get_metadata(PositionProvider, node)
if isinstance(indent_pos, CodeRange):
indent_pos_whitespace = self.get_metadata(
WhitespaceInclusivePositionProvider, node
)
if isinstance(indent_pos, CodeRange) and isinstance(
indent_pos_whitespace, CodeRange
):
self.indent_stack.append(
(cst.ensure_type(node, cst.IndentedBlock), indent_pos)
(
cst.ensure_type(node, cst.IndentedBlock),
indent_pos,
indent_pos_whitespace,
)
)

def leave_IndentedBlock(self, original_node, updated_node):
Expand Down
48 changes: 42 additions & 6 deletions nodpy/file_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,27 @@ def makeProgramInfo(
if stackFrame.function == "<module>":
func_head_start = 0
func_head_start_id = 0
func_body_start = 0
func_end = len(source_lines) + 1
body_indent = CodeRange(
CodePosition(0, 0),
CodePosition(len(source_lines) + 1, 0),
)
body_indent_whitespace = CodeRange(
CodePosition(0, 0),
CodePosition(len(source_lines) + 1, 0),
)
else:
finder = FunctionFinder(stackFrame.function, stackFrame.lineno)
module = wrapper.visit(finder)
_log.debug(module)
# _log.info(module)
body_indent = finder.body_indent
func_body_start = finder.body_indent_whitespace.start.line + 1
while source_lines[max(func_body_start - 1, 0)] == "\n":
func_body_start += 1
func_end = finder.body_indent_whitespace.end.line - 1
while source_lines[min(func_end - 1, len(source_lines) - 1)] == "\n":
func_end -= 1
func_head_start = finder.parent_pos.start.line
func_head_start_id = finder.parent_pos.start.line
if zoom_out > -1:
Expand All @@ -183,15 +195,25 @@ def makeProgramInfo(
if (
nodFinder.indent_block is not None
and nodFinder.indent_pos is not None
and nodFinder.indent_pos_whitespace is not None
and nodFinder.indent_pos.start.line >= body_indent.start.line
and nodFinder.indent_pos.end.line <= body_indent.end.line
):
body_indent = nodFinder.indent_pos
func_head_start = nodFinder.indent_pos.start.line
func_body_start = nodFinder.indent_pos_whitespace.start.line + 1
while source_lines[max(func_body_start - 1, 0)] == "\n":
func_body_start += 1
# func_body_start = nodFinder.indent_pos.start.line
func_end = nodFinder.indent_pos.end.line
func_head_start = func_body_start
_log.info(f"Zoom Out = {zoom_out}")
_log.info(nodFinder.indent_pos_whitespace)
indent = body_indent.start.column
func_body_start = body_indent.start.line
func_end = body_indent.end.line

_log.info(
f"indent = {indent}, func_body_start = {func_body_start}, func_end = {func_end}"
)
_log.info(body_indent)
return writeNotebook(
ProgramInfo(
index=index,
Expand All @@ -208,13 +230,27 @@ def makeProgramInfo(
frame_xml=list(stackFrame.frame.f_locals.keys()),
fmt=fmt,
file_info=FileInfo(
function_body_position=body_indent,
function_body_position=CodeRange(
CodePosition(
func_body_start,
body_indent.start.column,
),
CodePosition(
func_end,
body_indent.start.column,
),
),
indent=indent,
text_header=source_lines[
max(func_head_start - 1, 0) : max(func_body_start - 1, 0)
],
text_body=[
line[indent:] if line[:indent] == """ """ * indent else line
(
line[indent:]
if line[:indent] == """ """ * indent
# else line.lstrip() if line.lstrip().startswith("#")
else line
)
for line in source_lines[max(func_body_start - 1, 0) : func_end]
],
text_above=source_lines[0 : max(func_head_start - 1, 0)],
Expand Down
1 change: 1 addition & 0 deletions nodpy/serverExtension.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ def post(self):
+ textwrap.indent(
nb_content_to_write,
" " * fileInfo.indent,
# lambda x: not x.startswith("#"),
).splitlines(True)
+ fileInfo.text_below
)
Expand Down
15 changes: 12 additions & 3 deletions nodpy/tests/moduletest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
from nodpy import notebook, nodLog


def f():
def f(x):

for i in range(10):
nodLog(i)
notebook()

# # execute notebook when $i = 8$

if i == 8:
notebook()


def g():
f(10)


f()
g()
Loading
Loading