Skip to content

Commit c9a59fb

Browse files
refactor(lang/py): Revise Python language support section (#312)
* Revise Python language support section * Add explicit steps to create needed directories/files * Move code examples into separate files * Make the "example host" section consistent with the other language support sections * Clarify comment about `--stub-wasi` option (made it clearer that it's an option passed to `componentize-py`) * fix(lang/py): wording of tooling --------- Co-authored-by: Victor Adossi <[email protected]>
1 parent 519a0c5 commit c9a59fb

File tree

3 files changed

+65
-40
lines changed

3 files changed

+65
-40
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from wit_world import exports
2+
3+
class Add(exports.Add):
4+
def add(self, x: int, y: int) -> int:
5+
return x + y
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from add import Root
2+
from wasmtime import Store
3+
4+
def main():
5+
store = Store()
6+
component = Root(store)
7+
print("1 + 2 =", component.add(store, 1, 2))
8+
9+
if __name__ == '__main__':
10+
main()

component-model/src/language-support/python.md

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,38 @@
22

33
## Building a Component with `componentize-py`
44

5-
[`componentize-py`](https://github.com/bytecodealliance/componentize-py) is a tool that converts a Python
5+
[`componentize-py`](https://github.com/bytecodealliance/componentize-py) is a tool
6+
that converts a Python
67
application to a WebAssembly component.
78

8-
First, install [Python 3.10 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/) if you don't already have them. Then, install `componentize-py`:
9+
First, install [Python 3.10 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/)
10+
if you don't already have them. Then, install `componentize-py`:
911

1012
```sh
1113
pip install componentize-py
1214
```
1315

14-
Next, create or download the WIT world you would like to target. For this example we will use an [`adder`
15-
world][adder-wit] with an `add` function (e.g. `wit/component.wit`):
16+
Next, create or download the WIT world you would like to target.
17+
For this example we will use an [`adder` world][adder-wit] with an `add` function.
1618

1719
```wit
1820
{{#include ../../examples/tutorial/wit/adder/world.wit}}
1921
```
2022

21-
If you want to generate bindings produced for the WIT world (for an IDE or typechecker), you can generate them using the `bindings` subcommand. Specify the path to the WIT interface with the world you are targeting:
23+
Create a new directory for your project and create a subdirectory in it called `wit`.
24+
Copy and paste this code into a file named `wit/component.wit`.
25+
26+
If you want to generate bindings for the WIT world (for an IDE or typechecker),
27+
you can generate them using the `bindings` subcommand.
28+
Specify the path to the WIT interface with the world you are targeting:
2229

2330
```console
2431
componentize-py --wit-path wit --world adder bindings .
2532
```
2633

2734
> [!NOTE]
28-
> You do not need to generate the bindings in order to `componentize` in the next step. `componentize` will generate bindings on-the-fly and bundle them into the produced component.
35+
> You do not need to generate the bindings in order to `componentize` in the next step.
36+
>`componentize` will generate bindings on-the-fly and bundle them into the produced component.
2937
>
3038
> If you attempt to run bindings generation twice, it will fail if the `bindings` folder already exists.
3139
@@ -46,18 +54,14 @@ Bindings are generated in a folder called `wit_world` by default:
4654
The `wit_world/exports` folder contains an `Add` protocol which has an `add` method that we can implement,
4755
which represents the export defined in the `adder` world WIT.
4856

49-
To implement the `adder` world (in particular the `add` interface that is exported), put the following code
50-
in a file called `app.py`:
57+
To implement the `adder` world (in particular the `add` interface that is exported),
58+
put the following code in a file called `app.py`:
5159

5260
```py
53-
from wit_world import exports
54-
55-
class Add(exports.Add):
56-
def add(self, x: int, y: int) -> int:
57-
return x + y
61+
{{#include ../../examples/tutorial/python/app.py}}
5862
```
5963

60-
We now can compile our application to a Wasm component using the `componentize` subcommand:
64+
We now can compile our application to a WebAssembly component using the `componentize` subcommand:
6165

6266
```console
6367
componentize-py \
@@ -69,54 +73,60 @@ componentize-py \
6973
Component built successfully
7074
```
7175

72-
To test the component, run it using the [Rust `add` host](./rust.md#creating-a-command-component-with-cargo-component):
76+
## Running components from the example host
7377

74-
```sh
75-
$ cd component-model/examples/add-host
76-
$ cargo run --release -- 1 2 ../path/to/add.wasm
77-
1 + 2 = 3
78-
```
78+
The following section requires you to have [a Rust toolchain][rust] installed.
79+
80+
{{#include example-host-part1.md}}
7981

80-
See [`componentize-py`'s examples](https://github.com/bytecodealliance/componentize-py/tree/main/examples) to try out build HTTP, CLI, and TCP components from Python applications.
82+
A successful run should show the following output
83+
(of course, the paths to your example host and adder component will vary):
84+
85+
{{#include example-host-part2.md}}
86+
87+
[rust]: https://www.rust-lang.org/learn/get-started
88+
89+
See [`componentize-py`'s examples](https://github.com/bytecodealliance/componentize-py/tree/main/examples)
90+
to try out building HTTP, CLI, and TCP components from Python applications.
8191

8292
## Running components from Python Applications
8393

84-
Wasm components can also be invoked from Python applications. This section walks through using tooling
85-
to call the [pre-built `app.wasm` component][add-wasm] in the examples.
94+
WebAssembly components can also be invoked from Python applications.
95+
This section walks through using python native tooling to call the [pre-built `add.wasm` component][add-wasm] in the examples.
8696

87-
> `wasmtime-py` is only able to run components built with `componentize-py` when the `--stub-wasi` option is used at build time. This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources), and `componentize-py` by default generates components which use resources from the `wasi:cli` world. See [this example](https://github.com/bytecodealliance/componentize-py/tree/main/examples/sandbox) of using the `--stub-wasi` option to generate a `wasmtime-py`-compatible component.
97+
> To use `wasmtime-py` to run a component built with `componentize-py`,
98+
> the `--stub-wasi` option must have been passed to `componentize-py`
99+
> when the component was built.
100+
> This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources),
101+
> and `componentize-py` by default generates components which use resources from the `wasi:cli` world.
102+
> See [this example](https://github.com/bytecodealliance/componentize-py/tree/main/examples/sandbox)
103+
> of using the `--stub-wasi` option to generate a `wasmtime-py`-compatible component.
88104

89-
First, install [Python 3.11 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/) if you don't already have them. Then, install [`wasmtime-py`](https://github.com/bytecodealliance/wasmtime-py):
105+
First, install [Python 3.11 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/) if you don't already have them.
106+
Then, install [`wasmtime-py`](https://github.com/bytecodealliance/wasmtime-py):
90107

91108
```sh
92109
$ pip install wasmtime
93110
```
94111

95112
First, generate the bindings to be able to call the component from a Python host application.
113+
If necessary, remove your `add.wasm` file that you generated in the previous section.
96114

97115
```sh
98116
# Get an add component that does not import the WASI CLI world
99117
$ wget https://github.com/bytecodealliance/component-docs/raw/main/component-model/examples/example-host/add.wasm
100118
$ python3 -m wasmtime.bindgen add.wasm --out-dir add
101119
```
102120

103-
The generated package `add` has all of the requisite exports/imports for the
104-
component and is annotated with types to assist with type-checking and
105-
self-documentation as much as possible. Inside the package is a `Root` class
106-
with an `add` function that calls the component's exported `add` function. We
107-
can now write a Python program that calls `add`:
121+
The generated package `add` has all of the requisite exports/imports for the component
122+
and is annotated with types to assist with type-checking and self-documentation as much as possible.
123+
Inside the package is a `Root` class with an `add` function
124+
that calls the component's exported `add` function.
125+
We can now write a Python program that calls `add`.
126+
Copy/paste the following code into a file called `host.py`:
108127

109128
```py
110-
from add import Root
111-
from wasmtime import Store
112-
113-
def main():
114-
store = Store()
115-
component = Root(store)
116-
print("1 + 2 =", component.add(store, 1, 2))
117-
118-
if __name__ == '__main__':
119-
main()
129+
{{#include ../../examples/tutorial/python/host.py}}
120130
```
121131

122132
Run the Python host program:

0 commit comments

Comments
 (0)