Blog Logo

28 Feb 2024 ~ 2 min read

PSX is for python what JSX is for javascript


Without looking too far into this, I wanted to see what could be a simple way to adapt the JSX syntax of React to python. The simplest way would be the functional way: imagine that the various html elements are actual python functions (with props).

def div(props, *children):
    return f'<div {format_props(props)}>{format_children(children)}</div>'


def h1(props, *children):
    return f'<h1 {format_props(props)}>{format_children(children)}</h1>'

There is a lot of code repetition here, so we might as well refactor that a little bit:

def create_element(tag):
    """Generates a function to create HTML elements of the specified tag."""
    def element(props=None, *children):
        props_str = format_props(props) if props else ""
        children_str = format_children(children)
        return f'<{tag}{props_str}>{children_str}</{tag}>'
    return element


# Creating specific HTML element functions
div = create_element("div")
p = create_element("p")
a = create_element("a")

Formatting the elements

We need few functions here:

def format_props(props):
    """Formats and returns a string of HTML attributes from a dictionary."""
    if not props:
        return ""
    return " " + " ".join(
        f'{key.replace("_", "-")}="{value}"'
        for key, value in props.items()
        if value is not None
    )


def format_children(children):
    """Formats and returns a string of HTML content from children components."""
    return "".join(str(child) for child in children)


def render(component):
    return component

Trying it

Now I simply put everything together into a simple app, to try it:

# Flask app
app = Flask(__name__)


@app.route("/")
def hello_world():

    content = div(
        {"className": "container"},
        div(
            {"className": "row"},
            div(
                {"className": "col"},
                p({}, "This is a paragraph inside a column."),
                a({"href": "https://example.com"}, "Click here"),
            ),
        ),
    )

    return render(content)


if __name__ == "__main__":
    app.run()

When I now run python app.py and visit http://127.0.0.1:5000 I get the web page as expected.


Headshot of Sylvain Bonnot

I'm Sylvain. I'm a data scientist based near Paris. You can see some of my work on GitHub.