Skip to content

Commit

Permalink
fix: update to latest extism_sys
Browse files Browse the repository at this point in the history
The newest version of `extism_plugin_new` consumes function metadata generated
by `extism_function_new`. Move the `extism_function_new` call to
plugin instantiation time to fix this.

Additionally, edit `pyproject.toml` to support running with `uv`.
  • Loading branch information
chrisdickinson committed Nov 21, 2024
1 parent 6c5e88c commit 4e5051d
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 43 deletions.
57 changes: 27 additions & 30 deletions extism/extism.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import json
import os
from base64 import b64encode
from cffi import FFI
import typing
from typing import (
get_args,
Expand All @@ -18,7 +17,6 @@
from enum import Enum
from uuid import UUID
from extism_sys import lib as _lib, ffi as _ffi # type: ignore
from annotated_types import Gt
import functools
import pickle

Expand Down Expand Up @@ -242,32 +240,32 @@ class Function:
A host function.
"""

def __init__(self, name: str, args, returns, f, *user_data):
self.pointer = None
args = [a.value for a in args]
returns = [r.value for r in returns]
def __init__(self, namespace: str | None, name: str, args, returns, f, *user_data):
self.namespace = namespace
self.name = name
self.args = [a.value for a in args]
self.returns = [r.value for r in returns]
if len(user_data) > 0:
self.user_data = _ffi.new_handle(user_data)
else:
self.user_data = _ffi.NULL
self.f = f


class _ExtismFunctionMetadata:
def __init__(self, f: Function):
self.pointer = _lib.extism_function_new(
name.encode(),
args,
len(args),
returns,
len(returns),
f,
self.user_data,
f.name.encode(),
f.args,
len(f.args),
f.returns,
len(f.returns),
f.f,
f.user_data,
_ffi.NULL,
)

def set_namespace(self, name: str):
_lib.extism_function_set_namespace(self.pointer, name.encode())

def with_namespace(self, name: str):
self.set_namespace(name)
return self
if f.namespace is not None:
_lib.extism_function_set_namespace(self.pointer, f.namespace.encode())

def __del__(self):
if not hasattr(self, "pointer"):
Expand Down Expand Up @@ -374,12 +372,10 @@ def _map_ret(xs) -> List[Tuple[ValType, Callable[[Any, Any, Any], Any]]]:


class ExplicitFunction(Function):
def __init__(self, name, namespace, args, returns, func, user_data):
def __init__(self, namespace, name, args, returns, func, user_data):
self.func = func

super().__init__(name, args, returns, handle_args, *user_data)
if namespace is not None:
self.set_namespace(namespace)
super().__init__(namespace, name, args, returns, handle_args, *user_data)

functools.update_wrapper(self, func)

Expand All @@ -388,7 +384,7 @@ def __call__(self, *args, **kwargs):


class TypeInferredFunction(ExplicitFunction):
def __init__(self, name, namespace, func, user_data):
def __init__(self, namespace, name, func, user_data):
kwargs: dict[str, Any] = {}
if hasattr(typing, "Annotated"):
kwargs["include_extras"] = True
Expand Down Expand Up @@ -418,8 +414,8 @@ def inner_func(plugin, inputs, outputs, *user_data):
emplace(plugin, slot, result)

super().__init__(
name,
namespace,
name,
[typ for (typ, _) in args],
[typ for (typ, _) in returns],
inner_func,
Expand Down Expand Up @@ -475,11 +471,12 @@ def __init__(
):
wasm = _wasm(plugin)
self.functions = functions
as_extism_functions = [_ExtismFunctionMetadata(f) for f in functions or []]

# Register plugin
errmsg = _ffi.new("char**")
if functions is not None:
function_ptrs = [f.pointer for f in functions]
if as_extism_functions is not None:
function_ptrs = [f.pointer for f in as_extism_functions]
ptr = _ffi.new("ExtismFunction*[]", function_ptrs)
self.plugin = _lib.extism_plugin_new(
wasm, len(wasm), ptr, len(function_ptrs), wasi, errmsg
Expand Down Expand Up @@ -804,10 +801,10 @@ def outer(func):
idx = len(HOST_FN_REGISTRY).to_bytes(length=4, byteorder="big")
user_data.append(idx)
fn = (
TypeInferredFunction(n, namespace, func, user_data)
TypeInferredFunction(namespace, n, func, user_data)
if signature is None
else ExplicitFunction(
n, namespace, signature[0], signature[1], func, user_data
namespace, n, signature[0], signature[1], func, user_data
)
)
HOST_FN_REGISTRY.append(fn)
Expand Down
18 changes: 9 additions & 9 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
[project]
authors = [{ email = "oss@extism.org", name = "The Extism Authors" }]
name = "extism"
version = "0.0.0+replaced-by-ci"
description = "Extism Host SDK for python"
readme = "README.md"
requires-python = ">=3.11"
dependencies = ["extism-sys>=1.9.0"]

[tool.poetry]
name = "extism"
version = "0.0.0+replaced-by-ci"
Expand All @@ -9,7 +18,7 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "^3.8"
cffi = "^1.10.0"
extism-sys = {version = "^1.0.0rc7", allow-prereleases = true}
extism-sys = { version = ">=1.9.0" }
annotated-types = "^0.6.0"

[tool.poetry.dev-dependencies]
Expand All @@ -25,3 +34,12 @@ mypy = "^1.5.1"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[dependency-groups]
dev = [
"black>=24.10.0",
"mypy>=1.13.0",
"sphinx-autodoc-typehints>=2.5.0",
"sphinx-rtd-theme>=3.0.2",
"sphinx>=8.1.3",
]
6 changes: 3 additions & 3 deletions tests/test_extism.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def frobbitz(self):

class TestExtism(unittest.TestCase):
def test_call_plugin(self):
plugin = extism.Plugin(self._manifest())
plugin = extism.Plugin(self._manifest(), functions=[])
j = json.loads(plugin.call("count_vowels", "this is a test"))
self.assertEqual(j["count"], 4)
j = json.loads(plugin.call("count_vowels", "this is a test again"))
Expand All @@ -32,7 +32,7 @@ def test_call_plugin(self):
self.assertEqual(j["count"], 3)

def test_function_exists(self):
plugin = extism.Plugin(self._manifest())
plugin = extism.Plugin(self._manifest(), functions=[])
self.assertTrue(plugin.function_exists("count_vowels"))
self.assertFalse(plugin.function_exists("i_dont_exist"))

Expand Down Expand Up @@ -115,7 +115,7 @@ def hello_world(
inp: typing.Annotated[
str, extism.Codec(lambda xs: xs.decode().replace("o", "u"))
],
*user_data
*user_data,
) -> typing.Annotated[
str, extism.Codec(lambda xs: xs.replace("u", "a").encode())
]:
Expand Down

0 comments on commit 4e5051d

Please sign in to comment.