Coverage for wasmtime/_store.py: 87%
62 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-12-01 19:40 +0000
« prev ^ index » next coverage.py v7.11.3, created at 2025-12-01 19:40 +0000
1from . import _ffi as ffi
2from ctypes import byref, c_uint64, cast, c_void_p, CFUNCTYPE
3import ctypes
4from wasmtime import Engine, WasmtimeError, Managed
5from . import _value as value
6import typing
8if typing.TYPE_CHECKING:
9 from ._wasi import WasiConfig
12class Store(Managed["ctypes._Pointer[ffi.wasmtime_store_t]"]):
13 __context: "typing.Optional[ctypes._Pointer[ffi.wasmtime_context_t]]"
15 def __init__(self, engine: typing.Optional[Engine] = None, data: typing.Optional[typing.Any] = None):
17 if engine is None:
18 engine = Engine()
19 elif not isinstance(engine, Engine):
20 raise TypeError("expected an Engine")
21 data_id = None
22 finalize = cast(0, CFUNCTYPE(None, c_void_p))
23 if data:
24 data_id = value._intern(data)
25 finalize = value._externref_finalizer
26 self._set_ptr(ffi.wasmtime_store_new(engine.ptr(), data_id, finalize))
27 self.__context = ffi.wasmtime_store_context(self.ptr())
28 self.engine = engine
30 def _delete(self, ptr: "ctypes._Pointer[ffi.wasmtime_store_t]") -> None:
31 ffi.wasmtime_store_delete(ptr)
32 self.__context = None
34 def _context(self) -> "ctypes._Pointer[ffi.wasmtime_context_t]":
35 if self.__context is None:
36 raise ValueError('already closed')
37 return self.__context
39 def data(self) -> typing.Optional[typing.Any]:
40 """
41 TODO
42 """
43 data = ffi.wasmtime_context_get_data(self._context())
44 if data:
45 # FIXME https://github.com/bytecodealliance/wasmtime-py/issues/303
46 return value._unintern(data) # type: ignore
47 else:
48 return None
50 def gc(self) -> None:
51 """
52 Runs a GC over `externref` values that have been passed into this Store,
53 cleaning out anything that is no longer referenced.
55 This is not required to be run manually, but can be done so if you'd
56 like more precise control over when unreferenced `externref` values are
57 deallocated.
58 """
59 ffi.wasmtime_context_gc(self._context())
61 def set_fuel(self, fuel: int) -> None:
62 """
63 Sets the amount of fuel in this store to `fuel`.
65 This is only relevant when `Config.consume_fuel` is configured.
67 This is a required call to ensure that the store has fuel to
68 execute WebAssembly since otherwise stores start with zero fuel.
70 Raises a `WasmtimeError` if this store's configuration is not configured
71 to consume fuel.
72 """
73 err = ffi.wasmtime_context_set_fuel(self._context(), fuel)
74 if err:
75 raise WasmtimeError._from_ptr(err)
77 def get_fuel(self) -> int:
78 """
79 Returns the amount of fuel left in the store.
81 This is only relevant when `Config.consume_fuel` is configured.
83 Raises a `WasmtimeError` if this store's configuration is not configured
84 to consume fuel or if the store doesn't have enough fuel remaining.
85 """
86 remaining = c_uint64(0)
87 err = ffi.wasmtime_context_get_fuel(self._context(), byref(remaining))
88 if err:
89 raise WasmtimeError._from_ptr(err)
90 return remaining.value
92 def set_wasi(self, wasi: "WasiConfig") -> None:
93 """
94 TODO
95 """
96 error = ffi.wasmtime_context_set_wasi(self._context(), wasi._consume())
97 if error:
98 raise WasmtimeError._from_ptr(error)
100 def set_epoch_deadline(self, ticks_after_current: int) -> None:
101 """
102 Configures the relative epoch deadline, after the current engine's
103 epoch, after which WebAssembly code will trap.
104 """
105 ffi.wasmtime_context_set_epoch_deadline(self._context(), ticks_after_current)
107 def set_limits(self,
108 memory_size: int = -1,
109 table_elements: int = -1,
110 instances: int = -1,
111 tables: int = -1,
112 memories: int = -1) -> None:
113 """
114 Configures the limits of various items within this store.
116 * `memory_size` - the maximum size, in bytes, that linear memory is
117 allowed to consume within this store. Setting this to a lower value
118 will cause instantiation to fail if a module needs more memory.
119 Additionally the `memory.grow` instruction will return -1 once this
120 threshold is reached.
122 * `table_elements` - the maximum number of elements that can be stored
123 within tables in this store. Currently each table element takes 8
124 bytes.
126 * `instances` - the maximum number of WebAssembly instances that can
127 be created.
129 * `tables` - the maximum number of WebAssembly tables that can
130 be created.
132 * `memories` - the maximum number of WebAssembly linear memories that
133 can be created.
135 If any limit is negative then the limit will not be set as a part of
136 this invocation and it will be ignored.
137 """
138 ffi.wasmtime_store_limiter(self.ptr(), memory_size, table_elements, instances, tables, memories)
141class StoreContext:
142 __ptr: typing.Optional["ctypes._Pointer[ffi.wasmtime_context_t]"]
144 def __init__(self, ptr: "ctypes._Pointer[ffi.wasmtime_context_t]"):
145 self.__ptr = ptr
147 def _context(self) -> "ctypes._Pointer[ffi.wasmtime_context_t]":
148 if self.__ptr is None:
149 raise ValueError("caller is no longer valid")
150 return self.__ptr
152 def _invalidate(self) -> None:
153 self.__ptr = None
156if typing.TYPE_CHECKING:
157 from ._func import Caller
160Storelike = typing.Union[Store, "Caller", StoreContext]