Repository: mwouts/jupytext

Issue:
Pair ipynb with files in subfolders one level down
I would like to pair `.ipynb` files with `.py` files according to this structure:

```
.
├── jupytext.toml
├── Alpha/
│   ├── notebooks_py/
│   │   └── notebook.py
│   └── notebook.ipynb
├── Beta/
│   ├── notebooks_py/
│   │   └── notebook.py
│   └── notebook.ipynb
└── Gamma/
    ├── notebooks_py/
    │   └── notebook.py
    └── notebook.ipynb
```

I haven't been able to figure this out. I am able to get it to work if I switch the locations of the `.ipynb` and `.py` files and use this in in my config:

```
[formats]
"notebooks_ipynb/" = "ipynb"
"./" = "py:percent"
```

I am open to manually pairing each `.py` and `.ipynb` pair or putting `jupytext.toml` config files in each project directory if that will help (`Alpha`, `Beta`, `Gamma`)

Discussion:
github-actions[bot]: Thank you for making this pull request.

Did you know? You can try it on Binder: [![Binder:lab](https://img.shields.io/badge/binder-jupyterlab-0172B2.svg)](https://mybinder.org/v2/gh/mwouts/jupytext/fix_1144?urlpath=lab/tree/demo/get_started.ipynb) or [![Binder:notebook](https://img.shields.io/badge/binder-notebook-0172B2.svg)](https://mybinder.org/v2/gh/mwouts/jupytext/fix_1144?filepath=demo).

Also, the version of Jupytext developed in this PR can be installed with `pip`:
```
HATCH_BUILD_HOOKS_ENABLE=true pip install git+https://github.com/mwouts/jupytext.git@fix_1144
```
(this requires `nodejs`, see more at [Developing Jupytext](https://jupytext.readthedocs.io/en/latest/developing.html))
<!-- thollander/actions-comment-pull-request "binder_link" -->
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/mwouts/jupytext/pull/1238?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 95.99%. Comparing base [(`fd07ae2`)](https://app.codecov.io/gh/mwouts/jupytext/commit/fd07ae2f4aa4de9132b4835ce3fa082a5009cb1d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts) to head [(`57ad343`)](https://app.codecov.io/gh/mwouts/jupytext/commit/57ad3437f15cb69ee6732dcf26f03b3a7f24e077?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts).


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1238      +/-   ##
==========================================
- Coverage   97.73%   95.99%   -1.75%     
==========================================
  Files          29       29              
  Lines        4468     4468              
==========================================
- Hits         4367     4289      -78     
- Misses        101      179      +78     
```

| [Flag](https://app.codecov.io/gh/mwouts/jupytext/pull/1238/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts) | Coverage Δ | |
|---|---|---|
| [external](https://app.codecov.io/gh/mwouts/jupytext/pull/1238/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts) | `?` | |
| [functional](https://app.codecov.io/gh/mwouts/jupytext/pull/1238/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts) | `?` | |
| [integration](https://app.codecov.io/gh/mwouts/jupytext/pull/1238/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts) | `?` | |
| [unit](https://app.codecov.io/gh/mwouts/jupytext/pull/1238/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts) | `?` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts#carryforward-flags-in-the-pull-request-comment) to find out more.


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/mwouts/jupytext/pull/1238?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Marc+Wouts).


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a577ff6..09e9b56 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,9 +6,11 @@ Jupytext ChangeLog
 
 **Fixed**
 - We have fixed a typo when `build_jupytext_contents_manager_class` can't be imported ([#1162](https://github.com/mwouts/jupytext/issues/1162))
+- Some dependencies of the JupyterLab extensions were updated ([#1243](https://github.com/mwouts/jupytext/issues/1243), [#1245](https://github.com/mwouts/jupytext/issues/1245))
 
 **Added**
 - Added support for Lua notebooks ([#1252](https://github.com/mwouts/jupytext/pull/1252)) - thanks to [erentar](https://github.com/erentar) for this contribution
+- Empty prefixes are now allowed in Jupytext format when specified as a dictionary ([#1144](https://github.com/mwouts/jupytext/issues/1144))
 
 
 1.16.2 (2024-05-05)
diff --git a/src/jupytext/config.py b/src/jupytext/config.py
index 81bdfe3..3b0269b 100644
--- a/src/jupytext/config.py
+++ b/src/jupytext/config.py
@@ -398,7 +398,9 @@ def load_jupytext_configuration_file(config_file, stream=None):
     # formats can be a dict prefix => format
     if isinstance(config.formats, dict):
         config.formats = [
-            (prefix[:-1] if prefix.endswith("/") else prefix) + "///" + fmt
+            fmt
+            if not prefix
+            else (prefix[:-1] if prefix.endswith("/") else prefix) + "///" + fmt
             for prefix, fmt in config.formats.items()
         ]
     config.formats = short_form_multiple_formats(config.formats)


Test patch:
diff --git a/tests/functional/config/test_config.py b/tests/functional/config/test_config.py
index 240ba4b..8c70562 100644
--- a/tests/functional/config/test_config.py
+++ b/tests/functional/config/test_config.py
@@ -158,6 +158,15 @@ formats = "ipynb,py:percent"
 """,
             "notebooks///ipynb,scripts///py:percent",
         ),
+        (
+            """# Pair local notebooks to scripts in 'notebooks_py' and md files in 'notebooks_md'
+[formats]
+"" = "ipynb"
+"notebooks_py" = "py:percent"
+"notebooks_md" = "md:myst"
+""",
+            "ipynb,notebooks_py///py:percent,notebooks_md///md:myst",
+        ),
     ],
 )
 def test_jupytext_formats(tmpdir, content_toml, formats_short_form):