Skip to content

Commit

Permalink
Optional end of cell marker for python scripts #31
Browse files Browse the repository at this point in the history
  • Loading branch information
mwouts committed Aug 15, 2018
1 parent ae4ecc5 commit 46e3a07
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
28 changes: 26 additions & 2 deletions nbrmd/cells.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,26 @@ def code_to_text(self,
if options != '':
lines.append('#+ ' + options)
else:
# Issue #31: does the cell ends with a blank line?
# Do we find two blank lines in the cell? In that case
# we add an end-of-cell marker
if (len(source) and _BLANK_LINE.match(source[-1])) or \
code_to_cell(self, source, False)[1] != len(source):
cellend = '-'
while True:
cellend_re = re.compile('^#( )' + cellend + '\s*$')
if len(list(filter(cellend_re.match, source))):
cellend = cellend + '-'
else:
break
metadata['cellend'] = cellend

options = metadata_to_json_options(metadata)
if options != '{}':
lines.append('# + ' + options)
lines.extend(source)
if 'cellend' in metadata:
lines.append('# ' + metadata['cellend'])
else:
lines.extend(self.markdown_escape(
code_to_rmd(source, metadata, default_language)))
Expand Down Expand Up @@ -232,10 +248,18 @@ def code_to_cell(self, lines, parse_opt):
else:
metadata = {}

# Find end of cell and return
if self.ext == '.Rmd':
end_cell_re = _END_CODE_MD
elif 'cellend' in metadata:
end_cell_re = re.compile('^#( )' + metadata['cellend'] + '\s*$')
del metadata['cellend']
else:
end_cell_re = None

# Find end of cell and return
if end_cell_re:
for pos, line in enumerate(lines):
if pos > 0 and _END_CODE_MD.match(line):
if pos > 0 and end_cell_re.match(line):
next_line_blank = pos + 1 == len(lines) or \
_BLANK_LINE.match(lines[pos + 1])
if next_line_blank and pos + 2 != len(lines):
Expand Down
21 changes: 14 additions & 7 deletions tests/python_notebook_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,24 @@
# - two blank lines if followed by an other code cell
# - one blank line if followed by a markdown cell

# Code cells can have blank lines, but no two consecutive blank lines (that's
# a cell break!). Below we have a cell with multiple instructions:
# Code cells can have blank lines, but no two consecutive blank lines (unless
# a specific cell end is specified in the cell options, see below).
# Now we have a cell with multiple instructions

a = 3

a + 1

# ## Metadata in code cells
# And a cell with an arbitrary count of blank lines. This last example
# is also an instance of a cell with metadata information in json format,
# escaped with '#+' or '# +'

# In case a code cell has metadata information, it
# is represented in json format, escaped with '#+' or '# +'
# + {"endcell": "-"}
def f(x):
return x + 1

# + {"scrolled": true}
a + 2

def g(x):
return x + 2

# -
24 changes: 24 additions & 0 deletions tests/test_read_simple_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,30 @@ def f(x):
compare(pynb, pynb2)


def test_read_cell_two_blank_lines(pynb="""# ---
# title: cell with two consecutive blank lines
# ---
# + {"cellend": "-"}
a = 1
a + 2
# -
"""):
nb = nbrmd.reads(pynb, ext='.py')

assert len(nb.cells) == 2
assert nb.cells[0].cell_type == 'raw'
assert nb.cells[0].source == '---\ntitle: cell with two ' \
'consecutive blank lines\n---'
assert nb.cells[1].cell_type == 'code'
assert nb.cells[1].source == 'a = 1\n\n\na + 2'

pynb2 = nbrmd.writes(nb, ext='.py')
compare(pynb, pynb2)


def test_read_multiline_comment(pynb="""'''This is a multiline
comment with "quotes", 'single quotes'
# and comments
Expand Down

0 comments on commit 46e3a07

Please sign in to comment.