#py-binary
Minimal Python Telepact example that verifies binary negotiation.
Browse the files:
api/binary.telepact.yaml- Telepact schemaserver.py- server implementationtest_example.py- example testMakefile- local run target
Run it:
make run#Source Files
#Makefile
#|
#| Copyright The Telepact Authors
#|
#| Licensed under the Apache License, Version 2.0 (the "License");
#| you may not use this file except in compliance with the License.
#| You may obtain a copy of the License at
#|
#| https://www.apache.org/licenses/LICENSE-2.0
#|
#| Unless required by applicable law or agreed to in writing, software
#| distributed under the License is distributed on an "AS IS" BASIS,
#| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#| See the License for the specific language governing permissions and
#| limitations under the License.
#|
SHELL := /bin/bash
PYTHON := .venv/bin/python
.PHONY: run
run:
@set -euo pipefail; $(MAKE) -C ../../lib/py; rm -rf .venv; uv venv --python python3.11 .venv; uv pip install --python $(PYTHON) pytest ../../lib/py/dist/*.tar.gz; $(PYTHON) -m pytest -q#api/
#api/binary.telepact.yaml
#|
#| Copyright The Telepact Authors
#|
#| Licensed under the Apache License, Version 2.0 (the "License");
#| you may not use this file except in compliance with the License.
#| You may obtain a copy of the License at
#|
#| https://www.apache.org/licenses/LICENSE-2.0
#|
#| Unless required by applicable law or agreed to in writing, software
#| distributed under the License is distributed on an "AS IS" BASIS,
#| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#| See the License for the specific language governing permissions and
#| limitations under the License.
#|
- fn.getNumbers:
limit: "integer"
->:
- Ok_:
values: ["integer"]#server.py
#|
#| Copyright The Telepact Authors
#|
#| Licensed under the Apache License, Version 2.0 (the "License");
#| you may not use this file except in compliance with the License.
#| You may obtain a copy of the License at
#|
#| https://www.apache.org/licenses/LICENSE-2.0
#|
#| Unless required by applicable law or agreed to in writing, software
#| distributed under the License is distributed on an "AS IS" BASIS,
#| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#| See the License for the specific language governing permissions and
#| limitations under the License.
#|
from telepact import FunctionRouter, Message, Server, TelepactSchema, TelepactSchemaFiles
async def get_numbers(function_name: str, request_message: Message) -> Message:
argument = request_message.body[function_name]
limit = argument['limit']
return Message({}, {
'Ok_': {
'values': list(range(1, limit + 1)),
},
})
def build_telepact_server() -> Server:
files = TelepactSchemaFiles('api')
schema = TelepactSchema.from_file_json_map(files.filenames_to_json)
options = Server.Options()
options.auth_required = False
function_router = FunctionRouter({'fn.getNumbers': get_numbers})
return Server(schema, function_router, options)#test_example.py
#|
#| Copyright The Telepact Authors
#|
#| Licensed under the Apache License, Version 2.0 (the "License");
#| you may not use this file except in compliance with the License.
#| You may obtain a copy of the License at
#|
#| https://www.apache.org/licenses/LICENSE-2.0
#|
#| Unless required by applicable law or agreed to in writing, software
#| distributed under the License is distributed on an "AS IS" BASIS,
#| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#| See the License for the specific language governing permissions and
#| limitations under the License.
#|
import asyncio
from telepact import Client, Message, Serializer
from server import build_telepact_server
async def run_example() -> None:
telepact_server = build_telepact_server()
saw_binary_response = False
async def adapter(message: Message, serializer: Serializer) -> Message:
nonlocal saw_binary_response
request_bytes = serializer.serialize(message)
response = await telepact_server.process(request_bytes)
if '@bin_' in response.headers:
saw_binary_response = True
return serializer.deserialize(response.bytes)
options = Client.Options()
options.use_binary = True
options.always_send_json = False
client = Client(adapter, options)
for _ in range(2):
response = await client.request(Message({}, {'fn.getNumbers': {'limit': 3}}))
assert response.body['Ok_']['values'] == [1, 2, 3]
assert saw_binary_response, 'expected at least one binary response'
def test_binary_example_runs_end_to_end() -> None:
asyncio.run(run_example())