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

api!: Add Renderer class for creating output renderers #964

Merged
merged 81 commits into from
Jan 9, 2024

Conversation

schloerke
Copy link
Collaborator

@schloerke schloerke commented Jan 3, 2024

Creates a new renderer function using a class-based implementation.

Example:

class text(Renderer[str]):
    """
    Class docs here!
    """

    def default_ui(self, id: str) -> Tag:
        return _ui.output_text_verbatim(id)

    async def transform(self, value: str) -> JSONifiable:
        return str(value)
class render_capitalize(Renderer[str]):
    # The documentation for the class will be displayed when the user hovers over the
    # decorator when **no** parenthesis are used. Ex: `@render_capitalize`
    # If no documentation is supplied to the `__init__()` method, then this
    # documentation will be displayed when parenthesis are used on the decorator.
    """
    Render capitalize class documentation goes here.
    """

    to_case: Literal["upper", "lower", "ignore"]
    """
    The case to render the value in.
    """
    placeholder: bool
    """
    Whether to render a placeholder value. (Defaults to `True`)
    """

    def default_ui(self, id: str):
        """
        Express UI for the renderer
        """
        return ui.output_text_verbatim(id, placeholder=self.placeholder)

    def __init__(
        self,
        _fn: ValueFn[str | None] | None = None,
        *,
        to_case: Literal["upper", "lower", "ignore"] = "upper",
        placeholder: bool = True,
    ) -> None:
        # If a different set of documentation is supplied to the `__init__` method,
        # then this documentation will be displayed when parenthesis are used on the decorator.
        # Ex: `@render_capitalize()`
        """
        Render capitalize documentation goes here.

        It is a good idea to talk about parameters here!

        Parameters
        ----------
        to_case
            The case to render the value. (`"upper"`)

            Options:
            - `"upper"`: Render the value in upper case.
            - `"lower"`: Render the value in lower case.
            - `"ignore"`: Do not alter the case of the value.

        placeholder
            Whether to render a placeholder value. (`True`)
        """
        # Do not pass params
        super().__init__(_fn)
        self.widget = None
        self.to_case = to_case

    async def render(self) -> str | None:
        value = await self.value_fn()
        if value is None:
            # If `None` is returned, then do not render anything.
            return None

        ret = str(value)
        if self.to_case == "upper":
            return ret.upper()
        if self.to_case == "lower":
            return ret.lower()
        if self.to_case == "ignore":
            return ret
        raise ValueError(f"Invalid value for `to_case`: {self.to_case}")

Screenshot 2024-01-09 at 5 07 45 PM

Screenshot 2024-01-09 at 5 08 04 PM

TODO

  • Remove occurrences of @output_transformer
  • Make sure documentation is pretty / as expected
    • Followup PR!

Branch management

Branched from tags/v0.6.1.1 main.

  • Added base branch of rc-v0.6.2
  • Resolve conflicts from base branch

Questions

  • Should render function decorators return a Callable or return a RendererBase?
    • A: RendererBase, if they accept a RendererBase
  • Should .transform() exist on Renderer?
    • A: Yes. it is the common case. Make it easy.
  • Should Renderer.default_ui be renamed? ui()? express_ui()?
    • A: leaving as default_ui for now
  • Why was DefaultUIFnImpl being used? The type does not make sense. Using DefaultUIFn
    • A: Type checker didn't find it
  • Should we utilize WrapAsync more within the async utils code?
    • A: For now, no.

@schloerke schloerke self-assigned this Jan 3, 2024
@wch wch mentioned this pull request Jan 4, 2024
@schloerke schloerke changed the base branch from rc-v0.6.2 to main January 8, 2024 18:38
shiny/render/renderer/_renderer.py Outdated Show resolved Hide resolved
shiny/render/renderer/_auto_register.py Outdated Show resolved Hide resolved
shiny/render/renderer/_renderer.py Outdated Show resolved Hide resolved
shiny/render/renderer/_renderer.py Outdated Show resolved Hide resolved
shiny/render/renderer/_renderer.py Outdated Show resolved Hide resolved
shiny/render/renderer/_renderer.py Outdated Show resolved Hide resolved
shiny/render/renderer/_utils.py Outdated Show resolved Hide resolved
shiny/render/transformer/_transformer.py Outdated Show resolved Hide resolved
shiny/render/transformer/_transformer.py Outdated Show resolved Hide resolved
shiny/render/renderer/_renderer.py Outdated Show resolved Hide resolved
@schloerke schloerke marked this pull request as ready for review January 9, 2024 22:03
@schloerke schloerke merged commit 2436e0b into main Jan 9, 2024
26 checks passed
@schloerke schloerke deleted the output_transformer_class branch January 9, 2024 22:14
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.

2 participants