Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(HTML)!: HTML class no longer inherits from str #86

Merged
merged 51 commits into from
Sep 19, 2024
Merged

Conversation

schloerke
Copy link
Collaborator

@schloerke schloerke commented Apr 22, 2024

Breaking changes

New features


Benefits:

  • No ambiguity between a str type and an HTML type.

Related py-shiny PRs in prep for this PR:

@schloerke schloerke marked this pull request as ready for review April 23, 2024 21:39
@schloerke schloerke requested a review from wch April 23, 2024 21:39
htmltools/_core.py Outdated Show resolved Hide resolved
@@ -87,7 +97,7 @@ class MetadataNode:

TagT = TypeVar("TagT", bound="Tag")

TagAttrValue = Union[str, float, bool, None]
TagAttrValue = Union[str, float, bool, "HTML", None]
Copy link
Collaborator Author

@schloerke schloerke Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given parity for other large union objects (TagNode and TagChild), I do not believe we should make a is_tag_attr_value() method as consolidate_attrs() should internally handle it.

For now, we will skip making this helper method.

@runtime_checkable
class Tagifiable(Protocol):
"""
Objects with `tagify()` methods are considered `Tagifiable`. Note that an object
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 | HTML": ...
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New HTML() support!

@@ -87,7 +97,7 @@ class MetadataNode:

TagT = TypeVar("TagT", bound="Tag")

TagAttrValue = Union[str, float, bool, None]
TagAttrValue = Union[str, float, bool, "HTML", None]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New HTML() support!

@@ -394,7 +486,7 @@ def _repr_html_(self) -> str:
# =============================================================================
# TagAttrDict class
# =============================================================================
class TagAttrDict(Dict[str, str]):
class TagAttrDict(Dict[str, "str | HTML"]):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New HTML() support!

@@ -453,15 +544,17 @@ def _normalize_attr_name(x: str) -> str:
return x.replace("_", "-")

@staticmethod
def _normalize_attr_value(x: TagAttrValue) -> Optional[str]:
def _normalize_attr_value(x: TagAttrValue) -> str | HTML | None:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New HTML() support!

@@ -689,7 +782,7 @@ def has_class(self, class_: str) -> bool:
else:
return False

def add_style(self: TagT, style: str, *, prepend: bool = False) -> TagT:
def add_style(self: TagT, style: str | HTML, *, prepend: bool = False) -> TagT:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New HTML() support!

@@ -908,8 +1001,8 @@ def wrap_displayhook_handler(
def handler_wrapper(value: object) -> None:
if isinstance(value, (Tag, TagList, Tagifiable)):
handler(value)
elif hasattr(value, "_repr_html_"):
handler(HTML(value._repr_html_())) # pyright: ignore
elif isinstance(value, ReprHtml):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use isinstance() rather than look for the key, which isinstance performs

) -> tuple[TagAttrs, list[TagChildT]]: ...


def consolidate_attrs(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new helper method (ported from py-shiny)

"""


def is_tag_node(x: object) -> TypeIs[TagNode]:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New helper method

return isinstance(x, (Tagifiable, MetadataNode, ReprHtml, str, HTML))


def is_tag_child(x: object) -> TypeIs[TagChild]:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New helper method

@@ -1724,7 +1904,7 @@ def _tagchilds_to_tagnodes(x: Iterable[TagChild]) -> list[TagNode]:
for i, item in enumerate(result):
if isinstance(item, (int, float)):
result[i] = str(item)
elif not isinstance(item, (Tagifiable, Tag, MetadataNode, ReprHtml, str)):
elif not is_tag_node(item):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using new helper method

@schloerke schloerke requested a review from wch September 19, 2024 06:58
htmltools/_core.py Outdated Show resolved Hide resolved
@schloerke schloerke merged commit 81e0749 into main Sep 19, 2024
17 checks passed
@schloerke schloerke deleted the html_not_str branch September 19, 2024 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants