posit-dev / py-htmltools

Tools for HTML generation and output
MIT License
19 stars 2 forks source link

Can't copy a dependency that has `all_files=True` and includes a directory #87

Closed gadenbuie closed 4 months ago

gadenbuie commented 4 months ago

This line throws an exception if src_file is a directory (or a link)

https://github.com/posit-dev/py-htmltools/blob/a3a98259ee4c5164763a6f70b86e531c13a5bcc1/htmltools/_core.py#L1612

If you make it past that (by checking with os.path.exists(src_file), this line throws:

https://github.com/posit-dev/py-htmltools/blob/a3a98259ee4c5164763a6f70b86e531c13a5bcc1/htmltools/_core.py#L1629

This issue is important because shiny's Bootstrap dependency uses all_files=True and includes a fonts/ subfolder that prevents a shiny app UI from being saved due to this error.

Reprex

from pathlib import Path

import htmltools

# create a dependency with a subdirectory ----
dep_dir = Path(__file__).parent / "the-dep"
dep_dir.mkdir(exist_ok=True)

dep_subdir = dep_dir / "subdir"
dep_subdir.mkdir(exist_ok=True)

with open(dep_dir / "script.js", "w") as f:
    f.write("console.log('hello from script.js')")

with open(dep_subdir / "style.css", "w") as f:
    f.write("body { background-color: lightblue; }")

dep = htmltools.HTMLDependency(
    name="dep",
    version="0.0.1",
    source={"subdir": str(dep_dir)},
    script={"src": "script.js"},
    all_files=True,
)

dep.copy_to(str(Path(__file__).parent / "the-dep-copy"), include_version=False)
# > Traceback (most recent call last):
# >   File "/Users/garrick/work/posit-dev/py-htmltools/_dev/issues/dep-dir/issue-dep-dir.py", line 26, in <module>
# >     dep.copy_to(str(Path(__file__).parent / "the-dep-copy"), include_version=False)
# >   File "/Users/garrick/work/posit-dev/py-htmltools/htmltools/_core.py", line 1613, in copy_to
# >     raise Exception(
# > Exception: Failed to copy HTML dependency dep-0.0.1 because /Users/garrick/work/posit-dev/py-htmltools/_dev/issues/dep-dir/the-dep/subdir doesn't exist.
# Use the dependency in an html fragment...
html = htmltools.tags.p(
    "Hello, world!",
    dep,
)

# ...that cannot be saved
html.save_html("index.html")
#> /work/posit-dev/py-htmltools/_dev/issues/dep-dir/issue-dep-dir.py
#> Traceback (most recent call last):
#>   File "/Users/garrick/work/posit-dev/py-htmltools/_dev/issues/dep-dir/issue-dep-dir.py", line 32, in <module>
#>     html.save_html("index.html")
#>   File "/Users/garrick/work/posit-dev/py-htmltools/htmltools/_core.py", line 823, in save_html
#>     return HTMLDocument(self).save_html(
#>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#>   File "/Users/garrick/work/posit-dev/py-htmltools/htmltools/_core.py", line 1012, in save_html
#>     dep.copy_to(destdir, include_version=include_version)
#>   File "/Users/garrick/work/posit-dev/py-htmltools/htmltools/_core.py", line 1613, in copy_to
#>     raise Exception(
#> Exception: Failed to copy HTML dependency dep-0.0.1 because /Users/garrick/work/posit-dev/py-htmltools/_dev/issues/dep-dir/the-dep/subdir doesn't exist.