目录
Vishwa Shah

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.h has no nanobind counterpart, so each self OP self expression becomes an explicit lambda. In-place operators return a reference under rv_policy::none so that a += b keeps returning a itself.
  • init(factory) becomes a placement-new __init__.
  • make_iterator now takes a scope and a name for the iterator type.
  • arg_v(name, value, repr) becomes arg(name).sig(repr) = value.
  • handle::cast<T>() becomes the free function nanobind::cast<T>(handle).
  • Path.get_absolute_path is split into two overloads. A Path default argument makes the type reference-cycle through its own function records, which nanobind reports as a leak at interpreter shutdown; the overloads also defer Path::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++ char is 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_ASSERTIONS was set on the extension target, where it does nothing: the macro is only read by nanobind’s own src/ files. It now also reaches the target that compiles nb_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 the ostk/core/ tree, whereas nanobind’s stubgen -O . writes the named module’s stubs flat into that directory, so .pyi files landed beside pyproject.toml and the ostk.core package-data glob never matched them. The wheel shipped py.typed and no stubs at all, a regression against pybind11. Output now goes to ${PROJECT_PATH}.

  • The second String.__add__ overload took String, making it an exact duplicate of the first. main had self + String() alongside self += std::string() and std::string() + self; std::string is the operand that completes that set. Behaviour is unchanged either way, since implicitly_convertible<std::string, String> already accepted a str, but the stub now shows String + str instead of the same overload twice.

Not addressed: the BUILD_WHEELS_IN_CMAKE=OFF branch still generates no stubs. That block is byte-identical to main and 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 > tolerance form 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

3天前468次提交

Open Space Toolkit ▸ Core

Build and Test Release Code Coverage Documentation GitHub version PyPI version License

Common types, containers and utilities.

Getting Started

Want to get started? This is the simplest and quickest way:

Binder

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:

docker run -it openspacecollective/open-space-toolkit-core-development python3.11 -m IPython

Once the shell is up and running, playing with it is easy:

from ostk.core.filesystem import Directory # Directory class

Directory.root().is_empty() # True if the root directory is empty

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:

docker run --publish=8888:8888 openspacecollective/open-space-toolkit-core-jupyter

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:

  • Runtime libraries: open-space-toolkit-core-X.Y.Z-1.x86_64-runtime
  • C++ headers: open-space-toolkit-core-X.Y.Z-1.x86_64-devel
  • Python bindings: open-space-toolkit-core-X.Y.Z-1.x86_64-python

Debian / Ubuntu

After downloading the relevant .deb binary packages, install:

apt install open-space-toolkit-core-*.deb

Python

Install from PyPI:

pip install open-space-toolkit-core

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:

make start-development

This will:

  1. Build the openspacecollective/open-space-toolkit-core-development Docker image.
  2. Create a development environment container with local source files and helper scripts mounted.
  3. Start a bash shell from the ./build working 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 ./build directory:

cmake ..
make

Tip: The ostk-build command simplifies building from within the development environment.

Test

To start a container to build and run the tests:

make test

Or to run them manually:

./bin/open-space-toolkit-core.test

Tip: The ostk-test command 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

Loft Orbital

License

Apache License 2.0

关于

Open Space Toolkit 核心库(类型、时间、容器等基础能力)。镜像收录自 https://github.com/open-space-collective/open-space-toolkit-core,License:Apache-2.0

22.0 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号