diff --git a/.github/py-shiny/check/action.yaml b/.github/py-shiny/check/action.yaml new file mode 100644 index 000000000..04975a87c --- /dev/null +++ b/.github/py-shiny/check/action.yaml @@ -0,0 +1,35 @@ +name: 'check py-shiny' +description: 'Action that checks py-shiny in multiple steps so that any of them may fail but not prevent the others from running. Note, this action is used by py-htmltools as a way to consistently check py-shiny. If more checks are needed for py-htmltools to believe py-shiny is working, it should be added here.' +runs: + using: "composite" + steps: + - name: Run unit tests + shell: bash + run: | + # Run unit tests + make check-tests + + - name: Type check + shell: bash + run: | + # Type check + make check-types + + - name: Lint code + shell: bash + run: | + # Lint code + make check-lint + + - name: Verify code formatting + shell: bash + run: | + # Verify code formatting + make check-format + + - name: Verify code can run with mypy (not Windows) + if: ${{ runner.os != 'Windows' }} + shell: bash + run: | + # Verify code can run with mypy (not Windows) + make ci-check-mypy-can-run diff --git a/shiny/ui/_navs.py b/shiny/ui/_navs.py index ca1cb457c..2480c03fb 100644 --- a/shiny/ui/_navs.py +++ b/shiny/ui/_navs.py @@ -1,27 +1,21 @@ from __future__ import annotations -__all__ = ( - "nav_panel", - "nav_menu", - "nav_control", - "nav_spacer", - "navset_tab", - "navset_card_tab", - "navset_pill", - "navset_underline", - "navset_card_pill", - "navset_card_underline", - "navset_pill_list", - "navset_hidden", - "navset_bar", -) - import collections.abc import copy import re from typing import Any, Literal, Optional, Sequence, cast -from htmltools import MetadataNode, Tag, TagAttrs, TagChild, TagList, css, div, tags +from htmltools import ( + HTML, + MetadataNode, + Tag, + TagAttrs, + TagChild, + TagList, + css, + div, + tags, +) from .._docstring import add_example from .._namespaces import resolve_id_or_none @@ -34,6 +28,22 @@ from .css import CssUnit, as_css_padding, as_css_unit from .fill import as_fill_item, as_fillable_container +__all__ = ( + "nav_panel", + "nav_menu", + "nav_control", + "nav_spacer", + "navset_tab", + "navset_card_tab", + "navset_pill", + "navset_underline", + "navset_card_pill", + "navset_card_underline", + "navset_pill_list", + "navset_hidden", + "navset_bar", +) + # ----------------------------------------------------------------------------- # Navigation items @@ -81,7 +91,7 @@ def resolve( return nav, content - def get_value(self) -> Optional[str]: + def get_value(self) -> str | HTML | None: if self.content is None: return None a_tag = cast(Tag, self.nav.children[0]) diff --git a/tests/pytest/test_modules.py b/tests/pytest/test_modules.py index 2b8c7d3ed..09f267d32 100644 --- a/tests/pytest/test_modules.py +++ b/tests/pytest/test_modules.py @@ -6,7 +6,7 @@ from typing import cast import pytest -from htmltools import Tag, TagList +from htmltools import HTML, Tag, TagList from shiny import App, Inputs, Outputs, Session, module, reactive, ui from shiny._connection import MockConnection @@ -28,7 +28,7 @@ def mod_outer_ui() -> TagList: return TagList(mod_inner_ui("inner"), ui.output_text("out2")) -def get_id(x: TagList, child_idx: int = 0) -> str: +def get_id(x: TagList, child_idx: int = 0) -> str | HTML: return cast(Tag, x[child_idx]).attrs["id"] @@ -44,7 +44,7 @@ def test_module_ui(): @pytest.mark.asyncio async def test_session_scoping(): - sessions: dict[str, Session | str | None] = {} + sessions: dict[str, Session | str | HTML | None] = {} @module.server def inner_server(input: Inputs, output: Outputs, session: Session):