Skip to content

Commit a7bdde2

Browse files
committed
auto header when pass list[dict] to put_table()
1 parent 6f2660a commit a7bdde2

File tree

1 file changed

+50
-29
lines changed

1 file changed

+50
-29
lines changed

pywebio/output.py

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,8 @@ def _get_output_spec(type, scope, position, **other_spec):
361361
return spec
362362

363363

364-
def put_text(*texts: Any, sep: str = ' ', inline: bool = False, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
364+
def put_text(*texts: Any, sep: str = ' ', inline: bool = False, scope: str = None,
365+
position: int = OutputPosition.BOTTOM) -> Output:
365366
"""
366367
Output plain text
367368
@@ -397,7 +398,8 @@ def _put_message(color, contents, closable=False, scope=None, position=OutputPos
397398
scope=scope, position=position).enable_context_manager()
398399

399400

400-
def put_info(*contents: Any, closable: bool = False, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
401+
def put_info(*contents: Any, closable: bool = False, scope: str = None,
402+
position: int = OutputPosition.BOTTOM) -> Output:
401403
"""Output information message.
402404
403405
:param contents: Message contents.
@@ -410,22 +412,25 @@ def put_info(*contents: Any, closable: bool = False, scope: str = None, position
410412
return _put_message(color='info', contents=contents, closable=closable, scope=scope, position=position)
411413

412414

413-
def put_success(*contents: Any, closable: bool = False, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
415+
def put_success(*contents: Any, closable: bool = False, scope: str = None,
416+
position: int = OutputPosition.BOTTOM) -> Output:
414417
"""Output success message.
415418
.. seealso:: `put_info()`
416419
.. versionadded:: 1.2
417420
"""
418421
return _put_message(color='success', contents=contents, closable=closable, scope=scope, position=position)
419422

420423

421-
def put_warning(*contents: Any, closable: bool = False, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
424+
def put_warning(*contents: Any, closable: bool = False, scope: str = None,
425+
position: int = OutputPosition.BOTTOM) -> Output:
422426
"""Output warning message.
423427
.. seealso:: `put_info()`
424428
"""
425429
return _put_message(color='warning', contents=contents, closable=closable, scope=scope, position=position)
426430

427431

428-
def put_error(*contents: Any, closable: bool = False, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
432+
def put_error(*contents: Any, closable: bool = False, scope: str = None,
433+
position: int = OutputPosition.BOTTOM) -> Output:
429434
"""Output error message.
430435
.. seealso:: `put_info()`
431436
"""
@@ -455,7 +460,8 @@ def put_html(html: Any, sanitize: bool = False, scope: str = None, position: int
455460
return Output(spec)
456461

457462

458-
def put_code(content: str, language: str = '', rows: int = None, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
463+
def put_code(content: str, language: str = '', rows: int = None, scope: str = None,
464+
position: int = OutputPosition.BOTTOM) -> Output:
459465
"""
460466
Output code block
461467
@@ -507,7 +513,8 @@ def _left_strip_multiple_line_string_literal(s):
507513
return '\n'.join(lines[:1] + lines_)
508514

509515

510-
def put_markdown(mdcontent: str, lstrip: bool = True, options: Dict[str, Union[str, bool]] = None, sanitize: bool = True,
516+
def put_markdown(mdcontent: str, lstrip: bool = True, options: Dict[str, Union[str, bool]] = None,
517+
sanitize: bool = True,
511518
scope: str = None, position: int = OutputPosition.BOTTOM, **kwargs) -> Output:
512519
"""
513520
Output Markdown
@@ -583,7 +590,8 @@ def span(content: Union[str, Output], row: int = 1, col: int = 1):
583590

584591

585592
@safely_destruct_output_when_exp('tdata')
586-
def put_table(tdata: List[Union[List, Dict]], header: List[Union[str, Tuple[Any, str]]] = None, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
593+
def put_table(tdata: List[Union[List, Dict]], header: List[Union[str, Tuple[Any, str]]] = None, scope: str = None,
594+
position: int = OutputPosition.BOTTOM) -> Output:
587595
"""
588596
Output table
589597
@@ -594,7 +602,7 @@ def put_table(tdata: List[Union[List, Dict]], header: List[Union[str, Tuple[Any,
594602
the first item of ``tdata`` will be used as the header.
595603
The header item can also use the :func:`span()` function to set the cell span.
596604
597-
When ``tdata`` is list of dict, ``header`` is used to specify the order of table headers, which cannot be omitted.
605+
When ``tdata`` is list of dict, ``header`` can be used to specify the order of table headers.
598606
In this case, the ``header`` can be a list of dict key or a list of ``(<label>, <dict key>)``.
599607
600608
:param int scope, position: Those arguments have the same meaning as for `put_text()`
@@ -644,9 +652,11 @@ def put_table(tdata: List[Union[List, Dict]], header: List[Union[str, Tuple[Any,
644652
The cell of table support ``put_xxx()`` calls.
645653
"""
646654

647-
# Change ``dict`` row table to list row table
648-
if tdata and isinstance(tdata[0], dict):
649-
if isinstance(header[0], (list, tuple)):
655+
if tdata and isinstance(tdata[0], dict): # Change ``dict`` row table to list row table
656+
if header is None:
657+
order = list(tdata[0].keys())
658+
header_ = [str(h).capitalize() for h in tdata[0].keys()]
659+
elif isinstance(header[0], (list, tuple)):
650660
header_ = [h[0] for h in header]
651661
order = [h[-1] for h in header]
652662
else:
@@ -657,14 +667,12 @@ def put_table(tdata: List[Union[List, Dict]], header: List[Union[str, Tuple[Any,
657667
for row in tdata
658668
]
659669
header = header_
670+
elif not tdata and isinstance(header[0], (list, tuple)):
671+
header = [h[0] for h in header]
660672
else:
661673
tdata = [list(i) for i in tdata] # copy data
662674

663675
if header:
664-
# when tdata is empty, header will not be process
665-
# see https://github.com/pywebio/PyWebIO/issues/453
666-
if isinstance(header[0], (list, tuple)):
667-
header = [h[0] for h in header]
668676
tdata = [header, *tdata]
669677

670678
span = {}
@@ -709,8 +717,10 @@ def _format_button(buttons):
709717
return btns, values
710718

711719

712-
def put_buttons(buttons: List[Union[Dict[str, Any], Tuple[str, Any], List, str]], onclick: Union[Callable[[Any], None], SequenceType[Callable[[], None]]],
713-
small: bool = None, link_style: bool = False, outline: bool = False, group: bool = False, scope: str = None,
720+
def put_buttons(buttons: List[Union[Dict[str, Any], Tuple[str, Any], List, str]],
721+
onclick: Union[Callable[[Any], None], SequenceType[Callable[[], None]]],
722+
small: bool = None, link_style: bool = False, outline: bool = False, group: bool = False,
723+
scope: str = None,
714724
position: int = OutputPosition.BOTTOM, **callback_options) -> Output:
715725
"""
716726
Output a group of buttons and bind click event
@@ -821,7 +831,8 @@ def click_callback(btn_idx):
821831

822832

823833
def put_button(label: str, onclick: Callable[[], None], color: str = None, small: bool = None, link_style: bool = False,
824-
outline: bool = False, disabled: bool = False, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
834+
outline: bool = False, disabled: bool = False, scope: str = None,
835+
position: int = OutputPosition.BOTTOM) -> Output:
825836
"""Output a single button and bind click event to it.
826837
827838
:param str label: Button label
@@ -849,7 +860,8 @@ def put_button(label: str, onclick: Callable[[], None], color: str = None, small
849860
position=position)
850861

851862

852-
def put_image(src: Union[str, bytes, PILImage], format: str = None, title: str = '', width: str = None, height: str = None,
863+
def put_image(src: Union[str, bytes, PILImage], format: str = None, title: str = '', width: str = None,
864+
height: str = None,
853865
scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
854866
"""Output image
855867
@@ -896,7 +908,8 @@ def put_image(src: Union[str, bytes, PILImage], format: str = None, title: str =
896908
return put_html(tag, scope=scope, position=position)
897909

898910

899-
def put_file(name: str, content: bytes, label: str = None, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
911+
def put_file(name: str, content: bytes, label: str = None, scope: str = None,
912+
position: int = OutputPosition.BOTTOM) -> Output:
900913
"""Output a link to download a file
901914
902915
To show a link with the file name on the browser. When click the link, the browser automatically downloads the file.
@@ -1013,7 +1026,8 @@ def set_processbar(name: str, value: float, label: str = None):
10131026
run_js(js_code)
10141027

10151028

1016-
def put_loading(shape: str = 'border', color: str = 'dark', scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
1029+
def put_loading(shape: str = 'border', color: str = 'dark', scope: str = None,
1030+
position: int = OutputPosition.BOTTOM) -> Output:
10171031
"""Output loading prompt
10181032
10191033
:param str shape: The shape of loading prompt. The available values are: `'border'` (default)、 `'grow'`
@@ -1067,7 +1081,8 @@ def after_exit():
10671081

10681082

10691083
@safely_destruct_output_when_exp('content')
1070-
def put_collapse(title: str, content: Union[str, Output, List[Union[str, Output]]] = [], open: bool = False, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
1084+
def put_collapse(title: str, content: Union[str, Output, List[Union[str, Output]]] = [], open: bool = False,
1085+
scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
10711086
"""Output collapsible content
10721087
10731088
:param str title: Title of content
@@ -1111,7 +1126,8 @@ def put_collapse(title: str, content: Union[str, Output, List[Union[str, Output]
11111126

11121127

11131128
@safely_destruct_output_when_exp('content')
1114-
def put_scrollable(content: Union[str, Output, List[Union[str, Output]]] = [], height: Union[int, Tuple[int, int]] = 400, keep_bottom: bool = False, border: bool = True,
1129+
def put_scrollable(content: Union[str, Output, List[Union[str, Output]]] = [],
1130+
height: Union[int, Tuple[int, int]] = 400, keep_bottom: bool = False, border: bool = True,
11151131
scope: str = None, position: int = OutputPosition.BOTTOM, **kwargs) -> Output:
11161132
"""Output a fixed height content area. scroll bar is displayed when the content exceeds the limit
11171133
@@ -1253,7 +1269,8 @@ def put_widget(template: str, data: Dict[str, Any], scope: str = None, position:
12531269

12541270

12551271
@safely_destruct_output_when_exp('content')
1256-
def put_row(content: List[Union[Output, None]] = [], size: str = None, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
1272+
def put_row(content: List[Union[Output, None]] = [], size: str = None, scope: str = None,
1273+
position: int = OutputPosition.BOTTOM) -> Output:
12571274
"""Use row layout to output content. The content is arranged horizontally
12581275
12591276
:param list content: Content list, the item is ``put_xxx()`` call or ``None``. ``None`` represents the space between the output
@@ -1293,7 +1310,8 @@ def put_row(content: List[Union[Output, None]] = [], size: str = None, scope: st
12931310

12941311

12951312
@safely_destruct_output_when_exp('content')
1296-
def put_column(content: List[Union[Output, None]] = [], size: str = None, scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
1313+
def put_column(content: List[Union[Output, None]] = [], size: str = None, scope: str = None,
1314+
position: int = OutputPosition.BOTTOM) -> Output:
12971315
"""Use column layout to output content. The content is arranged vertically
12981316
12991317
:param list content: Content list, the item is ``put_xxx()`` call or ``None``. ``None`` represents the space between the output
@@ -1415,7 +1433,8 @@ def put_grid(content: List[List[Union[Output, None]]], cell_width: str = 'auto',
14151433

14161434

14171435
@safely_destruct_output_when_exp('content')
1418-
def put_scope(name: str, content: Union[Output, List[Output]] = [], scope: str = None, position: int = OutputPosition.BOTTOM) -> Output:
1436+
def put_scope(name: str, content: Union[Output, List[Output]] = [], scope: str = None,
1437+
position: int = OutputPosition.BOTTOM) -> Output:
14191438
"""Output a scope
14201439
14211440
:param str name:
@@ -1599,7 +1618,8 @@ def style(outputs: Union[Output, List[Output]], css_style: str) -> Union[Output,
15991618

16001619

16011620
@safely_destruct_output_when_exp('content')
1602-
def popup(title: str, content: Union[str, Output, List[Union[str, Output]]] = None, size: str = PopupSize.NORMAL, implicit_close: bool = True,
1621+
def popup(title: str, content: Union[str, Output, List[Union[str, Output]]] = None, size: str = PopupSize.NORMAL,
1622+
implicit_close: bool = True,
16031623
closable: bool = True):
16041624
"""
16051625
Show a popup.
@@ -1696,7 +1716,8 @@ def close_popup():
16961716
send_msg(cmd='close_popup')
16971717

16981718

1699-
def toast(content: str, duration: float = 2, position: str = 'center', color: str = 'info', onclick: Callable[[], None] = None):
1719+
def toast(content: str, duration: float = 2, position: str = 'center', color: str = 'info',
1720+
onclick: Callable[[], None] = None):
17001721
"""Show a notification message.
17011722
17021723
:param str content: Notification content.

0 commit comments

Comments
 (0)