feat!: merge v6.0.0 (#220)
build!: migrate python bindings from pybind11 to nanobind (#211)
build: migrate python bindings from pybind11 to nanobind
nanobind is a from-scratch rewrite of pybind11 by the same author, targeting C++17 and trading pybind11’s breadth for a much leaner call path. Measured on this repository’s own bindings, it is ~2.7x faster on a geometric mean of call shapes (up to ~6x on method calls, ~9x on overload dispatch), compiles ~3x faster and produces a ~33% smaller extension module.
The bindings themselves translate almost mechanically. The parts that do not:
pybind11/operators.hhas no nanobind counterpart, so eachself OP selfexpression becomes an explicit lambda. In-place operators return a reference underrv_policy::noneso thata += bkeeps returningaitself.init(factory)becomes a placement-new__init__.make_iteratornow takes a scope and a name for the iterator type.arg_v(name, value, repr)becomesarg(name).sig(repr) = value.handle::cast<T>()becomes the free functionnanobind::cast<T>(handle).Path.get_absolute_pathis split into two overloads. APathdefault argument makes the type reference-cycle through its own function records, which nanobind reports as a leak at interpreter shutdown; the overloads also deferPath::Current()to call time, matching the C++ default.nanobind is fetched with FetchContent, as magic_enum already is, so no development image change is needed. It is pinned to v2.9.2: v3.x requires Python 3.10 and this project still ships 3.9 wheels. Stubs now come from nanobind’s own stubgen rather than pybind11-stubgen.
One user-visible behaviour change: passing a string that is not exactly one character where a C++
charis expected (String.char("")) now raises TypeError rather than ValueError.Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
- fix: apply compact assertions to the nanobind runtime, and package stubs
Three review findings:
NB_COMPACT_ASSERTIONSwas set on the extension target, where it does nothing: the macro is only read by nanobind’s ownsrc/files. It now also reaches the target that compilesnb_combined.cpp, under the same non-Debug condition. nanobind’s documented manual build applies it to both.Stub generation wrote nothing into the package.
pybind11-stubgen -o .created theostk/core/tree, whereas nanobind’sstubgen -O .writes the named module’s stubs flat into that directory, so.pyifiles landed besidepyproject.tomland theostk.corepackage-data glob never matched them. The wheel shippedpy.typedand no stubs at all, a regression against pybind11. Output now goes to${PROJECT_PATH}.The second
String.__add__overload tookString, making it an exact duplicate of the first.mainhadself + String()alongsideself += std::string()andstd::string() + self;std::stringis the operand that completes that set. Behaviour is unchanged either way, sinceimplicitly_convertible<std::string, String>already accepted astr, but the stub now showsString + strinstead of the same overload twice.Not addressed: the
BUILD_WHEELS_IN_CMAKE=OFFbranch still generates no stubs. That block is byte-identical tomainand never generated them under pybind11 either; nothing in CI or the Makefile sets that option, which defaults to ON. Adding stubs there is a separate change.Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
Update bindings/python/src/OpenSpaceToolkitCorePy/Container/Dictionary.cpp
Update bindings/python/test/types_/test_string.py
feat: upgrade to nanobind 3
Update bindings/python/src/OpenSpaceToolkitCorePy/Container/Dictionary.cpp
chore: style
Co-authored-by: Claude Opus 5 (1M context) noreply@anthropic.com
feat!: deprecate Real and Integer, replace uses with double and int (#214)
feat: deprecate Real and Integer, replace uses with double and int
Mark type::Real and type::Integer as [[deprecated]] and replace all uses within the library, tests and Python bindings with double and int.
- Object, Logger, Pump, Table, Dictionary and String now use int/double
- Array::isNear(tolerance) and Array::toString() support arithmetic types
- Object::Integer(…) and Object::Real(…) no longer default to Undefined
- Python Integer/Real classes carry deprecation notes in their docstrings
Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
- fix: make Array arithmetic isNear overflow-safe and toString locale-independent
- isNear(tolerance): compute integral distances in the unsigned domain so INT_MIN/INT_MAX and unsigned types are handled; keep a separate floating-point comparison
- toString: imbue the classic locale before streaming floating-point values
- fix the isNear comparator example in Array.hpp
Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
- chore: apply batched suggestions from code review
Co-authored-by: Antoine Paletta 98616558+apaletta3@users.noreply.github.com
feat: address feedback
fix: update Array isNear NaN test for reviewed comparison
The reviewed isNear change compares with
distance > tolerance, so a NaN distance is no longer rejected. Update the NaN test expectation to match.Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
- fix: keep Array isNear NaN-safe for floating-point elements
Revert the
distance > toleranceform from the review suggestion: it treats a NaN distance as near. Restore!(distance <= tolerance)and the original NaN test expectation.Co-Authored-By: Claude Sonnet 5.5 noreply@anthropic.com
Co-authored-by: Claude Sonnet 5.5 noreply@anthropic.com Co-authored-by: Antoine Paletta 98616558+apaletta3@users.noreply.github.com
- refactor!: replace Undefined pattern with std::optional (#217)
Path, File and Directory are now always defined, and “no value” is expressed with std::optional instead of an Undefined() sentinel.
- Remove Undefined() and isDefined() from Path, File and Directory, along with the guards that threw on undefined instances
- Remove the unimplemented Undefined()/isDefined() declarations from System::User, System::Group and Logger::Source
- Remove Object::Format::Undefined and Table::Format::Undefined; Object::Parse, Object::Load, Object::toString, Dictionary::Parse and Table::Load take std::optional = std::nullopt, and nullopt keeps the previous auto-detect behaviour (Object::toString still throws without a format)
- Python: remove Path/File/Directory undefined() and is_defined() and Object.Format.Undefined; Object.parse/load and Dictionary.parse default format to None
Object::Undefined, Real, Integer and Sign are unchanged.
BREAKING CHANGE: removed Path::Undefined, Path::isDefined, File::Undefined, File::isDefined, Directory::Undefined, Directory::isDefined, User/Group/Source::Undefined and ::isDefined, Object::Format::Undefined and Table::Format::Undefined. Callers that need an empty value should use std::optional, and callers passing Format::Undefined should pass std::nullopt. Python: Path/File/Directory.undefined() and .is_defined() and Object.Format.Undefined are removed.
Co-authored-by: Claude Sonnet 5.5 noreply@anthropic.com
- refactor!: normalize getters to return const references for stored members (#218)
Only getters are kept. Stored non-trivial members return
const T&so the caller decides whether to copy. Computed and trivial values return by value.
- Object: getString/getDictionary/getArray return
const T&(with&&overloads returning a copy so temporaries do not dangle); the const access{Boolean,Integer,Real,String,Dictionary,Array} overloads are removed- Array: accessFirst/accessLast (const) become getFirst/getLast; accessWhere is removed in favour of getWhere
- Dictionary iterators: const accessKey/accessValue/accessMapIterator become getKey/getValue/getMapIterator
- Exception::getScope, RuntimeError::getMessage/getStackTrace and File/Directory::getPath return
const T&- Python: ConstIterator.access_key/access_value become get_key/get_value
BREAKING CHANGE: the const access* overloads on Object, Array and the Dictionary iterators are removed or renamed to get*, Array::accessWhere is removed, Python access_key/access_value are renamed to get_key/get_value, and Object::getString/getDictionary/getArray are ref-qualified so member pointers to them are ambiguous.
Co-authored-by: Claude Sonnet 5.5 noreply@anthropic.com
Co-authored-by: Claude Opus 5 (1M context) noreply@anthropic.com Co-authored-by: Antoine Paletta 98616558+apaletta3@users.noreply.github.com
Open Space Toolkit 核心库(类型、时间、容器等基础能力)。镜像收录自 https://github.com/open-space-collective/open-space-toolkit-core,License:Apache-2.0
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802047560号
Open Space Toolkit ▸ Core
Common types, containers and utilities.
Getting Started
Want to get started? This is the simplest and quickest way:
Nothing to download or install! This will automatically start a JupyterLab environment in your browser with Open Space Toolkit libraries and example notebooks ready to use.
Alternatives
Docker Images
Docker must be installed on your system.
iPython
The following command will start an iPython shell within a container where the OSTk components are already installed:
Once the shell is up and running, playing with it is easy:
Tip: Use tab for auto-completion!
JupyterLab
The following command will start a JupyterLab server within a container where the OSTk components are already installed:
Once the container is running, access http://localhost:8888/lab and create a Python 3 Notebook.
Installation
C++
The binary packages are hosted using GitHub Releases:
open-space-toolkit-core-X.Y.Z-1.x86_64-runtimeopen-space-toolkit-core-X.Y.Z-1.x86_64-developen-space-toolkit-core-X.Y.Z-1.x86_64-pythonDebian / Ubuntu
After downloading the relevant
.debbinary packages, install:Python
Install from PyPI:
Documentation
Documentation is available here:
Setup
Development Environment
Using Docker for development is recommended, to simplify the installation of the necessary build tools and dependencies. Instructions on how to install Docker are available here.
To start the development environment:
This will:
openspacecollective/open-space-toolkit-core-developmentDocker image.bashshell from the./buildworking directory.If installing Docker is not an option, you can manually install the development tools (GCC, CMake) and all required dependencies, by following a procedure similar to the one described in the Development Dockerfile.
Build
From the
./builddirectory:Tip: The
ostk-buildcommand simplifies building from within the development environment.Test
To start a container to build and run the tests:
Or to run them manually:
Tip: The
ostk-testcommand simplifies running tests from within the development environment.Contribution
Contributions are more than welcome!
Please read our contributing guide to learn about our development process, how to propose fixes and improvements, and how to build and test the code.
Special Thanks
License
Apache License 2.0