hgraph-web 0.8.20__tar.gz
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.
- hgraph_web-0.8.20/.gitignore +7 -0
- hgraph_web-0.8.20/CHANGELOG.md +37 -0
- hgraph_web-0.8.20/CMakeLists.txt +396 -0
- hgraph_web-0.8.20/LICENSE +21 -0
- hgraph_web-0.8.20/PKG-INFO +100 -0
- hgraph_web-0.8.20/README.md +86 -0
- hgraph_web-0.8.20/cmake/hgraph-webConfig.cmake.in +38 -0
- hgraph_web-0.8.20/include/hgraph/web/export.h +16 -0
- hgraph_web-0.8.20/include/hgraph/web/service.h +146 -0
- hgraph_web-0.8.20/include/hgraph/web/testing/fake_transport.h +136 -0
- hgraph_web-0.8.20/include/hgraph/web/types.h +482 -0
- hgraph_web-0.8.20/include/hgraph/web/value_builders.h +260 -0
- hgraph_web-0.8.20/pyproject.toml +47 -0
- hgraph_web-0.8.20/python/hgraph_web/__init__.py +841 -0
- hgraph_web-0.8.20/python/hgraph_web/_endpoints.py +433 -0
- hgraph_web-0.8.20/python/hgraph_web/compat.py +1251 -0
- hgraph_web-0.8.20/python/tests/_loopback_harness.py +66 -0
- hgraph_web-0.8.20/python/tests/test_api.py +481 -0
- hgraph_web-0.8.20/python/tests/test_compat.py +548 -0
- hgraph_web-0.8.20/python/tests/test_endpoints.py +381 -0
- hgraph_web-0.8.20/python/tests/test_packaging.py +182 -0
- hgraph_web-0.8.20/python/tests/test_runtime.py +244 -0
- hgraph_web-0.8.20/src/asio_server.cpp +4945 -0
- hgraph_web-0.8.20/src/curl_client.cpp +2483 -0
- hgraph_web-0.8.20/src/detail/h2_engine.h +147 -0
- hgraph_web-0.8.20/src/detail/route_table.cpp +383 -0
- hgraph_web-0.8.20/src/detail/route_table.h +111 -0
- hgraph_web-0.8.20/src/detail/service_transport.h +1189 -0
- hgraph_web-0.8.20/src/detail/stream_model.h +121 -0
- hgraph_web-0.8.20/src/detail/web_bindings.h +186 -0
- hgraph_web-0.8.20/src/nghttp2_session.cpp +457 -0
- hgraph_web-0.8.20/src/python_module.cpp +171 -0
- hgraph_web-0.8.20/src/service.cpp +75 -0
- hgraph_web-0.8.20/src/testing/fake_transport.cpp +1246 -0
- hgraph_web-0.8.20/src/value_builders.cpp +938 -0
- hgraph_web-0.8.20/test_package/CMakeLists.txt +13 -0
- hgraph_web-0.8.20/test_package/main.cpp +34 -0
- hgraph_web-0.8.20/tests/CMakeLists.txt +112 -0
- hgraph_web-0.8.20/tests/h2spec_server.cpp +209 -0
- hgraph_web-0.8.20/tests/test_client_loopback.cpp +339 -0
- hgraph_web-0.8.20/tests/test_h2_engine.cpp +539 -0
- hgraph_web-0.8.20/tests/test_h2_loopback.cpp +864 -0
- hgraph_web-0.8.20/tests/test_loopback.cpp +754 -0
- hgraph_web-0.8.20/tests/test_route_table.cpp +354 -0
- hgraph_web-0.8.20/tests/test_service.cpp +1375 -0
- hgraph_web-0.8.20/tests/test_service_transport.cpp +210 -0
- hgraph_web-0.8.20/tests/test_types.cpp +169 -0
- hgraph_web-0.8.20/tests/transport_perf.cpp +412 -0
- hgraph_web-0.8.20/tools/audit_distribution.py +171 -0
- hgraph_web-0.8.20/tools/run_h2spec.py +112 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Retain the private request, response, WebSocket, delivery, and event
|
|
6
|
+
transport envelopes as immutable `Shared<T>` allocations across the
|
|
7
|
+
push-source and graph-buffering path. Public web service schemas remain
|
|
8
|
+
unchanged and receive one concrete projection at publication.
|
|
9
|
+
- Keep server timer handles immutable during shutdown so graph teardown cannot
|
|
10
|
+
race an Asio timer callback copying the same handle.
|
|
11
|
+
- Initial extension skeleton (RFC 0024).
|
|
12
|
+
- Service tier: one standard bounded burst push source per independently
|
|
13
|
+
ordered logical channel, avoiding cross-channel head-of-line blocking while
|
|
14
|
+
distributing distinct TSD keys together and preserving same-key/scalar FIFO;
|
|
15
|
+
graph-side stateless grouping followed by standard `collect`/mapped `emit`,
|
|
16
|
+
standard scalar `emit`, and command sinks; domain byte/reservation watermarks
|
|
17
|
+
released at graph handoff without a second value queue; the
|
|
18
|
+
eleven service interfaces wired through
|
|
19
|
+
`impl_input`/`impl_output`, wiring sugar, and the socketless
|
|
20
|
+
`FakeWebServer`/`FakeWebClient` transports. Graph-owned subscription
|
|
21
|
+
generations prevent queued HTTP or WebSocket ingress from crossing route/key
|
|
22
|
+
removal and re-addition boundaries (RFC 0024/0027).
|
|
23
|
+
- Python surface: the `hgraph_web` schemas/services/wiring helpers, the
|
|
24
|
+
`@http_endpoint`/`@ws_endpoint` decorators with JSON/text codec helpers
|
|
25
|
+
and route/server authenticators, and `hgraph_web.compat` — the released
|
|
26
|
+
tornado adaptor API re-implemented on the native transports with its
|
|
27
|
+
legacy behaviors reproduced only there (parity notes in the module).
|
|
28
|
+
Compatibility requests are keyed before route streams merge, preserving
|
|
29
|
+
concurrent requests matched by distinct routes in one burst cycle.
|
|
30
|
+
- Live transports: the Asio/Beast server (h1.1 + WebSocket, TLS with the
|
|
31
|
+
HTTP/2 ALPN seam, route trie, port-sharing listener registry, request
|
|
32
|
+
timeouts, watermark read-pausing, strict stop ordering) and the libcurl
|
|
33
|
+
client (h1 + h2, WebSocket over CONNECT_ONLY, response reservations,
|
|
34
|
+
pre-warmed value bindings), `register_server`/`register_client`, and
|
|
35
|
+
the loopback test tiers — an independent Beast oracle against the
|
|
36
|
+
server, and the extension's own client against its own server
|
|
37
|
+
(RFC 0024, implementation plan steps 3-4).
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.25)
|
|
2
|
+
|
|
3
|
+
project(hgraph_web VERSION 0.8.0 LANGUAGES C CXX)
|
|
4
|
+
|
|
5
|
+
include(GNUInstallDirs)
|
|
6
|
+
include(CMakePackageConfigHelpers)
|
|
7
|
+
include(CTest)
|
|
8
|
+
include(FetchContent)
|
|
9
|
+
|
|
10
|
+
option(HGRAPH_WEB_FETCH_NGHTTP2
|
|
11
|
+
"Fetch the pinned nghttp2 release when a CMake package is unavailable"
|
|
12
|
+
ON)
|
|
13
|
+
option(HGRAPH_WEB_FETCH_CURL
|
|
14
|
+
"Fetch the pinned curl release when a CMake package is unavailable"
|
|
15
|
+
ON)
|
|
16
|
+
option(HGRAPH_WEB_FETCH_BOOST
|
|
17
|
+
"Fetch the pinned Boost release when a CMake package is unavailable"
|
|
18
|
+
ON)
|
|
19
|
+
option(HGRAPH_WEB_FORCE_FETCH_DEPENDENCIES
|
|
20
|
+
"Use the pinned third-party releases even when system packages are available"
|
|
21
|
+
OFF)
|
|
22
|
+
option(HGRAPH_WEB_BUILD_PYTHON "Build the optional Python authoring bridge" OFF)
|
|
23
|
+
|
|
24
|
+
# Load only the limited-API Python targets before the installed hgraph SDK.
|
|
25
|
+
# Linking an embedding target such as Python::Python would pin this ABI3
|
|
26
|
+
# extension to the interpreter used for the build.
|
|
27
|
+
if(HGRAPH_WEB_BUILD_PYTHON)
|
|
28
|
+
find_package(Python 3.12 COMPONENTS
|
|
29
|
+
Interpreter Development.Module Development.SABIModule REQUIRED)
|
|
30
|
+
endif()
|
|
31
|
+
|
|
32
|
+
if(NOT TARGET hgraph::core)
|
|
33
|
+
find_package(hgraph CONFIG REQUIRED)
|
|
34
|
+
endif()
|
|
35
|
+
|
|
36
|
+
if(HGRAPH_WEB_BUILD_PYTHON AND PROJECT_IS_TOP_LEVEL)
|
|
37
|
+
get_target_property(_hgraph_web_core_links hgraph::options INTERFACE_LINK_LIBRARIES)
|
|
38
|
+
if("Python::Python" IN_LIST _hgraph_web_core_links)
|
|
39
|
+
message(FATAL_ERROR
|
|
40
|
+
"The selected hgraph SDK embeds a specific Python interpreter and "
|
|
41
|
+
"cannot produce an ABI3 hgraph-web wheel; use the SDK installed "
|
|
42
|
+
"by an hgraph stable-ABI wheel")
|
|
43
|
+
endif()
|
|
44
|
+
endif()
|
|
45
|
+
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
# Third-party transport stack (RFC 0024, packaging): OpenSSL everywhere (one
|
|
48
|
+
# TLS surface, including Windows), then nghttp2 -> curl -> Boost in that
|
|
49
|
+
# order. curl links the same nghttp2 it uses for client HTTP/2, so the later
|
|
50
|
+
# server HTTP/2 activation adds only a translation unit, not a dependency.
|
|
51
|
+
# Everything fetched is built static and stays PRIVATE to this extension.
|
|
52
|
+
|
|
53
|
+
# A Python extension statically embeds its TLS stack. Keep OpenSSL inside the
|
|
54
|
+
# extension on wheel platforms where a package-local dynamic dependency would
|
|
55
|
+
# otherwise require loader-path repair. In particular, Python 3.8+ does not
|
|
56
|
+
# search the Windows process PATH for dependent DLLs.
|
|
57
|
+
if(HGRAPH_WEB_BUILD_PYTHON AND (APPLE OR WIN32))
|
|
58
|
+
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
|
59
|
+
endif()
|
|
60
|
+
find_package(OpenSSL REQUIRED)
|
|
61
|
+
|
|
62
|
+
# Keep the fetched transport libraries static without disturbing how the
|
|
63
|
+
# extension itself (or any sibling target) honors BUILD_SHARED_LIBS, and keep
|
|
64
|
+
# their test suites out of this build.
|
|
65
|
+
set(_hgraph_web_saved_build_shared_libs ${BUILD_SHARED_LIBS})
|
|
66
|
+
set(_hgraph_web_saved_build_testing ${BUILD_TESTING})
|
|
67
|
+
set(BUILD_SHARED_LIBS OFF)
|
|
68
|
+
set(BUILD_STATIC_LIBS ON)
|
|
69
|
+
set(BUILD_TESTING OFF)
|
|
70
|
+
# The static transport archives link into a shared Python module on ELF
|
|
71
|
+
# wheels, so every fetched object must be position independent.
|
|
72
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
73
|
+
|
|
74
|
+
# Sibling dependencies (Arrow, the AWS SDK) import system curl and friends at
|
|
75
|
+
# the root scope, so a bare TARGET check would adopt whatever they found.
|
|
76
|
+
# Each dependency is adopted only when this extension's own versioned find
|
|
77
|
+
# succeeded; otherwise the pinned release is fetched.
|
|
78
|
+
set(HGRAPH_WEB_NGHTTP2_TARGET "")
|
|
79
|
+
if(NOT HGRAPH_WEB_FORCE_FETCH_DEPENDENCIES)
|
|
80
|
+
find_package(nghttp2 CONFIG QUIET)
|
|
81
|
+
if(nghttp2_FOUND AND TARGET nghttp2::nghttp2)
|
|
82
|
+
set(HGRAPH_WEB_NGHTTP2_TARGET nghttp2::nghttp2)
|
|
83
|
+
endif()
|
|
84
|
+
endif()
|
|
85
|
+
if(NOT HGRAPH_WEB_NGHTTP2_TARGET)
|
|
86
|
+
if(NOT HGRAPH_WEB_FETCH_NGHTTP2)
|
|
87
|
+
message(FATAL_ERROR
|
|
88
|
+
"nghttp2 was not found; install its CMake package or enable "
|
|
89
|
+
"HGRAPH_WEB_FETCH_NGHTTP2")
|
|
90
|
+
endif()
|
|
91
|
+
set(ENABLE_LIB_ONLY ON CACHE BOOL "" FORCE)
|
|
92
|
+
set(ENABLE_DOC OFF CACHE BOOL "" FORCE)
|
|
93
|
+
set(ENABLE_SHARED_LIB OFF CACHE BOOL "" FORCE)
|
|
94
|
+
set(ENABLE_STATIC_LIB ON CACHE BOOL "" FORCE)
|
|
95
|
+
FetchContent_Declare(nghttp2
|
|
96
|
+
GIT_REPOSITORY https://github.com/nghttp2/nghttp2.git
|
|
97
|
+
GIT_TAG v1.64.0
|
|
98
|
+
GIT_SHALLOW TRUE
|
|
99
|
+
)
|
|
100
|
+
FetchContent_MakeAvailable(nghttp2)
|
|
101
|
+
if(TARGET nghttp2_static)
|
|
102
|
+
set(HGRAPH_WEB_NGHTTP2_TARGET nghttp2_static)
|
|
103
|
+
elseif(TARGET nghttp2)
|
|
104
|
+
set(HGRAPH_WEB_NGHTTP2_TARGET nghttp2)
|
|
105
|
+
else()
|
|
106
|
+
message(FATAL_ERROR "nghttp2 did not provide its library target")
|
|
107
|
+
endif()
|
|
108
|
+
# Point curl's nghttp2 discovery at the fetched tree: the version header
|
|
109
|
+
# is generated into the binary include directory at configure time.
|
|
110
|
+
set(NGHTTP2_INCLUDE_DIR
|
|
111
|
+
"${nghttp2_SOURCE_DIR}/lib/includes;${nghttp2_BINARY_DIR}/lib/includes"
|
|
112
|
+
CACHE STRING "" FORCE)
|
|
113
|
+
set(NGHTTP2_LIBRARY ${HGRAPH_WEB_NGHTTP2_TARGET} CACHE STRING "" FORCE)
|
|
114
|
+
endif()
|
|
115
|
+
|
|
116
|
+
set(HGRAPH_WEB_CURL_TARGET "")
|
|
117
|
+
if(NOT HGRAPH_WEB_FORCE_FETCH_DEPENDENCIES)
|
|
118
|
+
# RFC 0024 pins curl >= 8.11: the WebSocket client API left its
|
|
119
|
+
# experimental phase there.
|
|
120
|
+
find_package(CURL 8.11 CONFIG QUIET)
|
|
121
|
+
if(CURL_FOUND AND TARGET CURL::libcurl)
|
|
122
|
+
set(HGRAPH_WEB_CURL_TARGET CURL::libcurl)
|
|
123
|
+
endif()
|
|
124
|
+
endif()
|
|
125
|
+
if(NOT HGRAPH_WEB_CURL_TARGET)
|
|
126
|
+
if(NOT HGRAPH_WEB_FETCH_CURL)
|
|
127
|
+
message(FATAL_ERROR
|
|
128
|
+
"curl >= 8.11 was not found; install its CMake package or enable "
|
|
129
|
+
"HGRAPH_WEB_FETCH_CURL")
|
|
130
|
+
endif()
|
|
131
|
+
set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
|
|
132
|
+
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|
133
|
+
# The fetched curl links the in-tree nghttp2 target, which cannot appear
|
|
134
|
+
# in curl's own CMake export set; the extension never consumes curl via
|
|
135
|
+
# its export anyway. Installation must be off entirely: a partial
|
|
136
|
+
# CURLConfig.cmake landing in the hgraph SDK prefix poisons every later
|
|
137
|
+
# find_package(CURL) in that prefix.
|
|
138
|
+
set(CURL_ENABLE_EXPORT_TARGET OFF CACHE BOOL "" FORCE)
|
|
139
|
+
set(CURL_DISABLE_INSTALL ON CACHE BOOL "" FORCE)
|
|
140
|
+
set(BUILD_LIBCURL_DOCS OFF CACHE BOOL "" FORCE)
|
|
141
|
+
set(BUILD_MISC_DOCS OFF CACHE BOOL "" FORCE)
|
|
142
|
+
set(ENABLE_CURL_MANUAL OFF CACHE BOOL "" FORCE)
|
|
143
|
+
# One TLS surface on every platform, including Windows (RFC 0024).
|
|
144
|
+
set(CURL_USE_OPENSSL ON CACHE BOOL "" FORCE)
|
|
145
|
+
set(CURL_USE_SCHANNEL OFF CACHE BOOL "" FORCE)
|
|
146
|
+
set(CURL_USE_SECTRANSP OFF CACHE BOOL "" FORCE)
|
|
147
|
+
set(USE_NGHTTP2 ON CACHE BOOL "" FORCE)
|
|
148
|
+
# The transport needs no auxiliary curl features; keeping them off keeps
|
|
149
|
+
# the wheel dependency-free beyond OpenSSL.
|
|
150
|
+
set(CURL_USE_LIBPSL OFF CACHE BOOL "" FORCE)
|
|
151
|
+
set(CURL_USE_LIBSSH2 OFF CACHE BOOL "" FORCE)
|
|
152
|
+
set(CURL_BROTLI OFF CACHE BOOL "" FORCE)
|
|
153
|
+
set(CURL_ZSTD OFF CACHE BOOL "" FORCE)
|
|
154
|
+
set(USE_LIBIDN2 OFF CACHE BOOL "" FORCE)
|
|
155
|
+
set(CURL_USE_GSSAPI OFF CACHE BOOL "" FORCE)
|
|
156
|
+
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
|
157
|
+
FetchContent_Declare(curl
|
|
158
|
+
GIT_REPOSITORY https://github.com/curl/curl.git
|
|
159
|
+
GIT_TAG curl-8_11_1
|
|
160
|
+
GIT_SHALLOW TRUE
|
|
161
|
+
)
|
|
162
|
+
FetchContent_MakeAvailable(curl)
|
|
163
|
+
if(APPLE AND CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND
|
|
164
|
+
TARGET libcurl_static)
|
|
165
|
+
# curl 8.11.1 passes an intentionally zero-length transfer buffer that
|
|
166
|
+
# AppleClang 21 diagnoses as an uninitialized const pointer. Keep that
|
|
167
|
+
# dependency-owned warning out of otherwise clean hgraph builds.
|
|
168
|
+
target_compile_options(libcurl_static PRIVATE
|
|
169
|
+
-Wno-uninitialized-const-pointer)
|
|
170
|
+
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND TARGET libcurl_static)
|
|
171
|
+
# GCC 14 diagnoses const conversions in curl 8.11.1's C compatibility
|
|
172
|
+
# surface. Keep that pinned-dependency warning off hgraph build logs.
|
|
173
|
+
target_compile_options(libcurl_static PRIVATE
|
|
174
|
+
-Wno-discarded-qualifiers)
|
|
175
|
+
endif()
|
|
176
|
+
# Adopt the concrete static target: the CURL::libcurl alias name may
|
|
177
|
+
# already be taken by a sibling's system-curl import.
|
|
178
|
+
if(TARGET libcurl_static)
|
|
179
|
+
set(HGRAPH_WEB_CURL_TARGET libcurl_static)
|
|
180
|
+
elseif(TARGET libcurl)
|
|
181
|
+
set(HGRAPH_WEB_CURL_TARGET libcurl)
|
|
182
|
+
else()
|
|
183
|
+
message(FATAL_ERROR "curl did not provide its static library target")
|
|
184
|
+
endif()
|
|
185
|
+
endif()
|
|
186
|
+
|
|
187
|
+
set(HGRAPH_WEB_BOOST_TARGETS "")
|
|
188
|
+
if(NOT HGRAPH_WEB_FORCE_FETCH_DEPENDENCIES)
|
|
189
|
+
find_package(Boost 1.85 CONFIG QUIET COMPONENTS system)
|
|
190
|
+
if(Boost_FOUND AND TARGET Boost::system)
|
|
191
|
+
set(HGRAPH_WEB_BOOST_TARGETS Boost::system)
|
|
192
|
+
if(TARGET Boost::beast)
|
|
193
|
+
list(APPEND HGRAPH_WEB_BOOST_TARGETS Boost::beast Boost::asio)
|
|
194
|
+
else()
|
|
195
|
+
list(APPEND HGRAPH_WEB_BOOST_TARGETS Boost::headers)
|
|
196
|
+
endif()
|
|
197
|
+
endif()
|
|
198
|
+
endif()
|
|
199
|
+
if(NOT HGRAPH_WEB_BOOST_TARGETS)
|
|
200
|
+
if(NOT HGRAPH_WEB_FETCH_BOOST)
|
|
201
|
+
message(FATAL_ERROR
|
|
202
|
+
"Boost >= 1.85 was not found; install its CMake package or enable "
|
|
203
|
+
"HGRAPH_WEB_FETCH_BOOST")
|
|
204
|
+
endif()
|
|
205
|
+
# The CMake-enabled release archive supports building only the needed
|
|
206
|
+
# subset; Beast and Asio are header-only, so this costs extraction, not
|
|
207
|
+
# compilation.
|
|
208
|
+
set(BOOST_INCLUDE_LIBRARIES beast asio system)
|
|
209
|
+
set(BOOST_ENABLE_CMAKE ON)
|
|
210
|
+
# Keep the fetched Boost out of the install tree; it is a build-time
|
|
211
|
+
# detail of this extension, never part of the hgraph SDK.
|
|
212
|
+
set(BOOST_SKIP_INSTALL_RULES ON)
|
|
213
|
+
FetchContent_Declare(boost
|
|
214
|
+
URL https://github.com/boostorg/boost/releases/download/boost-1.87.0/boost-1.87.0-cmake.tar.xz
|
|
215
|
+
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
|
216
|
+
)
|
|
217
|
+
FetchContent_MakeAvailable(boost)
|
|
218
|
+
if(NOT TARGET Boost::beast)
|
|
219
|
+
message(FATAL_ERROR "Boost did not provide its Beast target")
|
|
220
|
+
endif()
|
|
221
|
+
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND TARGET boost_container)
|
|
222
|
+
# GCC 14 reports an unreachable size_t wraparound iteration in the
|
|
223
|
+
# pinned Boost.Container dlmalloc implementation after inlining.
|
|
224
|
+
target_compile_options(boost_container PRIVATE
|
|
225
|
+
-Wno-aggressive-loop-optimizations)
|
|
226
|
+
endif()
|
|
227
|
+
set(HGRAPH_WEB_BOOST_TARGETS Boost::beast Boost::asio Boost::system)
|
|
228
|
+
endif()
|
|
229
|
+
|
|
230
|
+
set(BUILD_SHARED_LIBS ${_hgraph_web_saved_build_shared_libs})
|
|
231
|
+
set(BUILD_TESTING ${_hgraph_web_saved_build_testing})
|
|
232
|
+
# A fetched dependency rewrites the shared BUILD_TESTING cache entry during
|
|
233
|
+
# its configure; restore the superbuild's value so a reconfigure does not
|
|
234
|
+
# silently drop every test target in the tree.
|
|
235
|
+
set(BUILD_TESTING ${_hgraph_web_saved_build_testing}
|
|
236
|
+
CACHE BOOL "Build the testing tree." FORCE)
|
|
237
|
+
unset(_hgraph_web_saved_build_shared_libs)
|
|
238
|
+
unset(_hgraph_web_saved_build_testing)
|
|
239
|
+
|
|
240
|
+
add_library(hgraph_web
|
|
241
|
+
src/asio_server.cpp
|
|
242
|
+
src/curl_client.cpp
|
|
243
|
+
src/nghttp2_session.cpp
|
|
244
|
+
src/detail/route_table.cpp
|
|
245
|
+
src/service.cpp
|
|
246
|
+
src/value_builders.cpp
|
|
247
|
+
src/testing/fake_transport.cpp
|
|
248
|
+
)
|
|
249
|
+
add_library(hgraph::web ALIAS hgraph_web)
|
|
250
|
+
|
|
251
|
+
get_target_property(HGRAPH_WEB_LIBRARY_TYPE hgraph_web TYPE)
|
|
252
|
+
if(HGRAPH_WEB_LIBRARY_TYPE STREQUAL "STATIC_LIBRARY")
|
|
253
|
+
target_compile_definitions(hgraph_web PUBLIC HGRAPH_WEB_STATIC_DEFINE)
|
|
254
|
+
endif()
|
|
255
|
+
|
|
256
|
+
target_compile_features(hgraph_web PUBLIC cxx_std_23)
|
|
257
|
+
# The transport targets join this link line with their translation units:
|
|
258
|
+
# ${HGRAPH_WEB_BOOST_TARGETS} with asio_server.cpp, ${HGRAPH_WEB_CURL_TARGET}
|
|
259
|
+
# with curl_client.cpp, and ${HGRAPH_WEB_NGHTTP2_TARGET} with the HTTP/2
|
|
260
|
+
# session (all PRIVATE; RFC 0024).
|
|
261
|
+
target_link_libraries(hgraph_web
|
|
262
|
+
PUBLIC hgraph::core
|
|
263
|
+
# The fetched transport libraries are build-tree targets outside this
|
|
264
|
+
# project's export set, so they must not leak into the installed
|
|
265
|
+
# interface. Beast/Asio are header-only (compiled into these objects); a
|
|
266
|
+
# SHARED hgraph_web links curl/nghttp2/OpenSSL in. A STATIC install
|
|
267
|
+
# instead needs system curl and OpenSSL at the consumer's final link —
|
|
268
|
+
# the package config records that (the CI SDK consumer uses the shared
|
|
269
|
+
# leg; wheels are always shared).
|
|
270
|
+
PRIVATE $<BUILD_INTERFACE:${HGRAPH_WEB_BOOST_TARGETS}>
|
|
271
|
+
$<BUILD_INTERFACE:${HGRAPH_WEB_CURL_TARGET}>
|
|
272
|
+
$<BUILD_INTERFACE:${HGRAPH_WEB_NGHTTP2_TARGET}>
|
|
273
|
+
OpenSSL::SSL OpenSSL::Crypto
|
|
274
|
+
)
|
|
275
|
+
target_include_directories(hgraph_web
|
|
276
|
+
PUBLIC
|
|
277
|
+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
278
|
+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
279
|
+
PRIVATE
|
|
280
|
+
${CMAKE_CURRENT_SOURCE_DIR}/src
|
|
281
|
+
)
|
|
282
|
+
set_target_properties(hgraph_web PROPERTIES
|
|
283
|
+
EXPORT_NAME web
|
|
284
|
+
POSITION_INDEPENDENT_CODE ON
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
if(MSVC)
|
|
288
|
+
# The transport implementation includes Windows headers. Keep their
|
|
289
|
+
# min/max macros from rewriting standard-library calls in this target.
|
|
290
|
+
# Its Asio transport requires Windows 10 APIs; publish that build-tree
|
|
291
|
+
# target to sibling tests so Boost does not silently assume Windows 7.
|
|
292
|
+
# Beast's template instantiation count in the server TU exceeds the
|
|
293
|
+
# default COFF section limit, hence /bigobj.
|
|
294
|
+
target_compile_definitions(hgraph_web PRIVATE NOMINMAX WIN32_LEAN_AND_MEAN)
|
|
295
|
+
target_compile_definitions(hgraph_web PUBLIC
|
|
296
|
+
$<BUILD_INTERFACE:_WIN32_WINNT=0x0A00>)
|
|
297
|
+
target_compile_options(hgraph_web PRIVATE /W4 /permissive- /bigobj)
|
|
298
|
+
else()
|
|
299
|
+
target_compile_options(hgraph_web PRIVATE -Wall -Wextra -Wpedantic)
|
|
300
|
+
endif()
|
|
301
|
+
|
|
302
|
+
if(HGRAPH_ENABLE_TSAN AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|
303
|
+
# Boost.Asio uses atomic_thread_fence for its fenced block. GCC warns that
|
|
304
|
+
# TSan cannot model that standalone fence; keep the diagnostic visible but
|
|
305
|
+
# do not let warnings-as-errors prevent the sanitizer runtime from running.
|
|
306
|
+
target_compile_options(hgraph_web PRIVATE -Wno-error=tsan)
|
|
307
|
+
endif()
|
|
308
|
+
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|
309
|
+
# GCC's -Wmaybe-uninitialized fires falsely on the std::optional-held
|
|
310
|
+
# scalar tuple the static-node machinery instantiates for the server
|
|
311
|
+
# runtime node; it is a middle-end diagnostic, so the suppression must
|
|
312
|
+
# be a compile flag — diagnostic pragmas do not reach it.
|
|
313
|
+
set_source_files_properties(src/asio_server.cpp PROPERTIES
|
|
314
|
+
COMPILE_OPTIONS "-Wno-maybe-uninitialized")
|
|
315
|
+
endif()
|
|
316
|
+
|
|
317
|
+
if(MSVC AND OPENSSL_USE_STATIC_LIBS)
|
|
318
|
+
# Windows TLS objects embed default-library directives for the OpenSSL
|
|
319
|
+
# import libraries. Ignore those names when CMake selected the statically
|
|
320
|
+
# linked archives for a self-contained consumer; otherwise MSVC still
|
|
321
|
+
# searches for the absent import libs.
|
|
322
|
+
target_link_options(hgraph_web INTERFACE
|
|
323
|
+
/NODEFAULTLIB:libcrypto.lib
|
|
324
|
+
/NODEFAULTLIB:libssl.lib
|
|
325
|
+
)
|
|
326
|
+
endif()
|
|
327
|
+
|
|
328
|
+
if(BUILD_TESTING)
|
|
329
|
+
add_subdirectory(tests)
|
|
330
|
+
endif()
|
|
331
|
+
|
|
332
|
+
if(HGRAPH_WEB_BUILD_PYTHON)
|
|
333
|
+
find_package(Python 3.12 COMPONENTS Interpreter Development.Module Development.SABIModule REQUIRED)
|
|
334
|
+
if(COMMAND hgraph_add_python_module AND TARGET hgraph::nanobind)
|
|
335
|
+
hgraph_add_python_module(_hgraph_web STABLE_ABI NOMINSIZE src/python_module.cpp)
|
|
336
|
+
elseif(NOT PROJECT_IS_TOP_LEVEL AND COMMAND nanobind_add_module)
|
|
337
|
+
if(HGRAPH_BUILD_SHARED)
|
|
338
|
+
set(_hgraph_web_nanobind_linkage NB_SHARED)
|
|
339
|
+
else()
|
|
340
|
+
set(_hgraph_web_nanobind_linkage NB_STATIC)
|
|
341
|
+
endif()
|
|
342
|
+
nanobind_add_module(_hgraph_web STABLE_ABI NOMINSIZE
|
|
343
|
+
${_hgraph_web_nanobind_linkage} src/python_module.cpp)
|
|
344
|
+
unset(_hgraph_web_nanobind_linkage)
|
|
345
|
+
else()
|
|
346
|
+
message(FATAL_ERROR
|
|
347
|
+
"HGRAPH_WEB_BUILD_PYTHON requires a Python-enabled installed hgraph SDK")
|
|
348
|
+
endif()
|
|
349
|
+
target_link_libraries(_hgraph_web PRIVATE hgraph::web)
|
|
350
|
+
if(APPLE)
|
|
351
|
+
set_target_properties(_hgraph_web PROPERTIES
|
|
352
|
+
INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}")
|
|
353
|
+
elseif(UNIX)
|
|
354
|
+
set_target_properties(_hgraph_web PROPERTIES
|
|
355
|
+
INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
|
|
356
|
+
endif()
|
|
357
|
+
install(TARGETS _hgraph_web
|
|
358
|
+
COMPONENT Python
|
|
359
|
+
LIBRARY DESTINATION hgraph_web
|
|
360
|
+
RUNTIME DESTINATION hgraph_web
|
|
361
|
+
)
|
|
362
|
+
endif()
|
|
363
|
+
|
|
364
|
+
install(TARGETS hgraph_web
|
|
365
|
+
EXPORT hgraphWebTargets
|
|
366
|
+
COMPONENT Development
|
|
367
|
+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
368
|
+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
369
|
+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
370
|
+
)
|
|
371
|
+
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
|
372
|
+
COMPONENT Development FILES_MATCHING PATTERN "*.h")
|
|
373
|
+
|
|
374
|
+
write_basic_package_version_file(
|
|
375
|
+
"${PROJECT_BINARY_DIR}/hgraph-webConfigVersion.cmake"
|
|
376
|
+
VERSION ${PROJECT_VERSION}
|
|
377
|
+
COMPATIBILITY SameMajorVersion
|
|
378
|
+
)
|
|
379
|
+
configure_package_config_file(
|
|
380
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/hgraph-webConfig.cmake.in"
|
|
381
|
+
"${PROJECT_BINARY_DIR}/hgraph-webConfig.cmake"
|
|
382
|
+
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/hgraph-web
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
install(EXPORT hgraphWebTargets
|
|
386
|
+
FILE hgraphWebTargets.cmake
|
|
387
|
+
NAMESPACE hgraph::
|
|
388
|
+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/hgraph-web
|
|
389
|
+
COMPONENT Development
|
|
390
|
+
)
|
|
391
|
+
install(FILES
|
|
392
|
+
"${PROJECT_BINARY_DIR}/hgraph-webConfig.cmake"
|
|
393
|
+
"${PROJECT_BINARY_DIR}/hgraph-webConfigVersion.cmake"
|
|
394
|
+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/hgraph-web
|
|
395
|
+
COMPONENT Development
|
|
396
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Howard Henson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: hgraph-web
|
|
3
|
+
Version: 0.8.20
|
|
4
|
+
Summary: HTTP/S and WebSocket transport extension for hgraph
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/hhenson/hgraph
|
|
7
|
+
Project-URL: Repository, https://github.com/hhenson/hgraph.git
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Requires-Dist: hgraph>=0.8.0
|
|
10
|
+
Requires-Dist: frozendict>=2
|
|
11
|
+
Provides-Extra: test
|
|
12
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# hgraph-web
|
|
16
|
+
|
|
17
|
+
C++-first HTTP/S and WebSocket transports for hgraph, implementing the contract
|
|
18
|
+
in hgraph RFC 0024. The extension covers all four transports — HTTP(S) server,
|
|
19
|
+
HTTP(S) client, WebSocket server, and WebSocket client — and exposes the same
|
|
20
|
+
service model to native C++ and Python graphs.
|
|
21
|
+
|
|
22
|
+
One path-bound, multi-interface `service_impl` owns the sockets, TLS contexts,
|
|
23
|
+
and worker threads for a configuration. Serving a route and connecting a
|
|
24
|
+
WebSocket are subscription services keyed by the immutable route or connection
|
|
25
|
+
key; responding, sending frames, and calling a remote endpoint are
|
|
26
|
+
request/reply services; events and statistics are reference services. Graph
|
|
27
|
+
output reaches the transport through the implementation's sink inputs, and
|
|
28
|
+
requests, frames, delivery reports, events, and stats re-enter the root graph
|
|
29
|
+
through bounded push sources. Listeners and clients are created on graph start
|
|
30
|
+
and stopped with the graph; there is no user-held server or client object.
|
|
31
|
+
|
|
32
|
+
Routing lives in the transport rather than the graph. The route key set arrives
|
|
33
|
+
as `TSS` deltas, is compiled into a native route table, and requests are
|
|
34
|
+
delivered already keyed by route. Duplicate and ordered headers, multi-value
|
|
35
|
+
query parameters, and binary bodies are preserved end to end.
|
|
36
|
+
|
|
37
|
+
The server speaks HTTP/1.1 and WebSocket over Asio/Beast; the client speaks
|
|
38
|
+
HTTP/1.1, HTTP/2, and WebSocket over libcurl. The server ships the complete
|
|
39
|
+
HTTP/2 seam — the ALPN callback, protocol dispatch, and configuration
|
|
40
|
+
placeholders — and rejects `h2` in server ALPN until the nghttp2 session lands
|
|
41
|
+
in a v1.x release. TLS termination, mTLS, SNI, and ALPN use OpenSSL on every
|
|
42
|
+
platform.
|
|
43
|
+
|
|
44
|
+
The core `hgraph` wheel owns a guarded compatibility shim at
|
|
45
|
+
`hgraph.adaptors.web` which delegates to this extension when it is installed.
|
|
46
|
+
The released `hgraph.adaptors.tornado` package is unchanged; whether it is
|
|
47
|
+
later re-pointed or deprecated is a separate migration decision. The extension
|
|
48
|
+
wheel installs only `hgraph_web`; it never contributes files to the core
|
|
49
|
+
`hgraph` package.
|
|
50
|
+
|
|
51
|
+
## Status
|
|
52
|
+
|
|
53
|
+
This is the packaging and public-header skeleton. The authoring surface —
|
|
54
|
+
schemas, service interfaces, decorators, and codec helpers — lands with the
|
|
55
|
+
service implementation; see the implementation plan in RFC 0024.
|
|
56
|
+
|
|
57
|
+
## Build and test
|
|
58
|
+
|
|
59
|
+
This is a first-party extension in the hgraph monorepo. It remains a separate
|
|
60
|
+
CMake package and Python distribution: the top-level core package does not link
|
|
61
|
+
curl, Boost, nghttp2, or OpenSSL, and does not install these modules.
|
|
62
|
+
|
|
63
|
+
For an in-tree native development build from the repository root:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
cmake -S . -B build-web \
|
|
67
|
+
-DHGRAPH_BUILD_WEB_EXTENSION=ON \
|
|
68
|
+
-DBUILD_TESTING=ON
|
|
69
|
+
cmake --build build-web --parallel
|
|
70
|
+
ctest --test-dir build-web --output-on-failure
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The extension can still be configured independently against an installed
|
|
74
|
+
hgraph SDK:
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/hgraph/install
|
|
78
|
+
cmake --build build --parallel
|
|
79
|
+
ctest --test-dir build --output-on-failure
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Each third-party dependency arrives with the translation unit that links it,
|
|
83
|
+
resolved with `find_package(... CONFIG QUIET)` first and falling back to a
|
|
84
|
+
pinned static `FetchContent` build. The skeleton links only `hgraph::core`.
|
|
85
|
+
|
|
86
|
+
Build its separately deployable ABI3 wheel from the repository root after
|
|
87
|
+
making the matching hgraph SDK discoverable through `CMAKE_PREFIX_PATH`:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
CMAKE_PREFIX_PATH=/path/to/hgraph/sdk \
|
|
91
|
+
uv build --wheel --package hgraph-web --python 3.12
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The deterministic suite runs against the extension's fake transport, which
|
|
95
|
+
exercises routing, pacing, reservation, and lifecycle without sockets. A live
|
|
96
|
+
loopback subset acts as the transport oracle.
|
|
97
|
+
|
|
98
|
+
Wheel builds require the SDK installed by a stable-ABI hgraph wheel. The
|
|
99
|
+
extension rejects an SDK that links `Python::Python`, because that would pin
|
|
100
|
+
the nominal ABI3 module to the build interpreter.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# hgraph-web
|
|
2
|
+
|
|
3
|
+
C++-first HTTP/S and WebSocket transports for hgraph, implementing the contract
|
|
4
|
+
in hgraph RFC 0024. The extension covers all four transports — HTTP(S) server,
|
|
5
|
+
HTTP(S) client, WebSocket server, and WebSocket client — and exposes the same
|
|
6
|
+
service model to native C++ and Python graphs.
|
|
7
|
+
|
|
8
|
+
One path-bound, multi-interface `service_impl` owns the sockets, TLS contexts,
|
|
9
|
+
and worker threads for a configuration. Serving a route and connecting a
|
|
10
|
+
WebSocket are subscription services keyed by the immutable route or connection
|
|
11
|
+
key; responding, sending frames, and calling a remote endpoint are
|
|
12
|
+
request/reply services; events and statistics are reference services. Graph
|
|
13
|
+
output reaches the transport through the implementation's sink inputs, and
|
|
14
|
+
requests, frames, delivery reports, events, and stats re-enter the root graph
|
|
15
|
+
through bounded push sources. Listeners and clients are created on graph start
|
|
16
|
+
and stopped with the graph; there is no user-held server or client object.
|
|
17
|
+
|
|
18
|
+
Routing lives in the transport rather than the graph. The route key set arrives
|
|
19
|
+
as `TSS` deltas, is compiled into a native route table, and requests are
|
|
20
|
+
delivered already keyed by route. Duplicate and ordered headers, multi-value
|
|
21
|
+
query parameters, and binary bodies are preserved end to end.
|
|
22
|
+
|
|
23
|
+
The server speaks HTTP/1.1 and WebSocket over Asio/Beast; the client speaks
|
|
24
|
+
HTTP/1.1, HTTP/2, and WebSocket over libcurl. The server ships the complete
|
|
25
|
+
HTTP/2 seam — the ALPN callback, protocol dispatch, and configuration
|
|
26
|
+
placeholders — and rejects `h2` in server ALPN until the nghttp2 session lands
|
|
27
|
+
in a v1.x release. TLS termination, mTLS, SNI, and ALPN use OpenSSL on every
|
|
28
|
+
platform.
|
|
29
|
+
|
|
30
|
+
The core `hgraph` wheel owns a guarded compatibility shim at
|
|
31
|
+
`hgraph.adaptors.web` which delegates to this extension when it is installed.
|
|
32
|
+
The released `hgraph.adaptors.tornado` package is unchanged; whether it is
|
|
33
|
+
later re-pointed or deprecated is a separate migration decision. The extension
|
|
34
|
+
wheel installs only `hgraph_web`; it never contributes files to the core
|
|
35
|
+
`hgraph` package.
|
|
36
|
+
|
|
37
|
+
## Status
|
|
38
|
+
|
|
39
|
+
This is the packaging and public-header skeleton. The authoring surface —
|
|
40
|
+
schemas, service interfaces, decorators, and codec helpers — lands with the
|
|
41
|
+
service implementation; see the implementation plan in RFC 0024.
|
|
42
|
+
|
|
43
|
+
## Build and test
|
|
44
|
+
|
|
45
|
+
This is a first-party extension in the hgraph monorepo. It remains a separate
|
|
46
|
+
CMake package and Python distribution: the top-level core package does not link
|
|
47
|
+
curl, Boost, nghttp2, or OpenSSL, and does not install these modules.
|
|
48
|
+
|
|
49
|
+
For an in-tree native development build from the repository root:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
cmake -S . -B build-web \
|
|
53
|
+
-DHGRAPH_BUILD_WEB_EXTENSION=ON \
|
|
54
|
+
-DBUILD_TESTING=ON
|
|
55
|
+
cmake --build build-web --parallel
|
|
56
|
+
ctest --test-dir build-web --output-on-failure
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The extension can still be configured independently against an installed
|
|
60
|
+
hgraph SDK:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/hgraph/install
|
|
64
|
+
cmake --build build --parallel
|
|
65
|
+
ctest --test-dir build --output-on-failure
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Each third-party dependency arrives with the translation unit that links it,
|
|
69
|
+
resolved with `find_package(... CONFIG QUIET)` first and falling back to a
|
|
70
|
+
pinned static `FetchContent` build. The skeleton links only `hgraph::core`.
|
|
71
|
+
|
|
72
|
+
Build its separately deployable ABI3 wheel from the repository root after
|
|
73
|
+
making the matching hgraph SDK discoverable through `CMAKE_PREFIX_PATH`:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
CMAKE_PREFIX_PATH=/path/to/hgraph/sdk \
|
|
77
|
+
uv build --wheel --package hgraph-web --python 3.12
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The deterministic suite runs against the extension's fake transport, which
|
|
81
|
+
exercises routing, pacing, reservation, and lifecycle without sockets. A live
|
|
82
|
+
loopback subset acts as the transport oracle.
|
|
83
|
+
|
|
84
|
+
Wheel builds require the SDK installed by a stable-ABI hgraph wheel. The
|
|
85
|
+
extension rejects an SDK that links `Python::Python`, because that would pin
|
|
86
|
+
the nominal ABI3 module to the build interpreter.
|