This PR cleans up types for Tag functions. This will reduce ambiguities in functions that call Tag functions, and simplifies the API a bit.
The biggest change is that, instead of a single TagChildArg type that encompasses both children and attribute dictionaries, it splits it into two types:
TagNode for actual children, like strings, numbers, Tag objects, and lists of those objects.
With this change, functions which wrap Tag functions can be more specific about what they accept. For example, shiny.ui.input_text previously looked like this:
def input_text(id: str, label: TagChildArg):
...
Previously, when TagChildArg encompassed both children and attributes, then this allowed label to be an attribute dictionary (as in label={"class":"foo"}), which was incorrect. Now, since TagChild only encompasses children (and not attributes), the function signature accurately reflects what is really allowed.
If a wrapper function really wants to accept both children and attributes, it needs a signature that explicitly accepts both types:
Drops the children parameter from the Tag class and tag functions, because it is not used. We previously thought it would be useful when you wanted to put attributes before children, like this:
div(class_="a", children=["b"])
But it turns out that it's actually simpler to use a dictionary, like one of the following:
This PR cleans up types for
Tag
functions. This will reduce ambiguities in functions that call Tag functions, and simplifies the API a bit.The biggest change is that, instead of a single
TagChildArg
type that encompasses both children and attribute dictionaries, it splits it into two types:TagNode
for actual children, like strings, numbers,Tag
objects, and lists of those objects.TagAttrs
, for dictionaries of attributes.The
Tag
functions have a signature like:Note that
TagAttrValue
andTagAttrs
are defined like this:With this change, functions which wrap Tag functions can be more specific about what they accept. For example,
shiny.ui.input_text
previously looked like this:Previously, when
TagChildArg
encompassed both children and attributes, then this allowedlabel
to be an attribute dictionary (as inlabel={"class":"foo"}
), which was incorrect. Now, sinceTagChild
only encompasses children (and not attributes), the function signature accurately reflects what is really allowed.If a wrapper function really wants to accept both children and attributes, it needs a signature that explicitly accepts both types:
This PR also does the following:
children
parameter from theTag
class and tag functions, because it is not used. We previously thought it would be useful when you wanted to put attributes before children, like this:But it turns out that it's actually simpler to use a dictionary, like one of the following: