Repository: mwouts/jupytext

Issue:
Black interferes with py:percent format in indented code blocks.
I am having an issue where py:percent notebooks that have cells divided within an if statement get destroyed by black when using --pipe black

``` 
# %%
if __name__ == '__main__':
     print(1)
# %%
     print(2)
```

gets reformatted into the following, which is not equivalent 

``` 
# %%
if __name__ == '__main__':
     print(1)
     # %%
     print(2)
```

For example, when running the following.

jupytext --to notebook test.py 
jupytext --to py:percent --pipe black test.ipynb

Will cause all cells that contain only indented code to be merged into one giant cell. Are they any formats / workarounds to ensure black does not destroy the scripts like so? Or are there any relevant settings that jupytext can set that will resolve this issue?


Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb0fa98..732c405 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
 **Changed**
 - Install Jupytext from source on MyBinder to avoid cache issues (#567)
 - Skip the tests that execute a notebook on Windows to avoid timeout issues (#489)
+- The `# %%` cell marker has the same indentation as the first line in the cell (#562)
 
 **Fixed**
 - Configured coverage targets in `codecov.yml`
diff --git a/jupytext/cell_reader.py b/jupytext/cell_reader.py
index b3d3de7..627d58b 100644
--- a/jupytext/cell_reader.py
+++ b/jupytext/cell_reader.py
@@ -747,9 +747,9 @@ class DoublePercentScriptCellReader(LightScriptCellReader):
         script = _SCRIPT_EXTENSIONS[self.ext]
         self.default_language = default_language or script["language"]
         self.comment = script["comment"]
-        self.start_code_re = re.compile(r"^{}\s*%%(%*)\s(.*)$".format(self.comment))
+        self.start_code_re = re.compile(r"^\s*{}\s*%%(%*)\s(.*)$".format(self.comment))
         self.alternative_start_code_re = re.compile(
-            r"^{}\s*(%%|<codecell>|In\[[0-9 ]*\]:?)\s*$".format(self.comment)
+            r"^\s*{}\s*(%%|<codecell>|In\[[0-9 ]*\]:?)\s*$".format(self.comment)
         )
         self.explicit_soc = True
 
diff --git a/jupytext/cell_to_text.py b/jupytext/cell_to_text.py
index 369036c..b9a4f9a 100644
--- a/jupytext/cell_to_text.py
+++ b/jupytext/cell_to_text.py
@@ -457,10 +457,18 @@ class DoublePercentCellExporter(BaseCellExporter):  # pylint: disable=W0223
         options = metadata_to_double_percent_options(
             self.metadata, self.cell_metadata_json
         )
+        indent = ""
+        if self.is_code() and active and self.source:
+            first_line = self.source[0]
+            if first_line.strip():
+                left_space = re.compile(r"^(\s*)").match(first_line)
+                if left_space:
+                    indent = left_space.groups()[0]
+
         if options.startswith("%") or not options:
-            lines = [self.comment + " %%" + options]
+            lines = [indent + self.comment + " %%" + options]
         else:
-            lines = [self.comment + " %% " + options]
+            lines = [indent + self.comment + " %% " + options]
 
         if self.is_code() and active:
             source = copy(self.source)
diff --git a/jupytext/version.py b/jupytext/version.py
index b6d1df7..5580906 100644
--- a/jupytext/version.py
+++ b/jupytext/version.py
@@ -1,3 +1,3 @@
 """Jupytext's version number"""
 
-__version__ = "1.5.2"
+__version__ = "1.6.0-dev"


Test patch:
diff --git a/tests/test_read_simple_percent.py b/tests/test_read_simple_percent.py
index 60839e8..bfc79ff 100644
--- a/tests/test_read_simple_percent.py
+++ b/tests/test_read_simple_percent.py
@@ -502,3 +502,32 @@ def test_docstring_with_quadruple_quote(
     py = jupytext.writes(nb, "py:percent")
     nb2 = jupytext.reads(py, "py")
     compare_notebooks(nb2, nb)
+
+
+def test_cell_marker_has_same_indentation_as_code(
+    text="""# %%
+if __name__ == '__main__':
+    print(1)
+
+    # %%
+    # INDENTED COMMENT
+    print(2)
+""",
+    nb_expected=new_notebook(
+        cells=[
+            new_code_cell(
+                """if __name__ == '__main__':
+    print(1)"""
+            ),
+            new_code_cell(
+                """    # INDENTED COMMENT
+    print(2)"""
+            ),
+        ]
+    ),
+):
+    """The cell marker should have the same indentation as the first code line. See issue #562"""
+    nb_actual = jupytext.reads(text, fmt="py:percent")
+    compare_notebooks(nb_actual, nb_expected)
+    text_actual = jupytext.writes(nb_actual, fmt="py:percent")
+    compare(text_actual, text)