polyplug-abi 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
polyplug_abi/__init__.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""polyplug_abi — ABI types for the polyplug plugin runtime.
|
|
2
|
+
|
|
3
|
+
This package provides the frozen ABI types that match the Rust ABI exactly.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from enum import IntEnum
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
from polyplug_abi.abi import (
|
|
12
|
+
POLYPLUG_ABI_VERSION,
|
|
13
|
+
AbiErrorCode,
|
|
14
|
+
Compatibility,
|
|
15
|
+
StringView,
|
|
16
|
+
Buffer,
|
|
17
|
+
Version,
|
|
18
|
+
AbiError,
|
|
19
|
+
GuestContractHandle,
|
|
20
|
+
GuestContractInstance,
|
|
21
|
+
HostContractInstance,
|
|
22
|
+
HostContractInterface,
|
|
23
|
+
VmLoaderData,
|
|
24
|
+
NativeDispatch,
|
|
25
|
+
VmDispatch,
|
|
26
|
+
GuestContractInterface,
|
|
27
|
+
HostApi,
|
|
28
|
+
PluginDescriptor,
|
|
29
|
+
BundleInitContext,
|
|
30
|
+
Array,
|
|
31
|
+
DependencyInfo,
|
|
32
|
+
RuntimeConfig,
|
|
33
|
+
DispatchType,
|
|
34
|
+
DispatchMechanisms,
|
|
35
|
+
ArenaOverflowBlock,
|
|
36
|
+
CallArena,
|
|
37
|
+
LogLevel,
|
|
38
|
+
fnv1a_64,
|
|
39
|
+
guest_contract_id,
|
|
40
|
+
host_contract_id,
|
|
41
|
+
bundle_id,
|
|
42
|
+
FNV_OFFSET,
|
|
43
|
+
FNV_PRIME,
|
|
44
|
+
)
|
|
45
|
+
from polyplug_abi.string_view_helper import (
|
|
46
|
+
to_str,
|
|
47
|
+
strip_prefix,
|
|
48
|
+
starts_with,
|
|
49
|
+
ends_with,
|
|
50
|
+
split,
|
|
51
|
+
bytes_as_view,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ReloadPhaseType(IntEnum):
|
|
56
|
+
"""Type tag for ReloadPhase variants."""
|
|
57
|
+
|
|
58
|
+
Preparing = 0
|
|
59
|
+
Reloaded = 1
|
|
60
|
+
Failed = 2
|
|
61
|
+
Unloading = 3
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class ReloadPhase:
|
|
65
|
+
"""Python representation of hot-reload phase notification.
|
|
66
|
+
|
|
67
|
+
Mirrors the ABI ``ReloadPhase`` struct exactly — there is no retry-count
|
|
68
|
+
field in the ABI.
|
|
69
|
+
|
|
70
|
+
Attributes:
|
|
71
|
+
type: The phase type (Preparing, Reloaded, Failed, or Unloading), or
|
|
72
|
+
the raw ``int`` discriminant when the runtime reports a phase this
|
|
73
|
+
SDK version does not know (the conversion is total — see
|
|
74
|
+
``polyplug.runtime``).
|
|
75
|
+
bundle_id: The FNV-1a hash of the bundle name.
|
|
76
|
+
bundle_name: The human-readable bundle name.
|
|
77
|
+
reason: Failure reason string (valid only for Failed).
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __init__(
|
|
81
|
+
self,
|
|
82
|
+
type: ReloadPhaseType | int,
|
|
83
|
+
bundle_id: int,
|
|
84
|
+
bundle_name: str,
|
|
85
|
+
reason: Optional[str] = None,
|
|
86
|
+
) -> None:
|
|
87
|
+
self.type: ReloadPhaseType | int = type
|
|
88
|
+
self.bundle_id: int = bundle_id
|
|
89
|
+
self.bundle_name: str = bundle_name
|
|
90
|
+
self.reason: Optional[str] = reason
|
|
91
|
+
|
|
92
|
+
def is_preparing(self) -> bool:
|
|
93
|
+
"""Return True if this is a Preparing phase."""
|
|
94
|
+
return self.type == ReloadPhaseType.Preparing
|
|
95
|
+
|
|
96
|
+
def is_reloaded(self) -> bool:
|
|
97
|
+
"""Return True if this is a Reloaded phase."""
|
|
98
|
+
return self.type == ReloadPhaseType.Reloaded
|
|
99
|
+
|
|
100
|
+
def is_failed(self) -> bool:
|
|
101
|
+
"""Return True if this is a Failed phase."""
|
|
102
|
+
return self.type == ReloadPhaseType.Failed
|
|
103
|
+
|
|
104
|
+
def is_unloading(self) -> bool:
|
|
105
|
+
"""Return True if this is an Unloading phase."""
|
|
106
|
+
return self.type == ReloadPhaseType.Unloading
|
|
107
|
+
|
|
108
|
+
def __repr__(self) -> str:
|
|
109
|
+
type_name: str = (
|
|
110
|
+
self.type.name
|
|
111
|
+
if isinstance(self.type, ReloadPhaseType)
|
|
112
|
+
else f"Unknown({self.type})"
|
|
113
|
+
)
|
|
114
|
+
return (
|
|
115
|
+
f"ReloadPhase(type={type_name}, bundle_id={self.bundle_id}, "
|
|
116
|
+
f"bundle_name={self.bundle_name!r}, reason={self.reason!r})"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
__all__ = [
|
|
121
|
+
"POLYPLUG_ABI_VERSION",
|
|
122
|
+
"AbiErrorCode",
|
|
123
|
+
"Compatibility",
|
|
124
|
+
"StringView",
|
|
125
|
+
"Buffer",
|
|
126
|
+
"Version",
|
|
127
|
+
"AbiError",
|
|
128
|
+
"GuestContractHandle",
|
|
129
|
+
"GuestContractInstance",
|
|
130
|
+
"HostContractInstance",
|
|
131
|
+
"HostContractInterface",
|
|
132
|
+
"VmLoaderData",
|
|
133
|
+
"NativeDispatch",
|
|
134
|
+
"VmDispatch",
|
|
135
|
+
"GuestContractInterface",
|
|
136
|
+
"HostApi",
|
|
137
|
+
"PluginDescriptor",
|
|
138
|
+
"BundleInitContext",
|
|
139
|
+
"Array",
|
|
140
|
+
"DependencyInfo",
|
|
141
|
+
"RuntimeConfig",
|
|
142
|
+
"DispatchType",
|
|
143
|
+
"DispatchMechanisms",
|
|
144
|
+
"LogLevel",
|
|
145
|
+
"fnv1a_64",
|
|
146
|
+
"guest_contract_id",
|
|
147
|
+
"host_contract_id",
|
|
148
|
+
"bundle_id",
|
|
149
|
+
"FNV_OFFSET",
|
|
150
|
+
"FNV_PRIME",
|
|
151
|
+
"ReloadPhaseType",
|
|
152
|
+
"ReloadPhase",
|
|
153
|
+
"to_str",
|
|
154
|
+
"strip_prefix",
|
|
155
|
+
"starts_with",
|
|
156
|
+
"ends_with",
|
|
157
|
+
"split",
|
|
158
|
+
"bytes_as_view",
|
|
159
|
+
]
|
polyplug_abi/abi.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Re-export all types from the auto-generated abi module.
|
|
2
|
+
# The canonical file is at sdks/python/abi/abi.py.
|
|
3
|
+
# This shared package makes the types available via `from polyplug_abi import ...`.
|
|
4
|
+
try:
|
|
5
|
+
from abi.abi import * # noqa: F401,F403
|
|
6
|
+
except ImportError:
|
|
7
|
+
from polyplug.abi.abi import * # noqa: F401,F403
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""polyplug_abi — String helper functions for StringView."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import ctypes
|
|
6
|
+
|
|
7
|
+
from polyplug_abi.abi import StringView
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def to_str(sv: StringView) -> str:
|
|
11
|
+
"""Convert StringView to Python str.
|
|
12
|
+
|
|
13
|
+
A null/zero-length view decodes to ``""``. A non-null view whose bytes are
|
|
14
|
+
NOT valid UTF-8 raises ``UnicodeDecodeError`` — the strict ``bytes.decode``
|
|
15
|
+
never silently substitutes replacement characters for a readable-but-invalid
|
|
16
|
+
view.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
sv: StringView from polyplug ABI
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
Python string (UTF-8 decoded)
|
|
23
|
+
|
|
24
|
+
Raises:
|
|
25
|
+
UnicodeDecodeError: if the viewed bytes are not valid UTF-8.
|
|
26
|
+
"""
|
|
27
|
+
if not sv.ptr or sv.len == 0:
|
|
28
|
+
return ""
|
|
29
|
+
data = ctypes.cast(sv.ptr, ctypes.POINTER(ctypes.c_char * sv.len)).contents
|
|
30
|
+
return bytes(data).decode("utf-8")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def strip_prefix(sv: StringView, prefix: str) -> str:
|
|
34
|
+
"""Strip prefix from StringView if present, otherwise return original string.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
sv: StringView from polyplug ABI
|
|
38
|
+
prefix: Prefix string to strip
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
String with prefix removed if it was present, otherwise original string
|
|
42
|
+
"""
|
|
43
|
+
s: str = to_str(sv)
|
|
44
|
+
if s.startswith(prefix):
|
|
45
|
+
return s[len(prefix) :]
|
|
46
|
+
return s
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def starts_with(sv: StringView, prefix: str) -> bool:
|
|
50
|
+
"""Check if StringView starts with prefix.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
sv: StringView from polyplug ABI
|
|
54
|
+
prefix: Prefix string to check for
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
True if the string starts with the prefix, False otherwise
|
|
58
|
+
"""
|
|
59
|
+
return to_str(sv).startswith(prefix)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def ends_with(sv: StringView, suffix: str) -> bool:
|
|
63
|
+
"""Check if StringView ends with suffix.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
sv: StringView from polyplug ABI
|
|
67
|
+
suffix: Suffix string to check for
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
True if the string ends with the suffix, False otherwise
|
|
71
|
+
"""
|
|
72
|
+
return to_str(sv).endswith(suffix)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def split(sv: StringView, delimiter: str) -> list[str]:
|
|
76
|
+
"""Split StringView by a literal delimiter, keeping empty segments.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
sv: StringView from polyplug ABI
|
|
80
|
+
delimiter: Literal delimiter string to split by
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
[] for a null/empty view, [s] for an empty delimiter, otherwise the
|
|
84
|
+
segments around every occurrence of the delimiter (empties kept)
|
|
85
|
+
"""
|
|
86
|
+
s: str = to_str(sv)
|
|
87
|
+
if not s:
|
|
88
|
+
return []
|
|
89
|
+
if not delimiter:
|
|
90
|
+
return [s]
|
|
91
|
+
return s.split(delimiter)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def bytes_as_view(data: bytes) -> StringView:
|
|
95
|
+
"""Build a borrowed ``StringView`` over a bytes object's internal buffer.
|
|
96
|
+
|
|
97
|
+
The caller MUST keep ``data`` alive for as long as the view is read —
|
|
98
|
+
ctypes does not root ``data`` through the view's raw pointer field. Bind
|
|
99
|
+
the bytes to a local (or other owner) that outlives every read of the
|
|
100
|
+
view; never build a view over a temporary such as ``s.encode("utf-8")``
|
|
101
|
+
passed inline. Empty bytes produce a null view (``ptr=None, len=0``),
|
|
102
|
+
which is legal at the ABI boundary.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
data: caller-owned UTF-8 bytes backing the view.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
StringView borrowing ``data``'s buffer (null view for empty bytes).
|
|
109
|
+
"""
|
|
110
|
+
if not data:
|
|
111
|
+
return StringView(ptr=None, len=0)
|
|
112
|
+
addr: int = ctypes.cast(ctypes.c_char_p(data), ctypes.c_void_p).value or 0
|
|
113
|
+
return StringView(ptr=addr, len=len(data))
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: polyplug-abi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: ABI types for the polyplug plugin runtime
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/polyplug/polyplug
|
|
7
|
+
Project-URL: Documentation, https://github.com/polyplug/polyplug#readme
|
|
8
|
+
Project-URL: Repository, https://github.com/polyplug/polyplug.git
|
|
9
|
+
Project-URL: Issues, https://github.com/polyplug/polyplug/issues
|
|
10
|
+
Keywords: polyplug,plugin,abi,ffi
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.10
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
polyplug_abi/__init__.py,sha256=dTRrlkjV-bNNJOyQZlZyQWwYsXlgcZatAUen06ajjic,3900
|
|
2
|
+
polyplug_abi/abi.py,sha256=QvQU9B2RkisfI5tdqqatzwdy-mIkThNdwdO90T8DDw0,317
|
|
3
|
+
polyplug_abi/string_view_helper.py,sha256=3y2mrMSK_NEwo9C9owBZfZq7kulHu0yOW7KMOB_x0Ww,3360
|
|
4
|
+
polyplug_abi-0.1.0.dist-info/METADATA,sha256=ur6AbfSniHhP0YSNLl9kVqHTOugIvAFuQWszHhScPNg,860
|
|
5
|
+
polyplug_abi-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
6
|
+
polyplug_abi-0.1.0.dist-info/top_level.txt,sha256=2KW-836oU-A4B48jcweB0U_kpBVU9kHqp2S6C1wL7uY,13
|
|
7
|
+
polyplug_abi-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
polyplug_abi
|