From 7a58d0bbb2650bd4f618d6735326a15c4b45a966 Mon Sep 17 00:00:00 2001 From: Marc Wouts Date: Wed, 19 Sep 2018 20:48:05 +0200 Subject: [PATCH] Support metadata for markdown cells in 'light' format #66 --- jupytext/cell_reader.py | 5 ++++- jupytext/cell_to_text.py | 9 ++++++++- jupytext/formats.py | 10 ++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/jupytext/cell_reader.py b/jupytext/cell_reader.py index f1c01477e..a4b4c8c06 100644 --- a/jupytext/cell_reader.py +++ b/jupytext/cell_reader.py @@ -140,7 +140,10 @@ def options_to_metadata(self, options): def find_code_cell_end(self, lines): """Given that this is a code cell, return position of end of cell marker, and position of next cell start""" - self.cell_type = 'code' + if self.metadata and 'cell_type' in self.metadata: + self.cell_type = self.metadata.pop('cell_type') + else: + self.cell_type = 'code' parser = StringParser(self.language or self.default_language) for i, line in enumerate(lines): # skip cell header diff --git a/jupytext/cell_to_text.py b/jupytext/cell_to_text.py index 7c592c81f..27a718214 100644 --- a/jupytext/cell_to_text.py +++ b/jupytext/cell_to_text.py @@ -27,7 +27,7 @@ def comment(lines, prefix): return [prefix + ' ' + line if line else prefix for line in lines] -class BaseCellExporter: +class BaseCellExporter(object): """A class that represent a notebook cell as text""" prefix = None @@ -143,6 +143,13 @@ class LightScriptCellExporter(BaseCellExporter): """A class that represent a notebook cell as a Python or Julia script""" prefix = '#' + def is_code(self): + # Treat markdown cells with metadata as code cells (#66) + if self.cell_type == 'markdown' and self.metadata: + self.metadata['cell_type'] = self.cell_type + return True + return super(LightScriptCellExporter, self).is_code() + def code_to_text(self): """Return the text representation of a code cell""" active = is_active(self.ext, self.metadata) diff --git a/jupytext/formats.py b/jupytext/formats.py index b85a49ed2..8d75161ea 100644 --- a/jupytext/formats.py +++ b/jupytext/formats.py @@ -67,12 +67,14 @@ def __init__(self, header_prefix='#', cell_reader_class=LightScriptCellReader, cell_exporter_class=LightScriptCellExporter, + # Version 1.3 on 2018-09-19 - jupytext v0.7.0 : Metadata are + # allowed for all cell types (and then include 'cell_type') # Version 1.2 on 2018-09-05 - jupytext v0.6.3 : Metadata bracket # can be omitted when empty, if previous line is empty #57 # Version 1.1 on 2018-08-25 - jupytext v0.6.0 : Cells separated # with one blank line #38 # Version 1.0 on 2018-08-22 - jupytext v0.5.2 : Initial version - current_version_number='1.2', + current_version_number='1.3', min_readable_version_number='1.1') for ext in ['.jl', '.py']] + \ [ NotebookFormatDescription( @@ -118,6 +120,7 @@ def guess_format(text, ext): if ext in ['.jl', '.py', '.R']: twenty_dash = ''.join(['#'] * 20) double_percent = '# %%' + double_percent_and_space = double_percent + ' ' twenty_dash_count = 0 double_percent_count = 0 @@ -127,7 +130,10 @@ def guess_format(text, ext): if parser.is_quoted(): continue - if line.startswith(double_percent): + # Don't count escaped Jupyter magics (no space between + # %% and command) as cells + if line == double_percent or \ + line.startswith(double_percent_and_space): double_percent_count += 1 if line.startswith(twenty_dash):