Skip to main content
Python is the dominant language in data engineering, ML infrastructure, and much of the cloud operations world. Teams already running Python-heavy Pulumi stacks can author ubx components in Python without switching languages. The structure mirrors TypeScript exactly: a class that extends pulumi.ComponentResource, a constructor that creates child resources, and public pulumi.Output properties for the values consumers will reference. The call site in .iac is unchanged from tutorial 18 or 19 — the same component block, the same source path pointing at a local directory, the same component.name.output references. Python or TypeScript or Go, the authoring language is never visible to .iac consumers.

What you’ll learn

  • How to structure a Python ComponentResource for use with ubx
  • The idiomatic Python pattern: ComponentResource + register_outputs()
  • The identical call site across all authoring languages

Why this matters

Python components run through Pulumi’s standard Python SDK — no ubx-specific runtime, no special packaging. A Python component that works standalone in a Pulumi Python project works identically when consumed via ubx.

The source code

# Forward-looking syntax — identical call site regardless of component language.
# ubx v1 local source resolution only supports .iac sources today (UBX-125).
component "database" {
  source         = "./component"
  identifier     = "myapp-${input.env}"
  instance_class = "db.t3.micro"
}

How it works

1

The Python component follows standard Pulumi patterns

super().__init__("ubx:component:RdsDatabase", name, {}, opts) registers the component in Pulumi’s resource graph. Child resources are created with opts=pulumi.ResourceOptions(parent=self). register_outputs() exposes outputs to callers.
2

Typed args via a dataclass-style args class

Python doesn’t have TypeScript’s interface syntax, so a dedicated RdsDatabaseArgs class provides typed, documented inputs. Defaults live in __init__, making the interface clear without requiring keyword-only arguments on the constructor.
3

ubx v1 local resolution: .iac sources only

Identical to the TypeScript case — source = "./component" pointing at a Python directory fails ubx validate today with no .iac files found. This is a forward-looking example showing the correct component structure for when UBX-125 ships.

Identical call site across languages

Compare these three component blocks — all three call the same interface with different implementations behind source:
# .iac component (works today — tutorial 18)
component "database" { source = "./components/rds"  identifier = "myapp-dev" instance_class = "db.t3.micro" }

# TypeScript component (forward-looking — tutorial 19)
component "database" { source = "./component"        identifier = "myapp-dev" instance_class = "db.t3.micro" }

# Python component (forward-looking — this tutorial)
component "database" { source = "./component"        identifier = "myapp-dev" instance_class = "db.t3.micro" }
The call site is syntactically identical. Swapping authoring languages requires no changes to consuming stacks.

Common mistakes

ubx v1 does not resolve local Python component sources. source = "./component" pointing at a directory with only .py files fails ubx validate with internal error: local component "./component": no .iac files found. Use a .iac component (tutorial 18) for local components that need to validate today.
The "ubx:component:RdsDatabase" type URN string passed to super().__init__() appears in Pulumi state and in pulumi stack output --show-urns. Use a consistent naming scheme: "ubx:component:YourComponentName" — same pattern across TypeScript, Python, and Go implementations.

Run it

# ubx validate currently fails for this example (UBX-125 — forward-looking syntax)
ubx validate  # expected: internal error: no .iac files found

What you learned

A Python component extends pulumi.ComponentResource with register_outputs() for outputs
The .iac call site is identical regardless of authoring language
Local Python component resolution is forward-looking in ubx v1 (tracked as UBX-125)

Next steps

Go component

Author the same component in Go

Local .iac component

The fully-supported local component path today