Skip to content

Commit

Permalink
Add eol --newline option for text content in nbconvert.writers.files
Browse files Browse the repository at this point in the history
  • Loading branch information
thisiswhereitype committed May 3, 2024
1 parent d6dc8a5 commit 6d7bc9b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
35 changes: 31 additions & 4 deletions nbconvert/nbconvertapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,16 @@
from textwrap import dedent, fill

from jupyter_core.application import JupyterApp, base_aliases, base_flags
from traitlets import Bool, DottedObjectName, Instance, List, Type, Unicode, default, observe
from traitlets import (
Bool,
DottedObjectName,
Instance,
List,
Type,
Unicode,
default,
observe,
)
from traitlets.config import Configurable, catch_config_error
from traitlets.utils.importstring import import_item

Expand Down Expand Up @@ -60,6 +69,7 @@ def validate(self, obj, value):
"writer": "NbConvertApp.writer_class",
"post": "NbConvertApp.postprocessor_class",
"output": "NbConvertApp.output_base",
"newline": "NbConvertApp.newline",
"output-dir": "FilesWriter.build_directory",
"reveal-prefix": "SlidesExporter.reveal_url_prefix",
"nbformat": "NotebookExporter.nbformat_version",
Expand Down Expand Up @@ -120,7 +130,10 @@ def validate(self, obj, value):
),
"coalesce-streams": (
{
"NbConvertApp": {"use_output_suffix": False, "export_format": "notebook"},
"NbConvertApp": {
"use_output_suffix": False,
"export_format": "notebook",
},
"FilesWriter": {"build_directory": ""},
"CoalesceStreamsPreprocessor": {"enabled": True},
},
Expand Down Expand Up @@ -304,6 +317,12 @@ def _classes_default(self):
}
writer_factory = Type(allow_none=True)

newline = Unicode(
None,
help="""The line ending to use when writing text. See builtin:`open`""",
allow_none=True,
).tag(config=True)

@observe("writer_class")
def _writer_class_changed(self, change):
new = change["new"]
Expand Down Expand Up @@ -523,7 +542,9 @@ def write_single_notebook(self, output, resources):
if not self.writer:
msg = "No writer object defined!"
raise ValueError(msg)
return self.writer.write(output, resources, notebook_name=notebook_name)
return self.writer.write(
output, resources, notebook_name=notebook_name, newline=self.newline
)

def postprocess_single_notebook(self, write_results):
"""Step 4: Post-process the written file
Expand Down Expand Up @@ -628,7 +649,13 @@ def document_config_options(self):
"""
categories = {
category: [c for c in self._classes_inc_parents() if category in c.__name__.lower()]
for category in ["app", "exporter", "writer", "preprocessor", "postprocessor"]
for category in [
"app",
"exporter",
"writer",
"preprocessor",
"postprocessor",
]
}
accounted_for = {c for category in categories.values() for c in category}
categories["other"] = [c for c in self._classes_inc_parents() if c not in accounted_for]
Expand Down
20 changes: 17 additions & 3 deletions nbconvert/writers/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def _write_items(self, items, build_dir):
with open(dest, "wb") as f:
f.write(data)

def write(self, output, resources, notebook_name=None, **kw):
def write(self, output, resources, notebook_name=None, newline=None, **kw):
"""
Consume and write Jinja output to the file system. Output directory
is set via the 'build_directory' variable of this instance (a
Expand Down Expand Up @@ -147,11 +147,25 @@ def write(self, output, resources, notebook_name=None, **kw):
dest_path = Path(build_directory) / dest

# Write conversion results.
self.log.info("Writing %i bytes to %s", len(output), dest_path)
if "\\\\" in repr(newline):
self.log.warning(
"Argument 'newline' contains escaped escape characters: %s",
format(repr(newline)),
)

if isinstance(output, str):
with open(dest_path, "w", encoding="utf-8") as f:
self.log.info(
"Writing %i len string to %s, (repr(newline): %s)",
len(output),
dest_path,
repr(newline),
)
with open(dest_path, "w", encoding="utf-8", newline=newline) as f:
f.write(output)

else:
# newline only applies in text mode.
self.log.info("Writing %i bytes to %s", len(output), dest_path)
with open(dest_path, "wb") as f:
f.write(output)

Expand Down

0 comments on commit 6d7bc9b

Please sign in to comment.