Skip to content

Commit ff2c0b4

Browse files
committed
Close #948. Update shiny.ui.card() logic to better handle express' RecallContextManager[CardItem] objects
1 parent 6ed505b commit ff2c0b4

File tree

1 file changed

+20
-26
lines changed

1 file changed

+20
-26
lines changed

shiny/ui/_card.py

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def _card_impl(
126126
wrapper = card_body
127127

128128
attrs, children = consolidate_attrs(*args, class_=class_, **kwargs)
129-
children = _wrap_children_in_card(*children, wrapper=wrapper)
129+
children = _as_card_items(*children, wrapper=wrapper)
130130

131131
tag = div(
132132
{
@@ -202,9 +202,9 @@ def __call__(self, *args: TagChild) -> CardItem:
202202

203203

204204
def _as_card_items(
205-
*children: TagChild | CardItem | None, # `TagAttrs` are not allowed here
205+
*children: TagChild, # `TagAttrs` are not allowed here
206206
wrapper: WrapperCallable | None,
207-
) -> list[CardItem]:
207+
) -> list[TagChild]:
208208
# We don't want `None`s creating empty card bodies
209209
children_vals = [child for child in children if child is not None]
210210

@@ -213,9 +213,9 @@ def _as_card_items(
213213
raise ValueError("`TagAttrs` are not allowed in `_as_card_items(*children=)`.")
214214

215215
if not callable(wrapper):
216-
ret: list[CardItem] = []
216+
ret: list[TagChild] = []
217217
for child in children_vals:
218-
if isinstance(child, CardItem):
218+
if is_card_item(child):
219219
ret.append(child)
220220
else:
221221
ret.append(CardItem(child))
@@ -225,7 +225,7 @@ def _as_card_items(
225225
# children that are not, should be wrapped in card_body(). Consecutive children
226226
# that are not card_item, should be wrapped in a single card_body().
227227
state = "asis" # "wrap" | "asis"
228-
new_children: list[CardItem] = []
228+
new_children: list[TagChild] = []
229229
children_to_wrap: list[TagChild] = []
230230

231231
def wrap_children():
@@ -235,7 +235,7 @@ def wrap_children():
235235
children_to_wrap = []
236236

237237
for child in children_vals:
238-
if isinstance(child, CardItem):
238+
if is_card_item(child):
239239
if state == "wrap":
240240
wrap_children()
241241
state = "asis"
@@ -250,13 +250,18 @@ def wrap_children():
250250
return new_children
251251

252252

253-
def _wrap_children_in_card(
254-
*children: TagChild | CardItem | None, # `TagAttrs` are not allowed here
255-
wrapper: WrapperCallable | None,
256-
) -> list[TagChild]:
257-
card_items = _as_card_items(*children, wrapper=wrapper)
258-
tag_children = [card_item.resolve() for card_item in card_items]
259-
return tag_children
253+
def is_card_item(x: object) -> bool:
254+
if isinstance(x, CardItem):
255+
return True
256+
257+
# This is for express' RecallContextManager[CardItem]
258+
# which we want to treat like a CardItem.
259+
fn = getattr(x, "fn", None)
260+
if callable(fn):
261+
ann = getattr(fn, "__annotations__", {})
262+
return ann.get("return", None) == "CardItem"
263+
264+
return False
260265

261266

262267
# TODO-maindocs; @add_example()
@@ -394,17 +399,6 @@ def __init__(
394399
):
395400
self._item = item
396401

397-
def resolve(self) -> TagChild:
398-
"""
399-
Resolves an object with the `CardItem` class by returning the `item` provided at initialization.
400-
401-
Returns
402-
-------
403-
:
404-
The `item` provided at initialization.
405-
"""
406-
return self._item
407-
408402
def tagify(self) -> TagList:
409403
"""
410404
Tagify the `item`
@@ -414,7 +408,7 @@ def tagify(self) -> TagList:
414408
:
415409
A tagified :class:`~htmltools.TagList` object.
416410
"""
417-
return TagList(self.resolve()).tagify()
411+
return TagList(self._item).tagify()
418412

419413

420414
@add_example()

0 commit comments

Comments
 (0)