diff --git a/jupytext/cli.py b/jupytext/cli.py index 7a031441a..f091d35ba 100644 --- a/jupytext/cli.py +++ b/jupytext/cli.py @@ -15,7 +15,7 @@ from .combine import combine_inputs_with_outputs from .compare import NotebookDifference, compare, test_round_trip_conversion -from .config import load_jupytext_config, prepare_notebook_for_save +from .config import load_jupytext_config, notebook_formats from .formats import ( _BINARY_FORMAT_OPTIONS, _VALID_FORMAT_OPTIONS, @@ -481,8 +481,6 @@ def jupytext_single_file(nb_file, args, log): if ext: fmt = {"extension": ext} if fmt: - if config: - config.set_default_format_options(fmt) set_format_options(fmt, args.format_options) log( "[jupytext] Reading {}{}".format( @@ -493,7 +491,7 @@ def jupytext_single_file(nb_file, args, log): ) ) - notebook = read(nb_file, fmt=fmt) + notebook = read(nb_file, fmt=fmt, config=config) if "extension" in fmt and "format_name" not in fmt: text_representation = notebook.metadata.get("jupytext", {}).get( "text_representation", {} @@ -501,15 +499,8 @@ def jupytext_single_file(nb_file, args, log): if text_representation.get("extension") == fmt["extension"]: fmt["format_name"] = text_representation["format_name"] - if config and "formats" not in notebook.metadata.get("jupytext", {}): - default_formats = config.default_formats(nb_file) - if default_formats: - notebook.metadata.setdefault("jupytext", {})["formats"] = default_formats - # Compute actual extension when using script/auto, and update nb_dest if necessary dest_fmt = args.output_format - if dest_fmt and config: - config.set_default_format_options(dest_fmt) if dest_fmt and dest_fmt["extension"] == ".auto": dest_fmt = check_auto_ext(dest_fmt, notebook.metadata, "--to") if not args.output and nb_file != "-": @@ -583,11 +574,14 @@ def jupytext_single_file(nb_file, args, log): # Read paired notebooks, except if the pair is being created nb_files = [nb_file, nb_dest] if args.sync: - set_prefix_and_suffix(fmt, notebook, nb_file) + formats = notebook_formats( + notebook, config, nb_file, fallback_on_current_fmt=False + ) + set_prefix_and_suffix(fmt, formats, nb_file) if args.set_formats is None: try: notebook, inputs_nb_file, outputs_nb_file = load_paired_notebook( - notebook, fmt, nb_file, log, args.pre_commit_mode + notebook, fmt, config, formats, nb_file, log, args.pre_commit_mode ) nb_files = [inputs_nb_file, outputs_nb_file] except NotAPairedNotebook as err: @@ -693,7 +687,7 @@ def jupytext_single_file(nb_file, args, log): dest_text = writes(notebook, fmt=dest_fmt) notebook = reads(dest_text, fmt=dest_fmt) - text = writes(notebook, fmt=fmt) + text = writes(notebook, fmt=fmt, config=config) if args.test_strict: compare(text, org_text) @@ -736,7 +730,7 @@ def lazy_write(path, fmt=None, action=None, update_timestamp_only=False): _, ext = os.path.splitext(path) fmt = copy(fmt or {}) fmt = long_form_one_format(fmt, update={"extension": ext}) - new_content = writes(notebook, fmt=fmt) + new_content = writes(notebook, fmt=fmt, config=config) diff = None if not new_content.endswith("\n"): new_content += "\n" @@ -830,7 +824,7 @@ def write_function(path, fmt): update_timestamp_only=(path == inputs_nb_file), ) - formats = prepare_notebook_for_save(notebook, config, nb_file) + formats = notebook_formats(notebook, config, nb_file) write_pair(nb_file, formats, write_function) return untracked_files @@ -918,11 +912,9 @@ def set_format_options(fmt, format_options): fmt[key] = value -def set_prefix_and_suffix(fmt, notebook, nb_file): +def set_prefix_and_suffix(fmt, formats, nb_file): """Add prefix and suffix information from jupytext.formats if format and path matches""" - for alt_fmt in long_form_multiple_formats( - notebook.metadata.get("jupytext", {}).get("formats") - ): + for alt_fmt in long_form_multiple_formats(formats): if alt_fmt["extension"] == fmt["extension"] and fmt.get( "format_name" ) == alt_fmt.get("format_name"): @@ -942,10 +934,8 @@ class InconsistentVersions(ValueError): """An error raised when two paired files in the git index contain inconsistent representations""" -def load_paired_notebook(notebook, fmt, nb_file, log, pre_commit_mode): +def load_paired_notebook(notebook, fmt, config, formats, nb_file, log, pre_commit_mode): """Update the notebook with the inputs and outputs of the most recent paired files""" - formats = notebook.metadata.get("jupytext", {}).get("formats") - if not formats: raise NotAPairedNotebook(f"{shlex.quote(nb_file)} is not a paired notebook") @@ -971,7 +961,7 @@ def read_one_file(path, fmt): return notebook log(f"[jupytext] Loading {shlex.quote(path)}") - return read(path, fmt=fmt) + return read(path, fmt=fmt, config=config) if use_git_index_rather_than_timestamp: # We raise an error if two representations of this notebook in the git index are inconsistent @@ -989,8 +979,8 @@ def read_one_file(path, fmt): with open(path0) as fp: text0 = fp.read() for alt_path, alt_fmt in nb_files_in_git_index[1:]: - nb = read(alt_path, fmt=alt_fmt) - alt_text = writes(nb, fmt=fmt0) + nb = read(alt_path, fmt=alt_fmt, config=config) + alt_text = writes(nb, fmt=fmt0, config=config) if alt_text != text0: diff = compare(alt_text, text0, alt_path, path0, return_diff=True) raise InconsistentVersions( diff --git a/jupytext/combine.py b/jupytext/combine.py index 72edad913..8daf2856d 100644 --- a/jupytext/combine.py +++ b/jupytext/combine.py @@ -49,12 +49,19 @@ def combine_inputs_with_outputs(nb_source, nb_outputs, fmt=None): ext = fmt.get("extension") or text_repr.get("extension") format_name = fmt.get("format_name") or text_repr.get("format_name") - nb_metadata = restore_filtered_metadata( - nb_source.metadata, - nb_outputs.metadata, - nb_source.metadata.get("jupytext", {}).get("notebook_metadata_filter"), - _DEFAULT_NOTEBOOK_METADATA, + notebook_metadata_filter = nb_source.metadata.get("jupytext", {}).get( + "notebook_metadata_filter" ) + if notebook_metadata_filter == "-all": + nb_metadata = nb_outputs.metadata + + else: + nb_metadata = restore_filtered_metadata( + nb_source.metadata, + nb_outputs.metadata, + notebook_metadata_filter, + _DEFAULT_NOTEBOOK_METADATA, + ) source_is_md_version_one = ( ext in [".md", ".markdown", ".Rmd"] and text_repr.get("format_version") == "1.0" diff --git a/jupytext/config.py b/jupytext/config.py index aa9c194d4..b31d7b27f 100644 --- a/jupytext/config.py +++ b/jupytext/config.py @@ -12,7 +12,6 @@ NOTEBOOK_EXTENSIONS, long_form_multiple_formats, long_form_one_format, - rearrange_jupytext_metadata, ) @@ -351,16 +350,19 @@ def validate_jupytext_configuration_file(config_file, config_dict): return config -def prepare_notebook_for_save(nbk, config, path): - """Apply the given configuration to the notebook before saving it""" +def notebook_formats(nbk, config, path, fallback_on_current_fmt=True): + """Return the list of formats for the current notebook""" metadata = nbk.get("metadata") - rearrange_jupytext_metadata(metadata) - jupytext_metadata = metadata.setdefault("jupytext", {}) - formats = jupytext_metadata.get("formats") or ( - config.default_formats(path) if config else None + jupytext_metadata = metadata.get("jupytext", {}) + formats = ( + jupytext_metadata.get("formats") + or metadata.get("jupytext_formats") + or (config.default_formats(path) if config else None) ) if not formats: + if not fallback_on_current_fmt: + return None text_repr = jupytext_metadata.get("text_representation", {}) ext = os.path.splitext(path)[1] fmt = {"extension": ext} @@ -379,13 +381,5 @@ def prepare_notebook_for_save(nbk, config, path): formats = [ preferred_format(f, config.preferred_jupytext_formats_save) for f in formats ] - config.set_default_format_options(jupytext_metadata) - - # Don't keep the formats if they are equal to the default - if config and jupytext_metadata.get("formats") == config.default_formats(path): - jupytext_metadata.pop("formats", None) - - if not jupytext_metadata: - metadata.pop("jupytext") return formats diff --git a/jupytext/contentsmanager.py b/jupytext/contentsmanager.py index fed6bd23a..4974def43 100644 --- a/jupytext/contentsmanager.py +++ b/jupytext/contentsmanager.py @@ -22,8 +22,8 @@ JupytextConfigurationError, find_global_jupytext_configuration_file, load_jupytext_configuration_file, + notebook_formats, preferred_format, - prepare_notebook_for_save, validate_jupytext_configuration_file, ) from .formats import ( @@ -122,7 +122,7 @@ def save(self, model, path=""): nbk = model["content"] try: config = self.get_config(path) - jupytext_formats = prepare_notebook_for_save(nbk, config, path) + jupytext_formats = notebook_formats(nbk, config, path) self.update_paired_notebooks(path, jupytext_formats) def save_one_file(path, fmt): @@ -161,7 +161,7 @@ def save_one_file(path, fmt): type="file", format="text", content=jupytext.writes( - nbformat.from_dict(model["content"]), fmt=fmt + nbformat.from_dict(model["content"]), fmt=fmt, config=config ), ) @@ -204,14 +204,15 @@ def get( else: model = self.super.get(path, content, type="file", format=format) model["type"] = "notebook" - config.set_default_format_options(fmt, read=True) if content: # We may need to update these keys, inherited from text files formats # Cf. https://github.com/mwouts/jupytext/issues/659 model["format"] = "json" model["mimetype"] = None try: - model["content"] = jupytext.reads(model["content"], fmt=fmt) + model["content"] = jupytext.reads( + model["content"], fmt=fmt, config=config + ) except Exception as err: self.log.error( u"Error while reading file: %s %s", path, err, exc_info=True @@ -289,11 +290,10 @@ def read_one_file(alt_path, alt_fmt): )["content"] self.log.info(u"Reading SOURCE from {}".format(alt_path)) - config.set_default_format_options(alt_fmt, read=True) text = self.super.get( alt_path, content=True, type="file", format=format )["content"] - return jupytext.reads(text, fmt=alt_fmt) + return jupytext.reads(text, fmt=alt_fmt, config=config) inputs, outputs = latest_inputs_and_outputs( path, fmt, formats, get_timestamp, contents_manager_mode=True diff --git a/jupytext/header.py b/jupytext/header.py index 9e307d97d..a1fd4a042 100644 --- a/jupytext/header.py +++ b/jupytext/header.py @@ -65,12 +65,12 @@ def encoding_and_executable(notebook, metadata, ext): return lines -def insert_jupytext_info_and_filter_metadata(metadata, ext, text_format): +def insert_jupytext_info_and_filter_metadata(metadata, fmt, text_format): """Update the notebook metadata to include Jupytext information, and filter the notebook metadata according to the default or user filter""" if insert_or_test_version_number(): metadata.setdefault("jupytext", {})["text_representation"] = { - "extension": ext, + "extension": fmt["extension"], "format_name": text_format.format_name, "format_version": text_format.current_version_number, "jupytext_version": __version__, @@ -79,17 +79,13 @@ def insert_jupytext_info_and_filter_metadata(metadata, ext, text_format): if "jupytext" in metadata and not metadata["jupytext"]: del metadata["jupytext"] - notebook_metadata_filter = metadata.get("jupytext", {}).get( - "notebook_metadata_filter" - ) + notebook_metadata_filter = fmt.get("notebook_metadata_filter") return filter_metadata( metadata, notebook_metadata_filter, _DEFAULT_NOTEBOOK_METADATA ) -def metadata_and_cell_to_header( - notebook, metadata, text_format, ext, root_level_metadata_as_raw_cell=True -): +def metadata_and_cell_to_header(notebook, metadata, text_format, fmt): """ Return the text header corresponding to a notebook, and remove the first cell of the notebook if it contained the header @@ -99,6 +95,7 @@ def metadata_and_cell_to_header( lines_to_next_cell = None root_level_metadata = {} + root_level_metadata_as_raw_cell = fmt.get("root_level_metadata_as_raw_cell", True) if not root_level_metadata_as_raw_cell: root_level_metadata = metadata.get("jupytext", {}).pop( @@ -117,7 +114,7 @@ def metadata_and_cell_to_header( lines_to_next_cell = cell.metadata.get("lines_to_next_cell") notebook.cells = notebook.cells[1:] - metadata = insert_jupytext_info_and_filter_metadata(metadata, ext, text_format) + metadata = insert_jupytext_info_and_filter_metadata(metadata, fmt, text_format) if metadata: root_level_metadata["jupyter"] = metadata @@ -131,7 +128,7 @@ def metadata_and_cell_to_header( header = ["---"] + header + ["---"] if ( - metadata.get("jupytext", {}).get("hide_notebook_metadata", False) + fmt.get("hide_notebook_metadata", False) and text_format.format_name == "markdown" ): header = [""] diff --git a/jupytext/jupytext.py b/jupytext/jupytext.py index bc382bbe7..aecd38afb 100644 --- a/jupytext/jupytext.py +++ b/jupytext/jupytext.py @@ -48,23 +48,44 @@ class NotSupportedNBFormatVersion(NotImplementedError): class TextNotebookConverter(NotebookReader, NotebookWriter): """A class that can read or write a Jupyter notebook as text""" - def __init__(self, fmt): + def __init__(self, fmt, config): self.fmt = copy(long_form_one_format(fmt)) + self.config = config self.ext = self.fmt["extension"] self.implementation = get_format_implementation( self.ext, self.fmt.get("format_name") ) - def update_fmt_with_notebook_options(self, metadata): + def update_fmt_with_notebook_options(self, metadata, read=False): """Update format options with the values in the notebook metadata, and record those options in the notebook metadata""" - # format options in notebook have precedence over that in fmt + # The settings in the Jupytext configuration file have precedence over the metadata in the notebook + # when the notebook is saved. This is because the metadata in the notebook might not be visible + # in the text representation when e.g. notebook_metadata_filter="-all", which makes them hard to edit. + if not read and self.config is not None: + self.config.set_default_format_options(self.fmt, read) + + # format options in notebook have precedence over that in fmt, and precedence over the config for opt in _VALID_FORMAT_OPTIONS: if opt in metadata.get("jupytext", {}): self.fmt.setdefault(opt, metadata["jupytext"][opt]) + + # we save the format options in the notebook metadata + for opt in _VALID_FORMAT_OPTIONS: if opt in self.fmt: metadata.setdefault("jupytext", {}).setdefault(opt, self.fmt[opt]) + if self.config is not None: + self.config.set_default_format_options(self.fmt, read=read) + + # We don't want default metadata filters in the notebook itself + for opt in _VALID_FORMAT_OPTIONS: + if opt in self.fmt and opt not in [ + "notebook_metadata_filter", + "cell_metadata_filter", + ]: + metadata.setdefault("jupytext", {}).setdefault(opt, self.fmt[opt]) + # Is this format the same as that documented in the YAML header? If so, we want to know the format version file_fmt = metadata.get("jupytext", {}).get("text_representation", {}) if self.fmt.get("extension") == file_fmt.get("extension") and self.fmt.get( @@ -91,12 +112,17 @@ def reads(self, s, **_): lines, self.implementation.header_prefix, self.implementation.extension, - self.fmt.get("root_level_metadata_as_raw_cell", True), + self.fmt.get( + "root_level_metadata_as_raw_cell", + self.config.root_level_metadata_as_raw_cell + if self.config is not None + else True, + ), ) default_language = default_language_from_metadata_and_ext( metadata, self.implementation.extension ) - self.update_fmt_with_notebook_options(metadata) + self.update_fmt_with_notebook_options(metadata, read=True) if header_cell: cells.append(header_cell) @@ -157,7 +183,7 @@ def writes(self, nb, metadata=None, **kwargs): """Return the text representation of the notebook""" if self.fmt.get("format_name") == "pandoc": metadata = insert_jupytext_info_and_filter_metadata( - metadata, self.ext, self.implementation + metadata, self.fmt, self.implementation ) cells = [] @@ -196,7 +222,7 @@ def writes(self, nb, metadata=None, **kwargs): "pygments_lexer", None ) metadata = insert_jupytext_info_and_filter_metadata( - metadata, self.ext, self.implementation + metadata, self.fmt, self.implementation ) cells = [] @@ -257,8 +283,7 @@ def writes(self, nb, metadata=None, **kwargs): nb, metadata, self.implementation, - self.ext, - self.fmt.get("root_level_metadata_as_raw_cell", True), + self.fmt, ) header.extend(header_content) @@ -334,13 +359,14 @@ def writes(self, nb, metadata=None, **kwargs): return "\n".join(header + lines) -def reads(text, fmt, as_version=nbformat.NO_CONVERT, **kwargs): +def reads(text, fmt, as_version=nbformat.NO_CONVERT, config=None, **kwargs): """ Read a notebook from a string :param text: the text representation of the notebook :param fmt: (optional) the jupytext format like `md`, `py:percent`, ... :param as_version: see nbformat.reads + :param config: (optional) a Jupytext configuration object :param kwargs: (not used) additional parameters for nbformat.reads :return: the notebook """ @@ -370,7 +396,7 @@ def reads(text, fmt, as_version=nbformat.NO_CONVERT, **kwargs): fmt["format_name"] = format_name fmt.update(format_options) - reader = TextNotebookConverter(fmt) + reader = TextNotebookConverter(fmt, config) notebook = reader.reads(text, **kwargs) rearrange_jupytext_metadata(notebook.metadata) @@ -382,12 +408,13 @@ def reads(text, fmt, as_version=nbformat.NO_CONVERT, **kwargs): return notebook -def read(fp, as_version=nbformat.NO_CONVERT, fmt=None, **kwargs): +def read(fp, as_version=nbformat.NO_CONVERT, fmt=None, config=None, **kwargs): """Read a notebook from a file name or a file object :param fp: a file name or a file object :param as_version: see nbformat.read :param fmt: (optional) the jupytext format like `md`, `py:percent`, ... + :param config: (optional) a Jupytext configuration object :param kwargs: (not used) additional parameters for nbformat.read :return: the notebook """ @@ -409,7 +436,7 @@ def read(fp, as_version=nbformat.NO_CONVERT, fmt=None, **kwargs): fmt = long_form_one_format(fmt) fmt.update({"extension": ext}) with io.open(fp, encoding="utf-8") as stream: - return read(stream, as_version=as_version, fmt=fmt, **kwargs) + return read(stream, as_version=as_version, fmt=fmt, config=config, **kwargs) if fmt is not None: fmt = long_form_one_format(fmt) @@ -418,15 +445,16 @@ def read(fp, as_version=nbformat.NO_CONVERT, fmt=None, **kwargs): rearrange_jupytext_metadata(notebook.metadata) return notebook - return reads(fp.read(), fmt, **kwargs) + return reads(fp.read(), fmt, config=config, **kwargs) -def writes(notebook, fmt, version=nbformat.NO_CONVERT, **kwargs): +def writes(notebook, fmt, version=nbformat.NO_CONVERT, config=None, **kwargs): """Return the text representation of the notebook :param notebook: the notebook :param fmt: the jupytext format like `md`, `py:percent`, ... :param version: see nbformat.writes + :param config: (optional) a Jupytext configuration object :param kwargs: (not used) additional parameters for nbformat.writes :return: the text representation of the notebook """ @@ -481,22 +509,23 @@ def writes(notebook, fmt, version=nbformat.NO_CONVERT, **kwargs): fmt["format_name"] = format_name update_jupytext_formats_metadata(metadata, fmt) - writer = TextNotebookConverter(fmt) + writer = TextNotebookConverter(fmt, config) return writer.writes(notebook, metadata) -def write(nb, fp, version=nbformat.NO_CONVERT, fmt=None, **kwargs): +def write(nb, fp, version=nbformat.NO_CONVERT, fmt=None, config=None, **kwargs): """Write a notebook to a file name or a file object :param nb: the notebook :param fp: a file name or a file object :param version: see nbformat.write :param fmt: (optional if fp is a file name) the jupytext format like `md`, `py:percent`, ... + :param config: (optional) a Jupytext configuration object :param kwargs: (not used) additional parameters for nbformat.write """ if fp == "-": # Use sys.stdout.buffer when possible, and explicit utf-8 encoding, cf. #331 - content = writes(nb, version=version, fmt=fmt, **kwargs) + content = writes(nb, version=version, fmt=fmt, config=config, **kwargs) try: # Python 3 sys.stdout.buffer.write(content.encode("utf-8")) @@ -513,14 +542,14 @@ def write(nb, fp, version=nbformat.NO_CONVERT, fmt=None, **kwargs): create_prefix_dir(fp, fmt) with io.open(fp, "w", encoding="utf-8") as stream: - write(nb, stream, version=version, fmt=fmt, **kwargs) + write(nb, stream, version=version, fmt=fmt, config=config, **kwargs) return else: assert ( fmt is not None ), "'fmt' argument in jupytext.write is mandatory unless fp is a file name" - content = writes(nb, version=version, fmt=fmt, **kwargs) + content = writes(nb, version=version, fmt=fmt, config=config, **kwargs) if isinstance(content, bytes): content = content.decode("utf8") fp.write(content) diff --git a/jupytext/version.py b/jupytext/version.py index 1df7ae010..8bd5d8569 100644 --- a/jupytext/version.py +++ b/jupytext/version.py @@ -1,3 +1,3 @@ """Jupytext's version number""" -__version__ = "1.10.3" +__version__ = "1.10.4-dev" diff --git a/tests/test_contentsmanager.py b/tests/test_contentsmanager.py index a219b4200..d4cdbeb5c 100644 --- a/tests/test_contentsmanager.py +++ b/tests/test_contentsmanager.py @@ -1541,21 +1541,25 @@ def test_save_file_with_default_cell_markers(tmpdir): nb = cm.get("nb.py")["content"] assert len(nb.cells) == 1 - nb.metadata["jupytext"]["cell_markers"] = "+,-" - del nb.metadata["jupytext"]["notebook_metadata_filter"] cm.save(model=notebook_model(nb), path="nb.py") with open(tmp_py) as fp: text2 = fp.read() compare( - "\n".join(text2.splitlines()[-len(text.splitlines()) :]), - "\n".join(text.splitlines()), + text2, + """# region +# this is a unique code cell +1 + 1 + +2 + 2 +# endregion +""", ) nb2 = cm.get("nb.py")["content"] compare_notebooks(nb2, nb) - assert nb2.metadata["jupytext"]["cell_markers"] == "+,-" + assert nb2.metadata["jupytext"]["cell_markers"] == "region,endregion" def test_notebook_extensions(tmpdir): @@ -1682,10 +1686,7 @@ def nb(text): assert model_py["last_modified"] <= model_md["last_modified"] -@pytest.mark.parametrize("nb_file", list_notebooks("ipynb_py")) -def test_filter_jupytext_version_information_416(nb_file, tmpdir): - tmp_py = str(tmpdir.join("notebook.py")) - +def test_filter_jupytext_version_information_416(python_notebook, tmpdir, cwd_tmpdir): cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) cm.default_notebook_metadata_filter = ( @@ -1693,17 +1694,17 @@ def test_filter_jupytext_version_information_416(nb_file, tmpdir): ) # load notebook - notebook = jupytext.read(nb_file) + notebook = python_notebook notebook.metadata["jupytext_formats"] = "ipynb,py" model = notebook_model(notebook) # save to ipynb and py cm.save(model=model, path="notebook.ipynb") - assert os.path.isfile(tmp_py) + assert os.path.isfile("notebook.py") # read py file - with open(tmp_py) as fp: + with open("notebook.py") as fp: text = fp.read() assert "---" in text diff --git a/tests/test_header.py b/tests/test_header.py index 7e0b34c5d..2f33b41b0 100644 --- a/tests/test_header.py +++ b/tests/test_header.py @@ -87,7 +87,7 @@ def test_metadata_and_cell_to_header(no_jupytext_version_number): metadata=metadata, cells=[new_raw_cell(source="---\ntitle: Sample header\n---")] ) header, lines_to_next_cell = metadata_and_cell_to_header( - nb, metadata, get_format_implementation(".md"), ".md" + nb, metadata, get_format_implementation(".md"), {"extension": ".md"} ) assert ( "\n".join(header) @@ -105,7 +105,7 @@ def test_metadata_and_cell_to_header(no_jupytext_version_number): def test_metadata_and_cell_to_header2(no_jupytext_version_number): nb = new_notebook(cells=[new_markdown_cell(source="Some markdown\ntext")]) header, lines_to_next_cell = metadata_and_cell_to_header( - nb, {}, get_format_implementation(".md"), ".md" + nb, {}, get_format_implementation(".md"), {"extension": ".md"} ) assert header == [] assert len(nb.cells) == 1 @@ -169,10 +169,13 @@ def test_header_in_html_comment(): def test_header_to_html_comment(no_jupytext_version_number): - metadata = {"jupytext": {"mainlanguage": "python", "hide_notebook_metadata": True}} + metadata = {"jupytext": {"mainlanguage": "python"}} nb = new_notebook(metadata=metadata, cells=[]) header, lines_to_next_cell = metadata_and_cell_to_header( - nb, metadata, get_format_implementation(".md"), ".md" + nb, + metadata, + get_format_implementation(".md"), + {"extension": ".md", "hide_notebook_metadata": True}, ) compare( "\n".join(header), @@ -181,7 +184,6 @@ def test_header_to_html_comment(no_jupytext_version_number): --- jupyter: jupytext: - hide_notebook_metadata: true mainlanguage: python --- diff --git a/tests/test_metadata_filters_from_config.py b/tests/test_metadata_filters_from_config.py index ab707af65..b0c69dc35 100644 --- a/tests/test_metadata_filters_from_config.py +++ b/tests/test_metadata_filters_from_config.py @@ -44,6 +44,4 @@ def test_metadata_filters_from_config(tmpdir): jupytext_cli([str(md_file), "--to", "notebook", "--update"]) nb2 = nbformat.read(str(nb_file), as_version=4) - - del nb2.metadata["jupytext"] compare_notebooks(nb2, nb) diff --git a/tests/test_pre_commit_mode.py b/tests/test_pre_commit_mode.py index 497c0965f..70953c704 100644 --- a/tests/test_pre_commit_mode.py +++ b/tests/test_pre_commit_mode.py @@ -126,3 +126,33 @@ def test_alert_inconsistent_versions(tmpdir, cwd_tmpdir, tmp_repo, capsys): assert "Error: test.ipynb and test.py are inconsistent" in out.err assert "git reset test.py && git checkout -- test.py" in out.err assert "git reset test.ipynb && git checkout -- test.ipynb" in out.err + + +def test_pre_commit_local_config(tmpdir, cwd_tmpdir, tmp_repo, python_notebook, capsys): + tmpdir.join(".jupytext.toml").write_text( + """default_notebook_metadata_filter = "-all" +default_cell_metadata_filter = "-all" +default_jupytext_formats = "ipynb,py:percent" +""", + encoding="utf-8", + ) + + write(python_notebook, str(tmpdir.join("test.ipynb"))) + + # create the paired file + jupytext(["--sync", "test.ipynb"]) + + print("--------- test.ipynb ---------") + print(tmpdir.join("test.ipynb").read_text("utf-8")) + print("--------- test.py ---------") + print(tmpdir.join("test.py").read_text("utf-8")) + + tmp_repo.git.add(".") + + capsys.readouterr() + exit_code = jupytext(["--pre-commit-mode", "--sync", "test.ipynb", "--diff"]) + + out, err = capsys.readouterr() + assert not err, err + assert "updating test" not in out.lower(), out + assert exit_code == 0, out