Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to htmltools for Python will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [UNRELEASED]

* The `HTMLDependency.copy()` method can now correctly copy folders in depenendencies that both include directories and have `all_files=True`. (#87)

## [0.5.1] 2023-12-18

* `Tag` objects can now be used as context managers, as in `with tags.div():`. When used this way, then inside the `with` block, `sys.displayhook` is replaced with a function which adds items as children to the `Tag`. This is meant to be used with Shiny Express, Quarto, or Jupyter. (#76)
Expand Down
18 changes: 9 additions & 9 deletions htmltools/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,7 @@ class Tagifiable(Protocol):
returns a `TagList`, the children of the `TagList` must also be tagified.
"""

def tagify(self) -> "TagList | Tag | MetadataNode | str":
...
def tagify(self) -> "TagList | Tag | MetadataNode | str": ...


@runtime_checkable
Expand All @@ -148,8 +147,7 @@ def __call__(
*args: TagChild | TagAttrs,
_add_ws: TagAttrValue = ...,
**kwargs: TagAttrValue,
) -> "Tag":
...
) -> "Tag": ...


@runtime_checkable
Expand All @@ -158,8 +156,7 @@ class ReprHtml(Protocol):
Objects with a `_repr_html_()` method.
"""

def _repr_html_(self) -> str:
...
def _repr_html_(self) -> str: ...


# =============================================================================
Expand Down Expand Up @@ -1609,7 +1606,7 @@ def copy_to(self, path: str, include_version: bool = True) -> None:
# Verify they all exist
for f in src_files:
src_file = os.path.join(paths["source"], f)
if not os.path.isfile(src_file):
if not os.path.exists(src_file):
raise Exception(
f"Failed to copy HTML dependency {self.name}-{str(self.version)} "
+ f"because {src_file} doesn't exist."
Expand All @@ -1626,7 +1623,10 @@ def copy_to(self, path: str, include_version: bool = True) -> None:
src_file = os.path.join(paths["source"], f)
target_file = os.path.join(target_dir, f)
os.makedirs(os.path.dirname(target_file), exist_ok=True)
shutil.copy2(src_file, target_file)
if os.path.isfile(src_file):
shutil.copy2(src_file, target_file)
elif os.path.isdir(src_file):
shutil.copytree(src_file, target_file)

def _validate_dicts(self, ld: Iterable[object], req_attr: list[str]) -> None:
for d in ld:
Expand Down Expand Up @@ -1740,7 +1740,7 @@ def _tag_show(
import IPython # pyright: ignore[reportUnknownVariableType]

ipy = ( # pyright: ignore[reportUnknownVariableType]
IPython.get_ipython() # pyright: ignore[reportUnknownMemberType]
IPython.get_ipython() # pyright: ignore[reportUnknownMemberType, reportPrivateImportUsage]
)
renderer = "ipython" if ipy else "browser"
except ImportError:
Expand Down
1 change: 1 addition & 0 deletions htmltools/_jsx.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
that's an issue for HTML() and <script> tags, so using normal HTML tags inside JSX
components may become unsupported in a future version (see #26 and #28)
"""

from __future__ import annotations

import copy
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ version = {attr = "htmltools.__version__"}
htmltools = ["py.typed"]

[tool.flake8]
ignore = "E203, E302, E402, E501, F403, F405, W503"
ignore = "E203, E302, E402, E501, E704, F403, F405, W503"
extend-exclude = "docs, .venv, venv, typings, e2e, build"

[tool.isort]
Expand Down
File renamed without changes.
12 changes: 12 additions & 0 deletions tests/test_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,15 @@ def test_copy_to():
dep4.copy_to(tmpdir4)
assert (Path(tmpdir4) / "w-1.0" / "testdep.css").exists()
assert (Path(tmpdir4) / "w-1.0" / "testdep.js").exists()

with tempfile.TemporaryDirectory() as tmpdir5:
path_testdep_nested = Path(__file__).parent / "assets" / "testdep-nested"
dep5 = HTMLDependency(
"w",
"1.0",
source={"subdir": str(path_testdep_nested)},
all_files=True,
)
dep5.copy_to(tmpdir5)
assert (Path(tmpdir5) / "w-1.0" / "css" / "my-styles.css").exists()
assert (Path(tmpdir5) / "w-1.0" / "js" / "my-js.js").exists()
2 changes: 1 addition & 1 deletion tests/test_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def test_basic_tag_api():
assert "style" not in x4.attrs.keys()
try:
x4.add_style("color: red")
assert False, "Expected ValueError for missing semicolon"
raise AssertionError("Expected ValueError for missing semicolon")
except ValueError as e:
assert "must end with a semicolon" in str(e)

Expand Down