viewdom_wired: Container and DI for viewdom

Pluggability for Templates and Components

Let’s say you share some nice components. You want them to work in different systems: Sphinx, Pelican, Flask, etc. You also want to make it easy to extend or customize without having to fork.

viewdom_wired brings pluggability and flexibility to viewdom templates and components. With dependency injection and containers from wired, the components in your pluggable apps are now swappable, easier to write and test, and less brittle.

Note

This is for people who want to make or consume a pluggable system. If that’s not you, then it’s unneeded complexity/magic.

Installation

For Python 3.7+:

$ pip install viewdom_wired

For Python 3.6, you’ll need the dataclasses backport.

Minimum Example

Let’s write a Greeting component. It expects to be passed a first_name:

@component()
@dataclass
class Greeting:
    first_name: str

    def __call__(self) -> VDOM:
        return html('<h1>Hello {self.first_name}</h1>')

You can then render a template which passes in first_name as a string:

    result = render(html('<{Greeting} first_name="World"/>'), container)

Don’t want to pass data down long component trees? Tell the injector to use a pipeline to get it:

    first_name: Annotated[str, Get(Settings, attr='first_name')]

Want to use that, but some of the time, manually pass in a prop to the component to override the injected value? Do so, and use an expression as the prop value:

    first_name = "Prop"  # noqa: F841
    result = render(html('<{Greeting} first_name={first_name} />'), container)

How It Works

viewdom_wired changes the viewdom rendering to use the wired_injector. It transparently wires up an InjectorContainer for the rendering, provides a @component decorator to turn on use_props, and pass long system_props such as children, parent_component, and whatever you pass into the render.