rustures
Fast, memory-aware offline change-point detection for Python — powered by Rust.
Exact dynamic programming, kernel methods, robust costs, custom Python costs,
and familiar fit / predict APIs in one native extension.
Documentation · Quick start · Algorithms · Custom costs · Tutorial
rustures finds points where the statistical behaviour of a sequence changes:
its mean, distribution, trend, autoregressive dynamics, or kernel representation.
The search algorithms and built-in cost functions run in Rust while the public API
stays in Python.
The project is inspired by the excellent
ruptures ecosystem, but it is an
independent implementation rather than a complete drop-in replacement.
[!IMPORTANT]
rusturesis currently pre-alpha. The API is usable and heavily tested, but public APIs and compatibility guarantees may still change between releases.
Why rustures?
- A native core without a Python loop in the hot path. Built-in costs and detectors execute in optimized Rust.
- Real concurrency from ordinary Python threads. Built-in predictions release
the GIL while the native search runs, so independent detections can overlap in a
ThreadPoolExecutorwithout process-level serialization overhead. - Exact and approximate search strategies. Use fixed-
Kdynamic programming, penalized optimal partitioning, kernel CPD, or faster greedy detectors. - Memory is part of the API. Dynp and full-Gram kernel backends reject oversized jobs before allocating their main tables.
- Kernel CPD without mandatory quadratic storage. The default fused backend is exact and does not materialize a full Gram matrix.
- Endpoint-batched custom Python costs. Dynp and Pelt accept ordinary scalar
callbacks plus an optional vectorized
error_many(starts, ends)protocol that is not available in ruptures' scalar-only custom-cost interface. - Multivariate input is first-class. Most costs accept an
(n_samples, n_features)NumPy array; scalar signals may remain one-dimensional. - Python-safe failure boundaries. Invalid data, allocation limits, numerical failures, and unwinding Rust panics become catchable Python exceptions.
- Reproducible validation. Deterministic generators, metrics, exhaustive small oracles, parity fixtures, and raw benchmark artifacts live in the repository.
Quick start
import rustures as rpt
# Deterministic piecewise-constant data and its true breakpoints.
signal, truth = rpt.pw_constant(
n_samples=600,
n_features=2,
n_bkps=3,
noise_std=0.7,
seed=42,
)
# Penalized exact segmentation.
prediction = rpt.Pelt(
model="l2",
min_size=10,
jump=1,
).fit_predict(signal, pen=12.0)
precision, recall = rpt.precision_recall(truth, prediction, margin=10)
print("truth: ", truth)
print("prediction:", prediction)
print(f"precision={precision:.3f}, recall={recall:.3f}")
Breakpoints use the half-open interval convention and always include the terminal
sample. A result such as [120, 360, 600] represents segments [0, 120),
[120, 360), and [360, 600).
Choosing an algorithm
| You know… | Start with | What it does |
|---|---|---|
The number of changes K |
Dynp |
Exact fixed-K dynamic programming |
| A penalty per additional change | Pelt |
Exact penalized optimal partitioning; uses pruning only when the cost proves it is valid |
| The change may be nonlinear or distributional | KernelCPD |
Exact linear, RBF, or cosine kernel segmentation |
| You need a fast exploratory result | Binseg |
Recursive binary segmentation |
| You prefer merge-based segmentation | BottomUp |
Starts small and merges neighbouring segments |
| Changes should be found from a local score | Window |
Window discrepancy with deterministic peak selection |
| A scalar signal is piecewise constant with robust L1 loss | L1Potts |
Weighted scalar L1-Potts optimization |
Fixed number of changes
algo = rpt.Dynp(model="normal", min_size=8, jump=2).fit(signal)
print("workspace bytes:", algo.estimated_memory_bytes(n_bkps=3))
breakpoints = algo.predict(n_bkps=3)
Dynp defaults to a 512 MiB prediction-workspace limit. Override it explicitly when you know the process budget:
algo = rpt.Dynp(
model="l2",
jump=1,
max_memory_bytes=256 * 1024 * 1024,
).fit(signal)
# Raises MemoryError before allocating DP states if the limit would be exceeded.
breakpoints = algo.predict(n_bkps=32)
Kernel change-point detection
kernel_algo = rpt.KernelCPD(
kernel="rbf",
gamma_policy="sampled",
gamma_samples=10_000,
seed=42,
backend="fused",
min_size=5,
jump=1,
)
breakpoints = kernel_algo.fit_predict(signal, n_bkps=3)
Available kernels are "linear", "rbf", and "cosine".
| Backend | Exact? | Main storage behaviour |
|---|---|---|
fused |
Yes | Default fixed-K implementation; no full Gram matrix |
streaming |
Yes | Computes kernel contributions without retaining a full Gram table |
full |
Yes | Stores a full Gram prefix for repeated constant-time segment-cost queries |
The full backend has its own 512 MiB default limit through max_gram_bytes.
Cost models
The following model strings work with the general-purpose detectors:
| Model | Detects changes in… | Notes |
|---|---|---|
l2 |
Mean | Fast prefix sums; scalar or multivariate |
l1 |
Median / robust location | Component-wise median absolute deviation |
rank |
Distribution | Global ranks with tie handling |
normal |
Gaussian mean and covariance | Regularized covariance log-determinant |
linear |
Regression relationship | First column is the response; remaining columns are predictors |
ar |
Autoregressive dynamics | Default order is 4 |
clinear |
Continuous piecewise-linear trend | Endpoint interpolation cost |
mahalanobis |
Metric-weighted scatter | Exposed as CostMahalanobis(metric=...) / CostMl |
Standalone cost objects expose fit, error(start, end), and sum_of_costs:
cost = rpt.CostL2().fit(signal)
segment_cost = cost.error(100, 220)
partition_cost = cost.sum_of_costs([100, 220, len(signal)])
Custom Python costs
Dynp and Pelt accept any object with this protocol:
class CustomCost:
min_size: int
def fit(self, signal): ...
def error(self, start: int, end: int) -> float: ...
# Optional pairwise batch: result[i] == error(starts[i], ends[i]).
# This is not a Cartesian product of every start and end.
def error_many(self, starts, ends): ...
For example, a Bernoulli negative log-likelihood cost can be written as:
import numpy as np
import rustures as rpt
class BernoulliCost:
min_size = 1
def fit(self, signal):
values = np.asarray(signal, dtype=np.float64).reshape(-1)
if not np.all((values == 0.0) | (values == 1.0)):
raise ValueError("BernoulliCost expects only 0 and 1")
self.values = values
self.prefix = np.r_[0.0, np.cumsum(values)]
return self
def error(self, start, end):
length = end - start
ones = self.prefix[end] - self.prefix[start]
p = ones / length
if p == 0.0 or p == 1.0:
return 0.0
return -(ones * np.log(p) + (length - ones) * np.log1p(-p))
def error_many(self, starts, ends):
starts = np.asarray(starts, dtype=np.intp)
ends = np.asarray(ends, dtype=np.intp)
lengths = ends - starts
ones = self.prefix[ends] - self.prefix[starts]
probabilities = ones / lengths
mixed = (ones > 0.0) & (ones < lengths)
costs = np.zeros(len(starts), dtype=np.float64)
costs[mixed] = (
-ones[mixed] * np.log(probabilities[mixed])
-(lengths[mixed] - ones[mixed])
* np.log1p(-probabilities[mixed])
)
return costs
binary_signal = np.r_[np.zeros(80), np.ones(60), np.zeros(90)]
breakpoints = rpt.Dynp(
custom_cost=BernoulliCost(),
min_size=10,
jump=1,
).fit_predict(binary_signal, n_bkps=2)
Unlike ruptures' custom-cost protocol, which calls error(start, end) once per
candidate, Rustures can send every candidate ending at the current endpoint through
one error_many call. This makes NumPy broadcasting and prefix-array indexing
possible without storing a full O(n²) cost table. Search algorithms batch only
the candidates they currently need, while a standalone segment request evaluates
only that segment.
The batch contract is pairwise, not Cartesian. For one-dimensional arrays with
shape (m,), the returned float64 array must also have shape (m,) and satisfy
costs[i] == error(int(starts[i]), int(ends[i])). During endpoint batching, all
entries of ends normally contain the same endpoint:
starts = [0, 4, 8]
ends = [20, 20, 20]
costs = [C(0,20), C(4,20), C(8,20)]
error_many must be genuinely vectorized to provide the largest benefit. Wrapping
scalar error calls in a Python list comprehension reduces Rust/Python crossings
but retains the Python loop. In a local pruned-Pelt workload (N=800, two features,
jump=4), a vectorized prefix-L2 callback reduced Rustures' callback count from
6,586 to 203 and predict time from 75.40 ms to 2.96 ms. This 25.5x figure is an
internal scalar-versus-vectorized Rustures comparison, not a claim that every
custom cost or every workload is 25.5x faster than ruptures.
Exceptions raised by a custom cost preserve their Python type, message, and
traceback. Custom Pelt uses the exact unpruned path because arbitrary user costs do
not automatically satisfy the PELT pruning inequality. A cost whose author has
proved the PELT inequality may explicitly expose a finite constant:
class PrunableCustomCost(CustomCost):
pelt_pruning_constant = 0.0
This is a mathematical correctness promise, not a tuning flag: an invalid value
can prune the optimal partition. After fitting, Pelt.uses_pelt_pruning reports
whether the optimized path is active.
Included utilities
Deterministic signal generators:
pw_constantpw_linearpw_normalpw_wavy
Evaluation metrics:
hausdorffprecision_recallrand_index
All generators require an explicit seed and return (signal, breakpoints). A seed
is reproducible within a Rustures version; generator streams may change between
releases when the documented RNG implementation is optimized.
Performance snapshot
The latest integration benchmark used Windows x86-64, Python 3.11, Rustures 0.1.1, ruptures 1.1.10, isolated worker processes, and five warmed timing runs. It exercised 57 cost, detector, kernel, custom-cost, metric, and dataset cases. Rustures returned valid results in every case; 39 of 40 comparable breakpoint results matched exactly. The remaining AR case uses a documented different segment-boundary policy.
| Measured group | Geometric-mean result versus ruptures |
|---|---|
L2 Dynp, four signal families (N=720) |
1347.00× faster |
L2 Pelt, four signal families (N=1200) |
668.77× faster |
Fused KernelCPD, linear/RBF/cosine (N=720) |
1.37× faster |
Full-Gram KernelCPD (N=720) |
1.89× slower |
Gram-free streaming KernelCPD (N=720) |
1.12× slower |
Scalar custom Pelt with proven pruning opt-in (N=800) |
1.07× slower |
Synthetic dataset generators (N=80000) |
1.33× faster |
The streaming backend incrementally reuses each symmetric kernel pair while
retaining only O(n) endpoint state; fused remains the default high-throughput
path. These are machine- and workload-specific measurements, not universal
guarantees. Raw timing, breakpoint, environment, and process-RSS data is available
in artifacts/validation/integration-comparison-optimized-windows-py311.json,
and the reproducible driver is
benchmarks/integration_comparison.py.
Correctness and safety
The repository currently checks correctness through several independent layers:
- exhaustive enumeration for small fixed-
Kand penalized problems; - black-box parity fixtures generated from pinned
rupturesbehaviour; - full-Gram, streaming, fused, scalar, and AVX2 backend parity tests;
- deterministic tie-breaking tests;
- finite-input, overflow, singular, collinear, constant, and large-offset cases;
- 2,528 Linear/AR fast-path comparisons against scalar SVD Dynp and Pelt;
- Python exception and Rust panic-boundary process-survival tests.
The AVX2 path uses runtime CPU detection. CPUs without AVX2 automatically use the scalar implementation instead of failing at import time.
Installation
Current compatibility
- Python 3.10 or newer is declared through
abi3-py310. - NumPy 1.23 or newer is required.
- Binary wheels are published for Linux x86-64 and ARM64, Windows x86-64, and macOS Intel and Apple Silicon.
- The current wheels target GIL-enabled CPython. They do not target 32-bit Python, PyPy, free-threaded CPython, or native Windows ARM64.
Install a published wheel from PyPI:
python -m pip install rustures
Build from source
Prerequisites: Python 3.10+, Rust 1.83+, and a working native compiler toolchain.
git clone https://github.com/denrew88/rustures.git
cd rustures
python -m venv .venv
Activate the environment:
Windows PowerShell: .venv\Scripts\Activate.ps1
Linux/macOS: source .venv/bin/activate
Build and install an editable release extension:
python -m pip install --upgrade pip
python -m pip install "maturin>=1.14,<2.0" "numpy>=1.23"
python -m maturin develop --release
Or create a wheel:
python -m maturin build --release
The wheel is written to target/wheels/.
Development
# Rust unit, oracle, and parity tests
cargo test
# Formatting and linting
cargo fmt -- --check
cargo clippy --all-targets --all-features -- -D warnings
# Python wheel tests after installing a built wheel
python -m pip install pytest
python -m pytest tests/python/test_wheel.py -q
# Longer Linear/AR regression matrix
cargo test --release --test regression_mass -- --ignored --nocapture
Tutorial notebooks are available in English and Korean.
Project status
Implemented today:
- Dynp, Pelt, Binseg, BottomUp, Window, KernelCPD, and L1Potts
- eight general-purpose cost models
- linear, RBF, and cosine kernels with three exact backends
- custom Python costs for Dynp and Pelt
- multivariate signal handling, metrics, and deterministic datasets
- typed Python errors, panic isolation, memory preflight, and type hints
Major work still planned:
- approximate low-rank kernel backends;
- broader profiling across CPU architectures and feature dimensions;
- additional interpreter and architecture coverage as the API matures.
License
Licensed under either of
at your option.
The Rust dependencies compiled into the wheel, their selected license options,
copyright notices, and full license texts are recorded in
THIRD-PARTY-LICENSES. The report is generated from
Cargo.lock for the verified Windows x86-64 target with:
cargo install --locked --features cli cargo-about
cargo about generate --locked --fail -c about.toml -o THIRD-PARTY-LICENSES about.hbs
Built for people who want Python ergonomics, Rust execution, and explicit correctness contracts in offline change-point detection.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rustures-0.2.0.tar.gz.
File metadata
- Download URL: rustures-0.2.0.tar.gz
- Upload date:
- Size: 362.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3ef37692f931ffda870e5026f78abb12ec69d7d686053d81ac1378927097b96
|
|
| MD5 |
407153460baad3e1ca04b495f6a1fec0
|
|
| BLAKE2b-256 |
90dbc3f1a14f6c1e1d6035ae472561977ef7a29b011a4ac52e464b873e39cf6d
|
Provenance
The following attestation bundles were made for rustures-0.2.0.tar.gz:
Publisher:
release.yml on denrew88/rustures
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rustures-0.2.0.tar.gz -
Subject digest:
d3ef37692f931ffda870e5026f78abb12ec69d7d686053d81ac1378927097b96 - Sigstore transparency entry: 2700608846
- Sigstore integration time:
-
Permalink:
denrew88/rustures@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/denrew88
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rustures-0.2.0-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: rustures-0.2.0-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 509.0 kB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d3faede1044299d4eee88f43a9634231217d44bd0679a955afce32524c15894
|
|
| MD5 |
d5ef55d638589a00427e47173c65d3ec
|
|
| BLAKE2b-256 |
fc4f9027fdba206f27d8e79133203dc9088d5c49362430cdb66caba38daa0643
|
Provenance
The following attestation bundles were made for rustures-0.2.0-cp310-abi3-win_amd64.whl:
Publisher:
release.yml on denrew88/rustures
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rustures-0.2.0-cp310-abi3-win_amd64.whl -
Subject digest:
7d3faede1044299d4eee88f43a9634231217d44bd0679a955afce32524c15894 - Sigstore transparency entry: 2700609156
- Sigstore integration time:
-
Permalink:
denrew88/rustures@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/denrew88
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rustures-0.2.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: rustures-0.2.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 577.5 kB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
080ff2793c1182bf9e0d65fe106df8859908453ff8a8a13d3fdffa3281f70747
|
|
| MD5 |
0d13534e630bcf7bf9eff1f2db289fc4
|
|
| BLAKE2b-256 |
4d9bcf8b29eeed478e4df964f57da2930df94a74bf436039c385d55d7c5b2512
|
Provenance
The following attestation bundles were made for rustures-0.2.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on denrew88/rustures
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rustures-0.2.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
080ff2793c1182bf9e0d65fe106df8859908453ff8a8a13d3fdffa3281f70747 - Sigstore transparency entry: 2700609062
- Sigstore integration time:
-
Permalink:
denrew88/rustures@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/denrew88
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rustures-0.2.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: rustures-0.2.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 517.5 kB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e9a03248a3290c180846a7faa2d9c649a3c23f36d64236765c1c5de2e549ff1
|
|
| MD5 |
d61606d3ec68f90f1f937470aeeeb1ee
|
|
| BLAKE2b-256 |
4d8546d50e01f632d5a5df5999ff43c58e5311850b4d8046d67215d72bd93d36
|
Provenance
The following attestation bundles were made for rustures-0.2.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on denrew88/rustures
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rustures-0.2.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
2e9a03248a3290c180846a7faa2d9c649a3c23f36d64236765c1c5de2e549ff1 - Sigstore transparency entry: 2700609266
- Sigstore integration time:
-
Permalink:
denrew88/rustures@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/denrew88
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rustures-0.2.0-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: rustures-0.2.0-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 502.3 kB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
408b8bb82de69c289b90a5805f81e8b33940aaeb2bb30af6064a4c30bc9dfb2e
|
|
| MD5 |
8677be09259039d6d8f198679c944135
|
|
| BLAKE2b-256 |
a6186c580af41d48f38070afd72814b2365df36a2bdc85b0ae6c8364c15dc164
|
Provenance
The following attestation bundles were made for rustures-0.2.0-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on denrew88/rustures
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rustures-0.2.0-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
408b8bb82de69c289b90a5805f81e8b33940aaeb2bb30af6064a4c30bc9dfb2e - Sigstore transparency entry: 2700608914
- Sigstore integration time:
-
Permalink:
denrew88/rustures@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/denrew88
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rustures-0.2.0-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: rustures-0.2.0-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 542.7 kB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
05c356b3fce3e8fc427660c2f707208559b235aa3beceec2fa304c2a9803a1a3
|
|
| MD5 |
5d0f61108ebbef4747f23eb399d76452
|
|
| BLAKE2b-256 |
311250c07c42d0dba390e1f3fc68fe27484e7020aef99bc0428992bd16eec97b
|
Provenance
The following attestation bundles were made for rustures-0.2.0-cp310-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on denrew88/rustures
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rustures-0.2.0-cp310-abi3-macosx_10_12_x86_64.whl -
Subject digest:
05c356b3fce3e8fc427660c2f707208559b235aa3beceec2fa304c2a9803a1a3 - Sigstore transparency entry: 2700608988
- Sigstore integration time:
-
Permalink:
denrew88/rustures@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/denrew88
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@79d6c43adbb5ef1a10525eea9e4bc47fa2858104 -
Trigger Event:
push
-
Statement type: