'Python-only' assembled components

Hi there! So, I’m at a stage where I’d really like to create re-usable (‘pure-Python’/non-JS/HTML) components that are composed of some of the existing components, plus optionally some computation in between. A trivial example would be this:

import streamlit as st
from streamlit.delta_generator import DeltaGenerator

def square_two_component(key: typing.Optional[str]=None, container: DeltaGenerator=st):

    selected = container.selectbox("Select", options=[1, 2, 3], key=f"{key}_integer_select")
    result = selected * selected
    container.write(f"The result is: {result}")
    return selected

square_result = square_two_component()

Obviously, this does nothing interesting, but I hope it illustrates the concept. I use this pattern for simple-to-medium complex assembled widgets, the main advantage being that they are very cheap to write and maintain (no html/js, no package building, etc.), and they reduce code-duplication and overall length of my streamlit ‘main’ files.
I can use this with any of the available container components (like an expander, empty, etc.), by specifying the optional container argument (within the limitations of streamlit of course – I could not use such a component in an expander if it also had an expander inside).

I’m currently creating Python mixin-classes that each contain a few of those components/widgets, dynamically create a class that collects all those, initiate an object of that class (calling the object my_st for example), and then use my components like:

squared = my_st.square_two_component()

or, if in a container:

expander = st.expander("Squared")
squared = my_st.square_two_component(container=expander)

This works well, and I can live with doing it like this. What I’d be interested in though, is whether it’d be easily possible to ‘attach’ all of my custom assembled components to the main st context, so the users of my components would not have to worry about creating the extra my_st instance, which would make it more usable (since it’d be the same as calling every other component: st.square_two_component() ). And the code would be nicer looking overall.
I just haven’t been able to figure out an easy way to ‘attach’ the components, that weren’t overly hacky. I could create a proxy object for st, but before I am being that nasty, I figured I’d ask here.

I do believe adopting/supporting this pattern officially could add quite some value to streamlit and its users, but I’m not 100% sure. I might misjudge how easy and non-invasive this would be to implement (if not possible already), in relation to its benefit. In a case like this, maybe there could be an extra attribute to the st object that holds all those custom widgets, something like:


… to make it clear that this component is not ‘officially’ supported, and depends on some 3rd party code to be available.