xbbg 1.1.0
Added
xbbg-mcplocal MCP server: Added a stdio Bloomberg MCP application underapps/xbbg-mcpwith tool surfaces forbdp,bdh,bds,bdib,bql,bsrch,bflds, and generic request execution. Responses are bounded structured JSON with Arrow schema metadata for coding agents.- GitHub-release MCP distribution path: Added release packaging for
xbbg-mcp, a Unix launcher wrapper (scripts/xbbg-mcp), and a convenience installer (scripts/install-xbbg-mcp.sh) so Claude Code and OpenCode users can install a local MCP binary without cloning or compiling the repo first. @xbbg/coreNode.js package: New first-class JavaScript/TypeScript client underjs-xbbg/that wraps the Rust engine via NAPI. Exposes the full request surface (bdp,bdh,bds,bdib,bdtick,bql,bqr,bsrch,beqs,blkp,bport,bcurves,bgovts,bflds), a typed error hierarchy, optional backends (Apache Arrow tables by default,nodejs-polarsas an optional peer), and a BPIPE/auth-awareconfigure(). Native addons are prebuilt and distributed as optional platform packages (@xbbg/core-darwin-arm64,@xbbg/core-linux-x64,@xbbg/core-win32-x64) sonpm install @xbbg/coreJust Works without a Rust toolchain.@xbbg/bridgeasync browser bridge: New companion package exposing the Rust engine through an async postMessage bridge, shipped alongside@xbbg/corewith matching platform-specific native addons.- GitHub-only JS package release workflow: Added a manual
js_github_release.ymlpath that builds, versions, validates, and attaches GitHub release tarballs for@xbbg/coreand@xbbg/bridgewithout npm publishing. The workflow intentionally ships the currently supported 8-asset set only:@xbbg/corewrapper plusdarwin-arm64/linux-x64/win32-x64, and@xbbg/bridgewrapper plusdarwin-arm64/linux-x64/win32-x64. The unreleased@xbbg/bridge-darwin-x64and@xbbg/bridge-linux-arm64package stubs remain excluded until Bloomberg SDK archive support exists. - Friendlier
AttributeErrorfor removedblplegacy APIs:blp.connect,blp.disconnect, andblp.getBlpapiVersionnow raise anAttributeErrorwhose message points directly at the 1.0 replacement (xbbg.configure,xbbg.shutdown/xbbg.reset,xbbg.get_sdk_info) with a copy-pasteable B-PIPE example, instead of the bare "module has no attribute" default. Implemented via a module-level__getattr__hook inpy-xbbg/src/xbbg/blp.py.
Changed
- Backend conversion moved to a single boundary with
pa.Tableas canonical form:_execute_request_terminalnow returns the rawpa.Tablefrom the Rust engine without wrapping in narwhals first;arequestdoes a single_convert_backendcall at its return._convert_backenddispatches directly frompa.Tablevia zero-copy primitives (pl.from_arrow,table.to_pandas, identity forpa.Table → pa.Table), bypassing the narwhals wrap/unwrap on the hot path. Short-circuiting middlewares that return non-pa.Tablevalues (e.g. caches returning lists) keep full control over their result. Measured on a 1000×10 frame:pa.Table → pa.Tablewent from 17.78 µs to 0.04 µs (464×),pa.Table → pl.DataFramefrom 39.89 µs to 18.67 µs (2.1×). Subscriptions streaming at 10k msgs/sec previously spent ~33% of a core on redundant wrap/unwrap in the dispatch layer; this cuts it roughly in half. Narwhals remains the canonical abstraction for backend-agnostic data manipulation inext/historical.py,ext/currency.py,ext/futures.py,ext/_utils.py, and_reshape_bqr_generic— this refactor only removes it from the pure routing path where it added overhead without value. - Minimum
narwhalsversion bumped to>=2.0: Required for thenw.Implementationenum and.implementationproperty used by the new_convert_backenddispatch. Downstream users pinned to narwhals 1.x will need to upgrade. No other narwhals 2.x breaking changes affect xbbg —get_native_namespace,new_series(native_namespace=),from_nativeidempotency, and.to_native()all remain stable across the 1→2 boundary. xbbg.configure()rejects unknown kwargs:configure()now raisesTypeErroron any keyword it does not recognize. Previously unknown kwargs were silently dropped by the RustPyEngineConfigconstructor, which meant typos (e.g.hots=...instead ofhost=...) would leave the host at the default without any warning. The Python normalizer now validates the kwarg set against the canonical field list before handing off to Rust.- Docs site restructured with Python/JavaScript split: The Starlight site under
docs/now has distinctpython/andjavascript/sections, an auto-generatedreleases/changelog.mdxpage (scripts/generate-changelog-docs.sh), and auto-generated Python API reference (scripts/generate-python-api-docs.sh, renamed fromgenerate-api-docs.sh). Thedeploy-docs.ymlworkflow now drives publishing automatically, and the host build no longer depends onsharpso it works on macOS without libvips.
Fixed
- Incorrect value types in
bdp/bdhlong format (issue #280): The default long format (LongMode::String) was converting all Bloomberg values to strings, ignoring resolvedfield_types. Now the Rust engine computes a common Arrow type from the field type hints at construction time — when all fields are numeric, thevaluecolumn isFloat64instead ofUtf8. Mixed-type queries (e.g., numeric + string fields) gracefully fall back to string. The fix is zero-copy:Valueis moved into the Arrow builder instead of being stringified and re-parsed. - macOS/Linux:
import xbbg._corefails withLibrary not loaded: @rpath/libblpapi3_64.so(issue #276): The pyo3 cdylib ships with zeroLC_RPATHentries on macOS, so dyld had nowhere to look forlibblpapi3_64.soat import time. Previously only Windows had pre-import SDK setup in__init__.py. Now_prepare_sdk_for_core_import()dispatches per-platform: Windows keeps the existingadd_dll_directorypath, while macOS and Linux preloadlibblpapi3_64.soviactypes.CDLL(..., RTLD_GLOBAL)so dyld/ld.so resolves the@rpathreference via install-name / already-loaded image matching. This mirrors the idiom Bloomberg's ownblpapi/internals.pyuses for itsffiutilsextension (which also ships with no rpath). All four SDK sources (xbbg.set_sdk_path(),blpapipackage, DAPI,BLPAPI_ROOT) are now honored on every platform. The friendlyImportErrorwrapper also recognizes macOS dlopen error strings (Library not loaded,image not found). RequestEnvironment.zfp_remotetype annotation: Corrected the dataclass field annotation fromint | Nonetostr | Noneto match the RustOption<String>(ZFP remote values are strings like"8194"/"8196"). The defensivegetattr()access in_snapshot_request_environmenthad been masking this type mismatch from static analyzers._convert_backendno longer hard-imports polars: A follow-up to the Arrow-canonical refactor accidentally replaced the intentionalhasattr(native, "to_arrow")capability check in the pyarrow branch with an unconditionalisinstance(native, pl.DataFrame), which forcedimport polars as plat module-load time and broke environments where polars (an optional backend) isn't installed. Restored the capability check, short-circuiting pandas inputs viaisinstancefirst so thehasattrpath only fires for genuine polars frames.- Polars/pyarrow global backend causes
AttributeErrorin all generated endpoints (issue #287):_execute_generated_endpointwas effectively calling_convert_backendtwice on the same frame — once inside the middleware terminal (which resolvedbackend=Noneto the global default and returned a native frame) and again in the outer call, which triednw_df.to_native()on the already-native frame. Pandas users were silently masked by anisinstance(nw_df, pd.DataFrame)short-circuit at the top of_convert_backend; polars and pyarrow users had no equivalent guard and sawAttributeError: 'DataFrame' object has no attribute 'to_native'. Affected all 14 generated endpoints (bdp/abdp,bdh/abdh,bds/abds,bdib/abdib,bdtick/abdtick,bql/abql,bqr/abqr,bsrch/absrch,beqs/abeqs,blkp/ablkp,bport/abport,bcurves/abcurves,bgovts/abgovts,bflds/abflds) — not justbdpas reported. Verified end-to-end against a real Bloomberg Terminal. ext/futures.pydate-like duck-typing: Collapsed threehasattr(value, "year"/"month"/"day")calls into a singleisinstance(value, date)check now thatdateis imported unconditionally. More precise and removes false positives from unrelated objects that happen to expose.year.markets/{info,bloomberg}.pyimports: Replacedimportlib.import_module("xbbg")+getattr(..., "bdp"/"abdp") # noqa: B009with deferredfrom xbbg.blp import bdp/abdpinside the consuming functions. Same lazy-loading behavior, removes the lint suppression, and lets static checkers resolve the symbol.- Incorrect timestamp in
parse_rfc3339_utctest: Fixed hardcoded expected value from1717242600to1717252200(correct UTC epoch for2024-06-01T14:30:00+00:00).
Removed
- Legacy
configure()kwarg aliases:xbbg.configure()no longer accepts the legacy connection-style aliases carried over from xbbg 0.x:server,server_host,server_port,max_attempt,auto_restart,max_recovery,retry_max,retry_delay,retry_backoff. TheNotImplementedErrorplaceholders forsessandtls_optionsare likewise gone — unknown kwargs now raise a uniformTypeError. Use the canonicalEngineConfigfield names instead:host,port,num_start_attempts,auto_restart_on_disconnection,max_recovery_attempts,retry_max_retries,retry_initial_delay_ms,retry_backoff_factor.
Full Changelog: v1.0.0...v1.1.0