diff --git a/content/v4/http-outbound.md b/content/v4/http-outbound.md index 39e663a2..284f5c4f 100644 --- a/content/v4/http-outbound.md +++ b/content/v4/http-outbound.md @@ -176,13 +176,18 @@ You can find a complete example of using outbound HTTP in the JavaScript SDK rep {{ startTab "Python"}} -> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3/http/index.html) +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/http/index.html) -HTTP functions and classes are available in the `http` module. The function name is [`send`](https://spinframework.github.io/spin-python-sdk/v3/http/index.html#spin_sdk.http.send). The [request type](https://spinframework.github.io/spin-python-sdk/http/index.html#spin_sdk.http.Request) is `Request`, and the [response type](https://spinframework.github.io/spin-python-sdk/v3/http/index.html#spin_sdk.http.Response) is `Response`. For example: +HTTP functions and classes are available in the `http` module. The function name is [`send`](https://spinframework.github.io/spin-python-sdk/v4/http/index.html#spin_sdk.http.send). The [request type](https://spinframework.github.io/spin-python-sdk/v4/http/index.html#spin_sdk.http.Request) is `Request`, and the [response type](https://spinframework.github.io/spin-python-sdk/v4/http/index.html#spin_sdk.http.Response) is `Response`. For example: ```python +from spin_sdk import http from spin_sdk.http import Request, Response, send -response = send(Request("GET", "https://random-data-api.fermyon.app/animals/json", {}, None)) + +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + response = await send(Request("GET", "https://random-data-api.fermyon.app/animals/json", {}, None)) + return response ``` **Notes** diff --git a/content/v4/http-trigger.md b/content/v4/http-trigger.md index af9eb6c3..83137f33 100644 --- a/content/v4/http-trigger.md +++ b/content/v4/http-trigger.md @@ -226,16 +226,16 @@ addEventListener('fetch', async (event: FetchEvent) => { {{ startTab "Python"}} -> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3/) +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/) -In Python, the application must define a top-level class named IncomingHandler which inherits from [IncomingHandler](https://spinframework.github.io/spin-python-sdk/v3/http/index.html#spin_sdk.http.IncomingHandler), overriding the `handle_request` method. +In Python, the application must define a top-level class named `HttpHandler` which inherits from [http.Handler](https://spinframework.github.io/spin-python-sdk/v4/http/index.html#spin_sdk.http.Handler), overriding the `handle_request` method. ```python from spin_sdk import http from spin_sdk.http import Request, Response -class IncomingHandler(http.IncomingHandler): - def handle_request(self, request: Request) -> Response: +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: return Response( 200, {"content-type": "text/plain"}, @@ -243,6 +243,8 @@ class IncomingHandler(http.IncomingHandler): ) ``` +You can find a complete example for handling a HTTP request in the [Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/hello). + {{ blockEnd }} {{ startTab "TinyGo"}} diff --git a/content/v4/kv-store-api-guide.md b/content/v4/kv-store-api-guide.md index aa81dd7d..0d7e8f45 100644 --- a/content/v4/kv-store-api-guide.md +++ b/content/v4/kv-store-api-guide.md @@ -123,19 +123,19 @@ addEventListener('fetch', async (event: FetchEvent) => { {{ startTab "Python"}} -> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3/key_value.html) +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/key_value.html) -The key value functions are provided through the `spin_key_value` module in the Python SDK. For example: +The key value functions are provided through the `key_value` module in the Python SDK. For example: ```python from spin_sdk import http, key_value from spin_sdk.http import Request, Response -class IncomingHandler(http.IncomingHandler): - def handle_request(self, request: Request) -> Response: - with key_value.open_default() as store: - store.set("test", bytes("hello world!", "utf-8")) - val = store.get("test") +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + with await key_value.open_default() as store: + await store.set("test", bytes("hello world!", "utf-8")) + val = await store.get("test") return Response( 200, @@ -148,8 +148,31 @@ class IncomingHandler(http.IncomingHandler): **General Notes** - The Python SDK doesn't surface the `close` operation. It automatically closes all stores at the end of the request; there's no way to close them early. -[`get` **Operation**](https://spinframework.github.io/spin-python-sdk/v3/wit/imports/key_value.html#spin_sdk.wit.imports.key_value.Store.get) -- If a key does not exist, it returns `None` +- To open the default key-value store, you can use the [`key_value.open_default`](https://spinframework.github.io/spin-python-sdk/v4/key_value.html#spin_sdk.key_value.open_default) function. You can use [`key_value.open`](https://spinframework.github.io/spin-python-sdk/v4/key_value.html#spin_sdk.key_value.open) to open any store by label. + +- Below is a breakdown of the methods surfaced directly from the underlying [spin-key-value-3.0.0 WIT definition](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_key_value_key_value_3_0_0.html): + + [`open` **Operation**](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_key_value_key_value_3_0_0.html#spin_sdk.wit.imports.spin_key_value_key_value_3_0_0.Store.open) + - Open the store with the specified label + + [`get` **Operation**](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_key_value_key_value_3_0_0.html#spin_sdk.wit.imports.spin_key_value_key_value_3_0_0.Store.get) + - If a key does not exist, it returns `None` + + [`set` **Operation**](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_key_value_key_value_3_0_0.html#spin_sdk.wit.imports.spin_key_value_key_value_3_0_0.Store.set) + - Sets a value associated with the specified key, overwriting any existing value. + + [`delete` **Operation**](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_key_value_key_value_3_0_0.html#spin_sdk.wit.imports.spin_key_value_key_value_3_0_0.Store.delete) + - Deletes the specified item from the store + + [`exists` **Operation**](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_key_value_key_value_3_0_0.html#spin_sdk.wit.imports.spin_key_value_key_value_3_0_0.Store.exists) + - Return whether the specified key is present in the store + + [`get_keys` **Operation**](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_key_value_key_value_3_0_0.html#spin_sdk.wit.imports.spin_key_value_key_value_3_0_0.Store.get_keys) + - Returns a `Tuple` containing a [StreamReader](https://github.com/bytecodealliance/componentize-py/blob/1b3d2e936868307a48fb70941dcad71b54e844f8/bundled/componentize_py_async_support/streams.py#L101) and a [FutureReader](https://github.com/bytecodealliance/componentize-py/blob/1b3d2e936868307a48fb70941dcad71b54e844f8/bundled/componentize_py_async_support/futures.py#L11). You _must_ check when the stream ends, to determine if the stream ended normally, or was terminated prematurely due to an error. + + > If you're familiar with previous versions of the Python SDK, note that `get_keys` no longer returns a list. To get the keys as a list, use `await util.collect(await store.get_keys())`. See [collect](https://spinframework.github.io/spin-python-sdk/v4/util.html#spin_sdk.util.collect) for more details. + +You can find a complete Python code example using the Key Value store in the [Spin Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-kv). {{ blockEnd }} diff --git a/content/v4/language-support-overview.md b/content/v4/language-support-overview.md index b175845c..847b16a9 100644 --- a/content/v4/language-support-overview.md +++ b/content/v4/language-support-overview.md @@ -61,7 +61,7 @@ This page contains information about language support for Spin features: {{ startTab "Python"}} -**[📄 Visit the Python Spin SDK reference documentation](https://spinframework.github.io/spin-python-sdk/v3) to see specific modules, functions, variables and syntax relating to the following Python SDK.** +**[📄 Visit the Python Spin SDK reference documentation](https://spinframework.github.io/spin-python-sdk/v4) to see specific modules, functions, variables and syntax relating to the following Python SDK.** | Feature | SDK Supported? | |-----|-----| @@ -77,7 +77,7 @@ This page contains information about language support for Spin features: | PostgreSQL | Supported | | [Outbound Redis](./python-components#an-outbound-redis-example) | Supported | | [Serverless AI](./serverless-ai-api-guide) | Supported | -| [MQTT Messaging](./mqtt-outbound) | Not Supported | +| [MQTT Messaging](./mqtt-outbound) | Supported | | **Extensibility** | | Authoring Custom Triggers | Not Supported | diff --git a/content/v4/mqtt-outbound.md b/content/v4/mqtt-outbound.md index fe7cdb81..0bd78b88 100644 --- a/content/v4/mqtt-outbound.md +++ b/content/v4/mqtt-outbound.md @@ -82,7 +82,24 @@ You can find a complete Rust code example for using outbound MQTT from an HTTP c {{ startTab "Python"}} -MQTT is not available in the current version of the Python SDK. +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/mqtt.html) + +To access an MQTT server, use the `open` function. You can then call the `publish` method on the connection to send MQTT messages: + +```python +from spin_sdk import http, mqtt +from spin_sdk.mqtt import Qos +from spin_sdk.http import Request, Response + +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + with await mqtt.open("mqtt://localhost:1883?client_id=client001", "user", "password", 30) as conn: + await conn.publish("telemetry", bytes("Eureka!", "utf-8"), Qos.AT_LEAST_ONCE) +``` + +For full details of the MQTT API, see the [Spin SDK reference documentation](https://spinframework.github.io/spin-python-sdk/v4/mqtt.html) + +You can find a complete Python code example for using outbound MQTT from an HTTP component in the [Spin Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-outbound-mqtt). {{ blockEnd }} diff --git a/content/v4/python-components.md b/content/v4/python-components.md index a73fd65b..fd9f1ad7 100644 --- a/content/v4/python-components.md +++ b/content/v4/python-components.md @@ -35,7 +35,7 @@ With Python being a very p > This guide assumes you are familiar with the Python programming language, but if you are just getting started, be sure to check out the official Python documentation and comprehensive language reference. -[**Want to go straight to the Spin SDK reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3) +[**Want to go straight to the Spin SDK reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4) ## Prerequisite @@ -49,7 +49,7 @@ If you do not have Python 3.10 or later, you can install it by following the ins ## Spin's Python HTTP Request Handler Template -Spin's Python HTTP Request Handler Template can be installed from [spin-python-sdk repository](https://github.com/spinframework/spin-python-sdk/tree/main/) using the following command: +Spin's Python HTTP Request Handler Template can be installed from [spin-python-sdk repository](https://github.com/spinframework/spin-python-sdk) using the following command: @@ -170,22 +170,22 @@ component = "hello-world" [component.hello-world] source = "app.wasm" [component.hello-world.build] -command = "componentize-py -w spin-http componentize app -o app.wasm" +command = "componentize-py -w spin:up/http-trigger@4.0.0 componentize app -o app.wasm" ``` ## A Simple HTTP Components Example In Spin, HTTP components are triggered by the occurrence of an HTTP request and must return an HTTP response at the end of their execution. Components can be built in any language that compiles to WASI. If you would like additional information about building HTTP applications you may find [the HTTP trigger page](./http-trigger.md) useful. -Building a Spin HTTP component using the Python SDK means defining a top-level class named IncomingHandler which inherits from [`IncomingHandler`](https://spinframework.github.io/spin-python-sdk/v3/wit/exports/index.html#spin_sdk.wit.exports.IncomingHandler), overriding the `handle_request` method. Here is an example of the default Python code which the previous `spin new` created for us; a simple example of a request/response: +Building a Spin HTTP component using the Python SDK means defining a top-level class named HttpHandler which inherits from [`HttpHandler`](https://spinframework.github.io/spin-python-sdk/v4/wit/exports/index.html#spin_sdk.wit.exports.HttpHandler), overriding the `handle_request` method. Here is an example of the default Python code which the previous `spin new` created for us; a simple example of a request/response: ```python -from spin_sdk.http import IncomingHandler, Request, Response +from spin_sdk.http import Handler, Request, Response -class IncomingHandler(IncomingHandler): - def handle_request(self, request: Request) -> Response: +class HttpHandler(Handler): + async def handle_request(self, request: Request) -> Response: return Response( 200, {"content-type": "text/plain"}, @@ -241,8 +241,8 @@ import json from spin_sdk import http from spin_sdk.http import Request, Response -class IncomingHandler(http.IncomingHandler): - def handle_request(self, request: Request) -> Response: +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: # Access the request.method if request.method == 'POST': # Read the request.body as a string @@ -330,14 +330,15 @@ This next example will create an outbound request, to obtain a random fact about from spin_sdk import http from spin_sdk.http import Request, Response, send -class IncomingHandler(http.IncomingHandler): - def handle_request(self, request: Request) -> Response: - resp = send(Request("GET", "https://random-data-api.fermyon.app/animals/json", {}, None)) - - return Response(200, - {"content-type": "text/plain"}, - bytes(f"Here is an animal fact: {str(resp.body, 'utf-8')}", "utf-8")) +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + resp = await send(Request("GET", "https://random-data-api.fermyon.app/animals/json", {}, None)) + return Response( + 200, + {"content-type": "text/plain"}, + bytes(f"Here is an animal fact: {str(resp.body, 'utf-8')}", "utf-8") + ) ``` ### Configuring Outbound Requests @@ -363,7 +364,7 @@ component = "hello-world" source = "app.wasm" allowed_outbound_hosts = ["https://random-data-api.fermyon.app"] [component.hello-world.build] -command = "componentize-py -w spin-http componentize app -o app.wasm" +command = "componentize-py -w spin:up/http-trigger@4.0.0 componentize app -o app.wasm" watch = ["*.py", "requirements.txt"] ``` @@ -418,12 +419,11 @@ route = "/..." component = "hello-world" [component.hello-world] -id = "hello-world" source = "app.wasm" variables = { redis_address = "redis://127.0.0.1:6379" } allowed_outbound_hosts = ["redis://127.0.0.1:6379"] [component.hello-world.build] -command = "spin py2wasm app -o app.wasm" +command = "componentize-py -w spin:up/http-trigger@4.0.0 componentize app -o app.wasm" ``` If you are still following along, please go ahead and update your `app.py` file one more time, as follows: @@ -434,20 +434,22 @@ If you are still following along, please go ahead and update your `app.py` file from spin_sdk import http, redis, variables from spin_sdk.http import Request, Response -class IncomingHandler(http.IncomingHandler): - def handle_request(self, request: Request) -> Response: - with redis.open(variables.get("redis_address")) as db: - db.set("foo", b"bar") - value = db.get("foo") - db.incr("testIncr") - db.sadd("testSets", ["hello", "world"]) - content = db.smembers("testSets") - db.srem("testSets", ["hello"]) +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + with await redis.open(await variables.get("redis_address")) as db: + await db.set("foo", b"bar") + value = await db.get("foo") + await db.incr("testIncr") + await db.sadd("testSets", ["hello", "world"]) + content = await db.smembers("testSets") + await db.srem("testSets", ["hello"]) assert value == b"bar", f"expected \"bar\", got \"{str(value, 'utf-8')}\"" - return Response(200, - {"content-type": "text/plain"}, - bytes(f"Executed outbound Redis commands: {request.uri}", "utf-8")) + return Response( + 200, + {"content-type": "text/plain"}, + bytes(f"Executed outbound Redis commands: {request.uri}", "utf-8") + ) ``` ### Building and Running the Application diff --git a/content/v4/quickstart.md b/content/v4/quickstart.md index 13df9495..1dfaf4fa 100644 --- a/content/v4/quickstart.md +++ b/content/v4/quickstart.md @@ -498,14 +498,14 @@ The `requirements.txt`, by default, contains the references to the `spin-sdk` an ```bash $ pip3 install -r requirements.txt -Collecting spin-sdk==3.1.0 (from -r requirements.txt (line 1)) - Using cached spin_sdk-3.1.0-py3-none-any.whl.metadata (16 kB) -Collecting componentize-py==0.13.3 (from -r requirements.txt (line 2)) - Using cached componentize_py-0.13.3-cp37-abi3-macosx_10_12_x86_64.whl.metadata (3.4 kB) -Using cached spin_sdk-3.1.0-py3-none-any.whl (94 kB) -Using cached componentize_py-0.13.3-cp37-abi3-macosx_10_12_x86_64.whl (38.8 MB) +Collecting spin-sdk==4.0.0 (from -r requirements.txt (line 1)) + Using cached spin_sdk-4.0.0-py3-none-any.whl.metadata (16 kB) +Collecting componentize-py==0.22.0 (from -r requirements.txt (line 2)) + Using cached componentize_py-0.22.0-cp37-abi3-macosx_10_12_x86_64.whl.metadata (3.4 kB) +Using cached spin_sdk-4.0.0-py3-none-any.whl (94 kB) +Using cached componentize_py-0.22.0-cp37-abi3-macosx_10_12_x86_64.whl (38.8 MB) Installing collected packages: spin-sdk, componentize-py -Successfully installed componentize-py-0.13.3 spin-sdk-3.1.0 +Successfully installed componentize-py-0.22.0 spin-sdk-4.0.0 ``` ## Structure of a Python Component @@ -540,7 +540,8 @@ component = "hello-python" [component.hello-python] source = "app.wasm" [component.hello-python.build] -command = "componentize-py -w spin-http componentize app -o app.wasm" +command = "componentize-py -w spin:up/http-trigger@4.0.0 componentize app -o app.wasm" +watch = ["*.py", "requirements.txt"] ``` This represents a simple Spin HTTP application (triggered by an HTTP request). It has: @@ -556,14 +557,14 @@ takes an HTTP request as a parameter and returns an HTTP response. ```python -from spin_sdk.http import IncomingHandler, Request, Response +from spin_sdk.http import Handler, Request, Response -class IncomingHandler(IncomingHandler): - def handle_request(self, request: Request) -> Response: +class HttpHandler(Handler): + async def handle_request(self, request: Request) -> Response: return Response( 200, {"content-type": "text/plain"}, - bytes("Hello from the Python SDK!", "utf-8") + bytes("Hello from Python!", "utf-8") ) ``` @@ -782,7 +783,8 @@ Then run: ```bash $ spin build -Executing the build command for component hello-python: "componentize-py -w spin-http componentize app -o app.wasm" +Building component hello-python with `componentize-py -w spin:up/http-trigger@4.0.0 componentize app -o app.wasm +Component built successfully Finished building all Spin components ``` @@ -796,7 +798,7 @@ If you would like to know what build command Spin runs for a component, you can ```toml [component.hello-python.build] -command = "componentize-py -w spin-http componentize app -o app.wasm" +command = "componentize-py -w spin:up/http-trigger@4.0.0 componentize app -o app.wasm" ``` You can always run this command manually; `spin build` is a shortcut. diff --git a/content/v4/rdbms-storage.md b/content/v4/rdbms-storage.md index 96d2d9a3..5ebf276d 100644 --- a/content/v4/rdbms-storage.md +++ b/content/v4/rdbms-storage.md @@ -144,20 +144,19 @@ addEventListener('fetch', async (event: FetchEvent) => { {{ startTab "Python"}} -> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3/) +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/) -The code below is an [Outbound MySQL example](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-mysql). There is also an outbound [PostgreSQL example](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-postgres) available. +The code below shows use of the [Postgres](https://spinframework.github.io/spin-python-sdk/v4/postgres.html) module and its [open](https://spinframework.github.io/spin-python-sdk/v4/postgres.html#spin_sdk.postgres.open) function for opening a connection to the database: ```python -from spin_sdk import http +from spin_sdk import http, postgres from spin_sdk.http import Request, Response -from spin_sdk import mysql -class IncomingHandler(http.IncomingHandler): - def handle_request(self, request: Request) -> Response: - with mysql.open("mysql://root:@127.0.0.1/spin_dev") as db: - print(db.query("select * from test", [])) - +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + with await postgres.open("user=postgres dbname=spin_dev host=localhost sslmode=disable password=password") as db: + print(db.query("SELECT * FROM test", [])) + return Response( 200, {"content-type": "text/plain"}, @@ -165,6 +164,8 @@ class IncomingHandler(http.IncomingHandler): ) ``` +You can find a complete outbound PostgreSQL example in the [Spin Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-postgres). There is also an [Outbound MySQL example](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-mysql) available. + {{ blockEnd }} {{ startTab "TinyGo"}} diff --git a/content/v4/redis-outbound.md b/content/v4/redis-outbound.md index fe73b1cb..f74f295d 100644 --- a/content/v4/redis-outbound.md +++ b/content/v4/redis-outbound.md @@ -115,23 +115,30 @@ You can find a complete TypeScript example for using outbound Redis from an HTTP {{ startTab "Python"}} -> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3/redis.html) +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/redis.html) -Redis functions are available in [the `redis` module](https://spinframework.github.io/spin-python-sdk/v3/redis.html). The function names are prefixed `redis_`. You must pass the Redis instance address to _each_ operation as its first parameter. For example: +Redis functions are available in [the `redis` module](https://spinframework.github.io/spin-python-sdk/v4/redis.html). + +To open a connection to a Redis instance, use the `redis.open` function. You can then call methods on the connection object to work with the Redis instance. For example: ```python -from spin_sdk import redis -with redis.open("redis://localhost:6379") as db: - val = db.get("test") +from spin_sdk import http, redis +from spin_sdk.http import Request, Response + +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + with await redis.open("redis://localhost:6379") as db: + print(await db.get("test")) ``` **General Notes** * Address and key parameters are strings (`str`). -* Bytes parameters and return values are `bytes`. (You can pass literal strings using the `b` prefix, e.g. `redis_set(address, key, b"hello")`.) -* Numeric return values are of type `int64`. +* Bytes parameters and return values are `bytes`. (You can pass literal strings using the `b` prefix, e.g. `set(key, b"hello")`.) +* Numeric return values are of type `int`. * Lists are passed and returned as Python lists. * Errors are signalled through exceptions. +* For a deep dive into the all of the methods available from this module, see the [spin_redis_3.0.0 WIT documentation](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_redis_redis_3_0_0.html). You can find a complete Python code example for using outbound Redis from an HTTP component in the [Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-redis). Please also see this, related, [outbound Redis (using Python) section](./python-components#an-outbound-redis-example). diff --git a/content/v4/redis-trigger.md b/content/v4/redis-trigger.md index 1975b388..d7ddf05d 100644 --- a/content/v4/redis-trigger.md +++ b/content/v4/redis-trigger.md @@ -94,15 +94,18 @@ The JavaScript/TypeScript SDK doesn't currently support Redis components. Pleas {{ startTab "Python"}} -In Python, the handler needs to implement the [`InboundRedis`](https://spinframework.github.io/spin-python-sdk/v3/wit/exports/index.html#spin_sdk.wit.exports.InboundRedis) class, and override the `handle_message` method: +In Python, the handler needs to implement the [`RedisHandler`](https://spinframework.github.io/spin-python-sdk/v4/wit/exports/index.html#spin_sdk.wit.exports.RedisHandler) class, and override the `handle_message` method: ```python from spin_sdk.wit import exports -class InboundRedis(exports.InboundRedis): - def handle_message(self, message: bytes): + +class RedisHandler(exports.RedisHandler): + async def handle_message(self, message: bytes) -> None: print(message) ``` +You can find a complete Python code example using the Redis trigger in the [Spin Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/redis-trigger). + {{ blockEnd }} {{ startTab "TinyGo"}} diff --git a/content/v4/serverless-ai-api-guide.md b/content/v4/serverless-ai-api-guide.md index 3812e970..b8a23700 100644 --- a/content/v4/serverless-ai-api-guide.md +++ b/content/v4/serverless-ai-api-guide.md @@ -158,30 +158,33 @@ addEventListener('fetch', async (event: FetchEvent) => { {{ startTab "Python"}} -> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3/llm.html) +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/llm.html) ```python -from spin_sdk import http +from spin_sdk import http, llm from spin_sdk.http import Request, Response -from spin_sdk import llm -class IncomingHandler(http.IncomingHandler): - def handle_request(self, request: Request) -> Response: +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: prompt="You are a stand up comedy writer. Tell me a joke." result = llm.infer("llama2-chat", prompt) - return Response(200, - {"content-type": "application/json"}, - bytes(result.text, "utf-8")) + + return Response( + 200, + {"content-type": "text/plain"}, + bytes(result.text, "utf-8") + ) ``` **General Notes** -[`infer` operation](https://spinframework.github.io/spin-python-sdk/v3/llm.html#spin_sdk.llm.infer): - +[`infer` operation](https://spinframework.github.io/spin-python-sdk/v4/llm.html#spin_sdk.llm.infer): - The model name is passed in as a string (as shown above; `"llama2-chat"`). -[`infer_with_options` operation](https://spinframework.github.io/spin-python-sdk/v3/llm.html#spin_sdk.llm.infer_with_options): -- It takes in a model name, prompt text, and optionally a [parameter object](https://spinframework.github.io/spin-python-sdk/v3/llm.html#spin_sdk.llm.InferencingParams) to control the inferencing. +[`infer_with_options` operation](https://spinframework.github.io/spin-python-sdk/v4/llm.html#spin_sdk.llm.infer_with_options): +- It takes in a model name, prompt text, and optionally a [parameter object](https://spinframework.github.io/spin-python-sdk/v4/llm.html#spin_sdk.llm.InferencingParams) to control the inferencing. + +You can find a complete Python code example using the LLM module in the [Spin Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-llm). {{ blockEnd }} diff --git a/content/v4/sqlite-api-guide.md b/content/v4/sqlite-api-guide.md index a4c59ff5..0b81396e 100644 --- a/content/v4/sqlite-api-guide.md +++ b/content/v4/sqlite-api-guide.md @@ -156,19 +156,19 @@ addEventListener('fetch', async (event: FetchEvent) => { {{ startTab "Python"}} -> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3/sqlite.html) +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/sqlite.html) -To use SQLite functions, use the `sqlite` module in the Python SDK. The [`sqlite_open`](https://spinframework.github.io/spin-python-sdk/v3/sqlite.html#spin_sdk.sqlite.open) and [`sqlite_open_default`](https://spinframework.github.io/spin-python-sdk/v3/sqlite.html#spin_sdk.sqlite.open_default) functions return a [connection object](https://spinframework.github.io/spin-python-sdk/v3/wit/imports/sqlite.html#spin_sdk.wit.imports.sqlite.Connection). The connection object provides the [`execute` method](https://spinframework.github.io/spin-python-sdk/v3/wit/imports/sqlite.html#spin_sdk.wit.imports.sqlite.Connection.execute) as described above. For example: +To use SQLite functions, use the `sqlite` module in the Python SDK. The [`open`](https://spinframework.github.io/spin-python-sdk/v4/sqlite.html#spin_sdk.sqlite.open) and [`open_default`](https://spinframework.github.io/spin-python-sdk/v4/sqlite.html#spin_sdk.sqlite.open_default) functions return a [`Connection` object](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_sqlite_sqlite_3_1_0.html#spin_sdk.wit.imports.spin_sqlite_sqlite_3_1_0.Connection). The `Connection` object provides the [`execute` method](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_sqlite_sqlite_3_1_0.html#spin_sdk.wit.imports.spin_sqlite_sqlite_3_1_0.Connection.execute) as described above. For example: ```python from spin_sdk import http, sqlite from spin_sdk.http import Request, Response -from spin_sdk.sqlite import ValueInteger +from spin_sdk.sqlite import Value_Integer -class IncomingHandler(http.IncomingHandler): - def handle_request(self, request: Request) -> Response: - with sqlite.open_default() as db: - result = db.execute("SELECT * FROM todos WHERE id > (?);", [ValueInteger(1)]) +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + with await sqlite.open_default() as db: + result = db.execute("SELECT * FROM todos WHERE id > (?);", [Value_Integer(1)]) rows = result.rows return Response( @@ -179,10 +179,12 @@ class IncomingHandler(http.IncomingHandler): ``` **General Notes** -* The `execute` method returns [a `QueryResult` object](https://spinframework.github.io/spin-python-sdk/v3/wit/imports/sqlite.html#spin_sdk.wit.imports.sqlite.QueryResult) with `rows` and `columns` methods. `columns` returns a list of strings representing column names. `rows` is an array of rows, each of which is an array of [`RowResult`](https://spinframework.github.io/spin-python-sdk/v3/wit/imports/sqlite.html#spin_sdk.wit.imports.sqlite.RowResult) in the same order as `columns`. -* The connection object doesn't surface the `close` function. +* The `execute` method returns [a `QueryResult` object](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_sqlite_sqlite_3_1_0.html#spin_sdk.wit.imports.spin_sqlite_sqlite_3_1_0.QueryResult) with `rows` and `columns` methods. `columns` returns a list of strings representing column names. `rows` is an array of rows, each of which is an array of [`RowResult`](https://spinframework.github.io/spin-python-sdk/v4/wit/imports/spin_sqlite_sqlite_3_1_0.html#spin_sdk.wit.imports.spin_sqlite_sqlite_3_1_0.RowResult) in the same order as `columns`. +* The `Connection` object doesn't surface the `close` function. * Errors are surfaced as exceptions. +You can find a complete Python code example using SQLite storage in the [Spin Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-sqlite). + {{ blockEnd }} {{ startTab "TinyGo"}} diff --git a/content/v4/variables.md b/content/v4/variables.md index ccc9ab67..44d7f1bd 100644 --- a/content/v4/variables.md +++ b/content/v4/variables.md @@ -173,24 +173,24 @@ addEventListener('fetch', async (event: FetchEvent) => { {{ startTab "Python"}} -> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v3/variables.html) +> [**Want to go straight to the reference documentation?** Find it here.](https://spinframework.github.io/spin-python-sdk/v4/variables.html) -The `variables` module has a function called `get`(https://spinframework.github.io/spin-python-sdk/v3/variables.html#spin_sdk.variables.get). +The `variables` module has a function called `get`(https://spinframework.github.io/spin-python-sdk/v4/variables.html#spin_sdk.variables.get). ```py -from spin_sdk.http import IncomingHandler, Request, Response, send -from spin_sdk import variables - -class IncomingHandler(IncomingHandler): - def handle_request(self, request: Request) -> Response: - token = variables.get("token") - api_uri = variables.get("api_uri") - version = variables.get("version") +from spin_sdk import http, variables +from spin_sdk.http import Request, Response + +class HttpHandler(http.Handler): + async def handle_request(self, request: Request) -> Response: + token = await variables.get("token") + api_uri = await variables.get("api_uri") + version = await variables.get("version") versioned_api_uri = f"{api_uri}/{version}" headers = { "Authorization": f"Bearer {token}" } - response = send(Request("GET", versioned_api_uri, headers, None)) + response = await send(Request("GET", versioned_api_uri, headers, None)) # Do something with the response ... return Response( 200, @@ -199,6 +199,8 @@ class IncomingHandler(IncomingHandler): ) ``` +You can find a complete Python code example using Variables in the [Spin Python SDK repository on GitHub](https://github.com/spinframework/spin-python-sdk/tree/main/examples/spin-variables). + {{ blockEnd }} {{ startTab "TinyGo"}} diff --git a/content/v4/writing-apps.md b/content/v4/writing-apps.md index a0bde37a..109dcc82 100644 --- a/content/v4/writing-apps.md +++ b/content/v4/writing-apps.md @@ -217,7 +217,7 @@ HTTP path: /... Choose the `http-py` template to create a new HTTP application. -> The Python development kit doesn't yet support Redis applications. +> The Python development kit doesn't yet offer a Redis application template.