Skip to content

Commit be5a160

Browse files
committed
Change path manipulations to use pathlib
1 parent 7628302 commit be5a160

File tree

6 files changed

+40
-42
lines changed

6 files changed

+40
-42
lines changed

jupyter_sphinx/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from sphinx.util.fileutil import copy_asset
99
from sphinx.errors import ExtensionError
1010
from IPython.lib.lexers import IPythonTracebackLexer, IPython3Lexer
11+
from pathlib import Path
1112

1213
from .ast import (
1314
JupyterCell,
@@ -121,18 +122,20 @@ def build_finished(app, env):
121122
if app.builder.format != "html":
122123
return
123124

125+
module_path = Path(__file__)
126+
outdir_path = Path(app.outdir)
127+
124128
# Copy stylesheet
125-
src = os.path.join(os.path.dirname(__file__), "css")
126-
dst = os.path.join(app.outdir, "_static")
129+
src = module_path / "css"
130+
dst = outdir_path / "_static"
127131
copy_asset(src, dst)
128132

129133
thebe_config = app.config.jupyter_sphinx_thebelab_config
130134
if not thebe_config:
131135
return
132136

133137
# Copy all thebelab related assets
134-
src = os.path.join(os.path.dirname(__file__), "thebelab")
135-
dst = os.path.join(app.outdir, "_static")
138+
src = module_path / "thebelab"
136139
copy_asset(src, dst)
137140

138141

jupyter_sphinx/ast.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ def html(self):
229229
)
230230

231231

232-
def cell_output_to_nodes(outputs, data_priority, write_stderr, dir, thebe_config):
232+
def cell_output_to_nodes(outputs, data_priority, write_stderr, out_dir, thebe_config):
233233
"""Convert a jupyter cell with outputs and filenames to doctree nodes.
234234
235235
Parameters
@@ -239,7 +239,7 @@ def cell_output_to_nodes(outputs, data_priority, write_stderr, dir, thebe_config
239239
Which media types to prioritize.
240240
write_stderr : bool
241241
If True include stderr in cell output
242-
dir : string
242+
out_dir : string
243243
Sphinx "absolute path" to the output folder, so it is a relative path
244244
to the source folder prefixed with ``/``.
245245
thebe_config: dict
@@ -305,19 +305,17 @@ def cell_output_to_nodes(outputs, data_priority, write_stderr, dir, thebe_config
305305
continue
306306
data = output["data"][mime_type]
307307
if mime_type.startswith("image"):
308+
file_path = Path(output.metadata["filenames"][mime_type])
309+
out_dir = Path(out_dir)
308310
# Sphinx treats absolute paths as being rooted at the source
309311
# directory, so make a relative path, which Sphinx treats
310312
# as being relative to the current working directory.
311-
filename = os.path.basename(output.metadata["filenames"][mime_type])
313+
filename = file_path.name
312314

313-
# checks if file dir path is inside a subdir of dir
314-
filedir = os.path.dirname(output.metadata["filenames"][mime_type])
315-
subpaths = filedir.split(dir)
316-
if subpaths and len(subpaths) > 1:
317-
subpath = subpaths[1]
318-
dir += subpath
315+
if out_dir in file_path.parents:
316+
out_dir = file_path.parent
319317

320-
uri = Path(os.path.join(dir, filename)).as_posix()
318+
uri = (out_dir / filename).as_posix()
321319
to_add.append(docutils.nodes.image(uri=uri))
322320
elif mime_type == "text/html":
323321
to_add.append(

jupyter_sphinx/execute.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Execution and managing kernels."""
22

33
import os
4+
from pathlib import Path
45

56
from sphinx.transforms import SphinxTransform
67
from sphinx.errors import ExtensionError
@@ -86,8 +87,9 @@ class ExecuteJupyterCells(SphinxTransform):
8687

8788
def apply(self):
8889
doctree = self.document
89-
doc_relpath = os.path.dirname(self.env.docname) # relative to src dir
90-
docname = os.path.basename(self.env.docname)
90+
docname_path = Path(self.env.docname)
91+
doc_dir_relpath = docname_path.parent # relative to src dir
92+
docname = docname_path.name
9193
default_kernel = self.config.jupyter_execute_default_kernel
9294
default_names = default_notebook_names(docname)
9395
thebe_config = self.config.jupyter_sphinx_thebelab_config
@@ -105,7 +107,7 @@ def apply(self):
105107
add_thebelab_library(doctree, self.env)
106108

107109
js.logger.info("executing {}".format(docname))
108-
output_dir = os.path.join(output_directory(self.env), doc_relpath)
110+
output_dir = Path(output_directory(self.env)) / doc_dir_relpath
109111

110112
# Start new notebook whenever a JupyterKernelNode is encountered
111113
jupyter_nodes = (JupyterCellNode, JupyterKernelNode)
@@ -205,7 +207,7 @@ def apply(self):
205207
# Write certain cell outputs (e.g. images) to separate files, and
206208
# modify the metadata of the associated cells in 'notebook' to
207209
# include the path to the output file.
208-
write_notebook_output(notebook, output_dir, file_name, self.env.docname)
210+
write_notebook_output(notebook, str(output_dir), file_name, self.env.docname)
209211

210212
try:
211213
cm_language = notebook.metadata.language_info.codemirror_mode.name
@@ -265,8 +267,10 @@ def write_notebook_output(notebook, output_dir, notebook_name, location=None):
265267
location=location,
266268
)
267269
contents = "\n\n".join(cell.source for cell in notebook.cells)
268-
with open(os.path.join(output_dir, notebook_name + ext), "w",
269-
encoding = "utf8") as f:
270+
271+
notebook_file = notebook_name + ext
272+
output_dir = Path(output_dir)
273+
with (output_dir / notebook_file).open("w", encoding = "utf8") as f:
270274
f.write(contents)
271275

272276

jupyter_sphinx/thebelab.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import docutils
55
from docutils.parsers.rst import Directive
6+
from pathlib import Path
67

78
import jupyter_sphinx as js
89

@@ -86,16 +87,17 @@ def add_thebelab_library(doctree, env):
8687
if isinstance(thebe_config, dict):
8788
pass
8889
elif isinstance(thebe_config, str):
89-
if os.path.isabs(thebe_config):
90+
thebe_config = Path(thebe_config)
91+
if thebe_config.is_absolute():
9092
filename = thebe_config
9193
else:
92-
filename = os.path.join(os.path.abspath(env.app.srcdir), thebe_config)
94+
filename = Path(env.app.srcdir).resolve() / thebe_config
9395

94-
if not os.path.exists(filename):
96+
if not filename.exists():
9597
js.logger.warning("The supplied thebelab configuration file does not exist")
9698
return
9799

98-
with open(filename, "r") as config_file:
100+
with filename.open("r") as config_file:
99101
try:
100102
thebe_config = json.load(config_file)
101103
except ValueError:

jupyter_sphinx/utils.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,13 @@ def sphinx_abs_dir(env, *paths):
7575
# output_directory / jupyter_execute / path relative to source directory
7676
# Sphinx expects download links relative to source file or relative to
7777
# source dir and prepended with '/'. We use the latter option.
78-
out_path = Path(
79-
os.path.abspath(
80-
os.path.join(output_directory(env), os.path.dirname(env.docname), *paths)
81-
)
82-
).as_posix()
83-
78+
out_path = (output_directory(env) / Path(env.docname).parent / Path(*paths)).resolve()
79+
8480
if os.name == "nt":
8581
# Can't get relative path between drives on Windows
86-
return out_path
82+
return out_path.as_posix()
8783

88-
return "/" + os.path.relpath(
89-
out_path,
90-
os.path.abspath(env.app.srcdir),
91-
)
84+
return "/" + out_path.relative_to(env.app.srcdir).as_posix()
9285

9386

9487
def output_directory(env):
@@ -99,6 +92,4 @@ def output_directory(env):
9992

10093
# Note: we are using an implicit fact that sphinx output directories are
10194
# direct subfolders of the build directory.
102-
return os.path.abspath(
103-
os.path.join(env.app.outdir, os.path.pardir, "jupyter_execute")
104-
)
95+
return (Path(env.app.outdir) / os.path.pardir / "jupyter_execute").resolve()

tests/test_execute.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ def doctree():
3535
def doctree(
3636
source, config=None, return_warnings=False, entrypoint="jupyter_sphinx"
3737
):
38-
src_dir = tempfile.mkdtemp()
38+
src_dir = Path(tempfile.mkdtemp())
3939
source_trees.append(src_dir)
40-
with open(os.path.join(src_dir, "conf.py"), "w", encoding = "utf8") as f:
40+
with (src_dir / "conf.py").open("w", encoding = "utf8") as f:
4141
f.write("extensions = ['%s']" % entrypoint)
4242
if config is not None:
4343
f.write("\n" + config)
44-
with open(os.path.join(src_dir, "contents.rst"), "w", encoding = "utf8") as f:
44+
with (src_dir / "contents.rst").open("w", encoding = "utf8") as f:
4545
f.write(source)
4646
warnings = StringIO()
4747
app = SphinxTestApp(srcdir=path(src_dir), status=StringIO(), warning=warnings)
@@ -590,7 +590,7 @@ def test_download_role(text, reftarget, caption, tmp_path):
590590

591591
if os.name == "nt":
592592
# Get equivalent abs path for Windows
593-
reftarget = Path(os.path.join(tmp_path, reftarget[1:])).resolve().as_posix()
593+
reftarget = (Path(tmp_path) / reftarget[1:]).resolve().as_posix()
594594

595595
assert_node(ret[0], [download_reference], reftarget=reftarget)
596596
assert_node(ret[0][0], [literal, caption])

0 commit comments

Comments
 (0)