tinyvdb
Lightweight Python bindings for TinyVDB — a lightweight C/C++ library for OpenVDB and NanoVDB file I/O, mesh-to-SDF conversion, and grid operations. No OpenVDB dependency required.
Built with the Python C Stable API (abi3) for broad compatibility: one wheel per platform works across CPython 3.11+.
The 0.9.1 release adds owning tree-maintenance results and sparse rebuild, resampling, meshing, and Poisson methods. Python views raise errors after their source is closed, reloaded, or replaced.
Installation
pip install tinyvdb
Pre-built wheels are available for:
| Platform | Architectures |
|---|---|
| Linux | x86_64, aarch64 |
| macOS | x86_64, arm64 |
| Windows | AMD64 |
Default wheels use portable scalar CPU kernels and do not require AVX2, OpenMP, Vulkan, or CUDA. NumPy is optional for array convenience functions. To enable SIMD when compiling from source for a compatible machine:
pip install --no-binary=tinyvdb tinyvdb -Ccmake.define.TINYVDB_SIMD=ON
Quick start
Read a VDB file
import tinyvdb
with tinyvdb.open("smoke.vdb") as f:
print(f.grid_count, "grids")
print(f.header)
f.read_grids()
grid = f.grid(0)
print(grid.name, grid.type_name)
print(grid.transform)
print(grid.metadata)
# Access tree structure
tree = grid.tree
node = tree.node(0)
print(node.type, node.origin)
Read a NanoVDB file
from contextlib import closing
from tinyvdb import nanovdb
with closing(nanovdb.NanoVDBFile("sphere.nvdb")) as f:
print(f.grid_count(), "grids")
for i in range(f.grid_count()):
print(f" Grid {i}: {f.grid_name(i)}")
print(f" Type: {f.grid_type(i)}")
print(f" Class: {f.grid_class(i)}")
print(f" Voxel size: {f.voxel_size(i)}")
print(f" BBox: {f.bbox(i)}")
print(f" World BBox: {f.world_bbox(i)}")
print(f" Node counts: {f.node_counts(i)}")
print(f" Active voxels: {f.active_voxel_count(i)}")
NanoVDB utilities
from tinyvdb import nanovdb
# Node sizes
leaf_size = nanovdb.leaf_node_size() # Default: Float
lower_size = nanovdb.lower_node_size() # Default: Float
upper_size = nanovdb.upper_node_size() # Default: Float
# Value sizes
float_size = nanovdb.value_size() # 4 bytes
vec3f_size = nanovdb.value_size(nanovdb.GRID_TYPE_VEC3F) # 12 bytes
double_size = nanovdb.value_size(nanovdb.GRID_TYPE_DOUBLE) # 8 bytes
# Grid type names
name = nanovdb.grid_type_name(nanovdb.GRID_TYPE_FLOAT) # "Float"
Load from bytes / save round-trip
data = open("input.vdb", "rb").read()
f = tinyvdb.from_bytes(data)
f.read_grids()
# Serialize back
output = f.to_bytes(compression=tinyvdb.COMPRESS_ZIP, level=5)
open("output.vdb", "wb").write(output)
f.close()
Mesh to SDF and back
import struct
import tinyvdb
# Vertices as flat float32 buffer, faces as flat uint32 buffer
vertices = struct.pack("9f", 0,0,0, 1,0,0, 0,1,0)
faces = struct.pack("3I", 0, 1, 2)
# Convert mesh to signed distance field
sdf = tinyvdb.mesh_to_sdf(vertices, faces, voxel_size=0.05, band_width=3.0)
print(sdf.shape) # (nx, ny, nz)
# Extract mesh via marching cubes
mesh = tinyvdb.sdf_to_mesh(sdf, isovalue=0.0)
print(mesh.num_vertices, mesh.num_faces)
Level-set primitives & SDF utilities
Generate analytic narrow-band SDFs (parallels OpenVDB's LevelSetSphere /
LevelSetPlatonic / LevelSetTubes) as DenseGrids, then operate on them with
the dense ops (CSG, filters, marching cubes) or write them to .vdb. Every voxel
holds the true signed distance clamped to ±half_width * voxel_size; negative is
inside. The grid is sized to enclose the primitive plus the band margin.
import numpy as np
import tinyvdb
sphere = tinyvdb.level_set_sphere(radius=1.0, center=(0, 0, 0), voxel_size=0.05)
box = tinyvdb.level_set_box(half_extents=(0.5, 0.4, 0.6))
torus = tinyvdb.level_set_torus(major_radius=1.0, minor_radius=0.3) # XZ plane, axis Y
capsule = tinyvdb.level_set_capsule(p0=(-0.5, 0, 0), p1=(0.5, 0, 0), radius=0.25)
# Platonic solids (radius = circumradius). Either the generic form or a named
# wrapper; the field is the convex half-space SDF (exact isosurface).
ico = tinyvdb.level_set_icosahedron(radius=1.0)
solid = tinyvdb.level_set_platonic(face_count=12, radius=1.0) # 4/6/8/12/20
print(sphere.shape, sphere.voxel_size, sphere.origin)
arr = np.array(sphere, copy=False) # zero-copy float32 view
# Combine and re-mesh
both = tinyvdb.csg_union(sphere, box)
mesh = tinyvdb.sdf_to_mesh(both, isovalue=0.0)
# SDF utilities
fog = tinyvdb.sdf_to_fog_volume(sphere) # density = clamp(-sdf/(hw*voxel), 0, 1)
mask = tinyvdb.sdf_interior_mask(sphere, isovalue=0.0) # 1.0 inside, 0.0 outside
# Split disjoint objects; extract sealed cavities
segments = tinyvdb.sdf_segmentation(grid, isovalue=0.0, connectivity=6) # list[DenseGrid]
voids = tinyvdb.sdf_extract_enclosed_regions(grid) # 1.0 mask of interior cavities
# Topology measures of the isosurface
chi = tinyvdb.level_set_euler_characteristic(torus) # 0.0 (2 for a sphere)
genus = tinyvdb.level_set_genus(torus) # 1 (0 for a sphere)
# Rebuild a clean SDF from the isosurface (renormalize and/or resample)
clean = tinyvdb.level_set_rebuild(damaged, isovalue=0.0, voxel_size=0.05)
Note:
level_set_rebuild(andmesh_to_sdf) use a brute-force mesh-to-SDF (O(voxels × triangles)); keep the voxel size coarse for large surfaces.
All generators take voxel_size= and half_width= (band width in voxels,
default 3, matching OpenVDB's LEVEL_SET_HALF_WIDTH).
Statistics & diagnostics
s = tinyvdb.grid_statistics(grid) # {min, max, mean, stddev, sum, count}
h = tinyvdb.grid_histogram(grid, -1.0, 1.0, nbins=32) # list of bin counts
# A valid narrow-band SDF has |grad| == 1 in the band:
chk = tinyvdb.check_level_set(grid, band_width=0.1, tol=0.1) # {mean_grad_mag, ...}
# A valid fog volume has all values in [0, 1]:
ok = tinyvdb.check_fog_volume(grid)["valid"]
Resampling & advection
# Resample to any voxel size over the same world AABB (order 0/1/2).
coarse = tinyvdb.resample_grid(grid, 0.1, order=1)
# Restore interior signs of a level set after an unsigned operation.
clean = tinyvdb.signed_flood_fill(grid, band_width=0.15)
# Higher-order advection through a steady velocity field (DenseVecGrid):
out = tinyvdb.advect(field, velocity, dt, scheme=tinyvdb.ADVECT_MACCORMACK, clamp=1)
# scheme: ADVECT_RK1..ADVECT_RK4, ADVECT_MACCORMACK, ADVECT_BFECC
Points & coordinate queries
# Point cloud -> unique occupied voxel coords / occupancy mask.
coords = tinyvdb.voxelize_points(points, voxel_size=0.05)
mask = tinyvdb.points_to_mask(points, 0.05) # DenseGrid
# Membership / index queries against an active coord set.
inside = tinyvdb.points_in_grid(points, coords, 0.05)
idx = tinyvdb.ijk_to_index(coords, query_coords) # -1 if absent
codes = tinyvdb.morton_encode(coords) # Z-order
# Higher-order sampling and point scatter.
vals = tinyvdb.sample_quadratic(grid, pts.tobytes()) # smoother than trilinear
pts = tinyvdb.scatter_points_in_sdf(sdf, n=1000) # uniform interior points
# Emission-absorption volume render (pinhole camera) -> (H, W) float image.
img = tinyvdb.volume_render(density, eye=(0, 0, 4), center=(0, 0, 0),
width=256, height=256, sigma=20.0)
Operators & filters
# Vector-grid operators (GridOperators)
mag = tinyvdb.magnitude(vec) # DenseVecGrid -> DenseGrid (|v|)
unit = tinyvdb.normalize(vec) # DenseVecGrid -> DenseVecGrid (v/|v|)
near = tinyvdb.cpt(sdf) # closest-point transform of an SDF
# Per-voxel composite of two same-shape grids
u = tinyvdb.comp_max(a, b) # also comp_min / comp_sum / comp_mult
# In-place-style filters (return a new DenseGrid)
m = tinyvdb.median_filter(grid, radius=1, iterations=1)
s = tinyvdb.mean_curvature_flow(grid, dt=0.0003, iterations=8) # keep dt small
Write a dense grid to .vdb
Write an existing dense field (e.g. an SDF you already computed) to a fresh .vdb
file. world = voxel_size * index + origin (per-axis ScaleTranslateMap).
The grid value type is selected from the numpy array's dtype:
| array | grid type written |
|---|---|
(nx, ny, nz) float32 |
Tree_float_5_4_3 |
(nx, ny, nz) float64 |
Tree_double_5_4_3 |
(nx, ny, nz) int32 |
Tree_int32_5_4_3 |
(nx, ny, nz) int64 |
Tree_int64_5_4_3 |
(nx, ny, nz) bool |
Tree_bool_5_4_3 (see note) |
(nx, ny, nz, 3) float32 |
Tree_vec3s_5_4_3 (vec3f) |
import numpy as np
import tinyvdb
sdf = np.random.randn(32, 32, 24).astype(np.float32) # your dense (nx, ny, nz) field
# numpy convenience (round-trips bit-exactly, dtype preserved):
tinyvdb.write_dense_grid("sdf.vdb", sdf, voxel_size=(0.05, 0.06, 0.07),
origin=(1.0, 2.0, 3.0), name="sdf")
arr, voxel_size, origin = tinyvdb.read_dense_grid("sdf.vdb")
assert np.array_equal(arr, sdf)
# other scalar types and vec3f, same call:
labels = np.random.randint(0, 10, (16, 16, 16)).astype(np.int32)
tinyvdb.write_dense_grid("labels.vdb", labels) # Tree_int32_5_4_3
velocity = np.random.randn(16, 16, 16, 3).astype(np.float32)
tinyvdb.write_dense_grid("vel.vdb", velocity) # Tree_vec3s_5_4_3
# numpy-free raw API for float (values is an nx*ny*nz float32 buffer in C order):
import struct
buf = struct.pack("24f", *range(24))
tinyvdb.write_float_grid("grid.vdb", buf, 2, 3, 4,
voxel_size=(0.1, 0.1, 0.1), origin=(0.0, 0.0, 0.0))
Note on
bool: tinyvdb stores BOOL grids as 1 byte/voxel rather than OpenVDB's bit-packed 1-bit format. Such files round-trip self-consistently throughread_dense_gridbut are not byte-compatible with OpenVDB and will not load in DCCs (Houdini/Blender/etc).
Write a sparse grid to .vdb
When you only have a set of active voxels (not a full dense block), write them
directly with write_sparse_grid — same dtype rules as write_dense_grid
(scalar (N,) arrays, or (N, 3) float32 for vec3f). Coords are world-voxel
indices and need not be contiguous.
import numpy as np, tinyvdb
coords = np.array([[0, 0, 0], [10, 2, 3], [100, 100, 100]], dtype=np.int32)
values = np.array([1.0, 2.0, 3.0], dtype=np.float32)
tinyvdb.write_sparse_grid("sparse.vdb", coords, values, voxel_size=0.1, name="pts")
coords_out, values_out, voxel_size, origin = tinyvdb.read_sparse_grid("sparse.vdb")
CSG operations
union = tinyvdb.csg_union(sdf_a, sdf_b)
intersection = tinyvdb.csg_intersection(sdf_a, sdf_b)
difference = tinyvdb.csg_difference(sdf_a, sdf_b)
Morphology and filtering
dilated = tinyvdb.dilate(sdf, iterations=2)
eroded = tinyvdb.erode(sdf, iterations=1)
smoothed = tinyvdb.gaussian_filter(sdf, width=1, iterations=3)
Measurement
area = tinyvdb.surface_area(sdf)
vol = tinyvdb.volume(sdf)
Ray casting
hit = tinyvdb.ray_cast_sdf(sdf,
origin=(0, 0, -5),
direction=(0, 0, 1),
max_t=100.0)
if hit:
print(hit["t"], hit["position"], hit["normal"])
Differential operators
grad = tinyvdb.gradient(sdf) # -> DenseVecGrid
div = tinyvdb.divergence(grad) # -> DenseGrid
lap = tinyvdb.laplacian(sdf) # -> DenseGrid
c = tinyvdb.curl(vec_field) # -> DenseVecGrid
Advection and Poisson solver
advected = tinyvdb.advect(field, velocity, dt=0.01)
solution, iterations = tinyvdb.solve_poisson(rhs, max_iters=500, tolerance=1e-6)
Particles and fracture
# Rasterize particles into SDF
sdf = tinyvdb.particles_to_sdf(positions, radii,
voxel_size=0.05, band_width=3.0)
# Fill volume interior with spheres
result = tinyvdb.volume_to_spheres(sdf, min_radius=0.01, max_spheres=500)
# Fracture volume with cutter SDFs
pieces = tinyvdb.fracture(volume, [cutter1, cutter2])
Manifold repair
mesh = tinyvdb.make_manifold(vertices, faces,
resolution=50, isovalue=0.55)
numpy interop
DenseGrid supports the buffer protocol, so zero-copy access works with numpy:
import numpy as np
grid = tinyvdb.mesh_to_sdf(verts, faces, 0.1, 3.0)
arr = np.frombuffer(grid, dtype=np.float32).reshape(grid.shape)
API reference
Types
| Type | Description |
|---|---|
VDBFile |
VDB file handle (context manager) |
VDBGrid |
Grid accessor (name, type, transform, metadata, tree) |
VDBTree |
Tree structure with node access |
VDBNode |
Tree node (root, internal, or leaf) |
DenseGrid |
3D scalar grid with buffer protocol |
DenseVecGrid |
3D vector field (3-component) with buffer protocol |
TriangleMesh |
Triangle mesh (vertices + faces as bytes) |
VDBError |
Exception type (subclass of RuntimeError) |
Constants
Compression
| Constant | Value | Description |
|---|---|---|
COMPRESS_NONE |
0 | No compression |
COMPRESS_ZIP |
1 | ZIP (zlib/miniz) |
COMPRESS_ACTIVE_MASK |
2 | Compress node masks |
COMPRESS_BLOSC |
4 | BLOSC (LZ4) |
SIGN_FLOOD_FILL |
0 | Exterior flood fill sign method |
SIGN_SWEEP |
1 | Directional sweep sign method |
NanoVDB constants below are available through tinyvdb.nanovdb.
NanoVDB Codecs
| Constant | Value | Description |
|---|---|---|
CODEC_NONE |
0 | No compression |
CODEC_ZIP |
1 | ZIP compression |
CODEC_BLOSC |
2 | BLOSC compression |
NanoVDB Grid Types
| Constant | Value | Description |
|---|---|---|
GRID_TYPE_FLOAT |
1 | 32-bit float |
GRID_TYPE_DOUBLE |
2 | 64-bit double |
GRID_TYPE_INT32 |
4 | 32-bit integer |
GRID_TYPE_INT64 |
5 | 64-bit integer |
GRID_TYPE_VEC3F |
6 | 3D float vector |
GRID_TYPE_VEC3D |
7 | 3D double vector |
NanoVDB Grid Classes
| Constant | Value | Description |
|---|---|---|
GRID_CLASS_LEVEL_SET |
1 | Level set |
GRID_CLASS_FOG_VOLUME |
2 | Fog volume |
GRID_CLASS_POINT_DATA |
6 | Point data |
Loaded-tree maintenance and ownership
with tinyvdb.open("sphere.vdb") as f:
f.read_grids()
grid = f.grid(0)
report = grid.diagnose() # generic finite-value/structural/transform checks
level_set = grid.diagnose(kind="level_set", check_gradient=True, tolerance=0.1)
result = grid.signed_flood_fill().prune()
# The result owns an independent tree and remains usable after f closes.
result.save("maintained.vdb")
payload = result.to_bytes()
diagnose(kind="generic" | "level_set" | "fog", check_gradient=False, tolerance=0.1) returns valid, flags, active voxel/tile counts, exact int64
active_bbox (exclusive maximum, or None), nonfinite_values, first bad node
and coordinate, and gradient statistics (band_count, mean_grad_mag,
max_grad_error, bad_fraction). Gradient checks require kind="level_set".
Flags match tinyvdb_tree.h: nonfinite=1, transform=2, background=4, active
tiles=8, range=16, inactive=32, gradient=64, class=128. Numeric defects are reports;
unsupported or structurally invalid trees raise VDBError.
signed_flood_fill(outside_width=None, inside_width=None) defaults to the root
background and its negation. Widths are finite positive/negative float world
distances. Use only on closed narrow bands; it propagates signs rather than
reconstructing distance. prune() is exact, preserving value bits and active
states; mixed signs/states never collapse. Both methods are float-tree only,
reject nonfinite data, return independently owned VDBGrid objects and preserve
the source. Flood fill rejects active tiles; pruning can create them. to_sparse
and to_sparse_typed reject active tiles rather than silently omitting their
volume. save and to_bytes serialize one grid using the existing compression
arguments (compression, level; save also accepts use_mmap). Borrowed
instance grids must first be made independent through maintenance.
Borrowed grid/tree/node views keep their file owner alive, but explicit close,
read_grids, replace_grid_from_sparse, and extend_grid_from_sparse invalidate
old views. Reacquire views after a reload or replacement. A reload invalidates
views even when it fails; a failed replacement does not. Any successful grid
replacement invalidates all views in that file. Access through a stale view
raises ValueError. Competing owner/view calls while heavy work releases the GIL
raise RuntimeError; serialize operations on the same owner. Dense constructors
validate dimensions/geometry and refuse reinitialization, preserving exported
buffers. Raw float/index input buffers require complete four-byte elements;
mesh buffers require complete triples.
Sparse tracking, affine sampling, meshing and PDE
with tinyvdb.open("sphere.vdb") as f:
f.read_grids()
source = f.grid(0).signed_flood_fill()
tracked = source.track_level_set(outside_width=3, inside_width=3)
rebuilt = source.rebuild_level_set(isovalue=0.2, outside_width=3, inside_width=3)
mesh = tracked.volume_to_mesh(adaptivity=0.05)
target = [[0, -0.5, 0.1, 0], [0.5, 0, 0, 0],
[0, 0, 0.75, 0], [0, 0, 0, 1]]
sampled = tracked.resample(target, sampler="linear")
# All results remain usable independently after file closure.
tracked.save("tracked.vdb")
rebuild_level_set(isovalue=0, outside_width=background, inside_width=background, max_voxels=0) reconstructs a world-distance band around
a closed, resolved isosurface. track_level_set has the same width/budget
arguments and uses isovalue zero. Both widths are positive magnitudes. These
methods change active values and topology, require orthogonal isotropic axes and
positive exterior background, and use geometric redistancing rather than
iterative advection/tracking. A nonzero isovalue must still lie below background.
They cannot repair unresolved/open surfaces.
resample(matrix, sampler="linear", max_voxels=0) accepts four matrix rows or
sixteen row-major values, mapping integer target indices to world coordinates.
Nearest sampling uses floor(x+0.5) per source axis; linear sampling uses eight
weighted taps. All finite invertible affine transforms are supported. Stored
inactive values and tiles contribute; only nonzero-weight active taps activate
the output. Values retain their scalar units; no redistancing is performed.
volume_to_mesh(isovalue=0, adaptivity=0, max_cells=0) returns an owning
TriangleMesh. Stored inactive values also determine the surface. Positive
adaptivity bounds vertex displacement in world units, using global clustering;
it does not guarantee topology preservation or manifoldness. Reflection-aware
winding is outward for the phase below isovalue. No dense bounding box is built.
rhs.solve_poisson(max_iterations=500, tolerance=1e-6, boundary="dirichlet", boundary_value=0, coefficient=1, max_voxels=0) returns
(solution, report) for -div(k grad u)=rhs over active voxels. The report has
iterations, converged, initial_residual_norm and final_residual_norm.
Python exposes constant conductivity and uniform Dirichlet/Neumann data; C callers
can supply per-face boundary and coefficient callbacks. Dirichlet values are at
missing neighbor centers; Neumann values are outward flux at half-cell faces.
Pure-Neumann components require compatible summed RHS/flux and get separate
zero means. Orthogonal anisotropic axes are supported; shear is rejected. The
solver starts at zero, uses double PCG, and checks residuals after float rounding.
A finite iterate is returned on iteration exhaustion with converged=False.
These methods preserve the source, produce independent libc-owned results and
use the existing stale-view/busy-owner guards. Zero budgets select 1,000,000
coordinates/cells; exceeding a working-set or scan budget raises VDBError.
Active tiles can expand within these budgets. Sparse methods are CPU-only.
Supported VDB versions
Reads and writes OpenVDB files version 220 through 225 (OpenVDB 3.x to 10.x+).
License
Apache License 2.0
Metadata
Release files for tinyvdb 0.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tinyvdb-0.9.1.tar.gz | 5.9 MB | With provenance | Details for tinyvdb-0.9.1.tar.gz |
Built distributions (wheels)
Total release size: 11.6 MB
Release files / tinyvdb-0.9.1.tar.gz
| Download URL | tinyvdb-0.9.1.tar.gz |
|---|---|
| Size | 5.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1935989687ec4b9044e8b8f8dcc153e52aa8cb406754a017e7a264da1b00bd77
|
|
BLAKE2b-256 checksum How to use checksums |
468f4146e77caa55d6f8d2642b9a13e155c4f817c2559ab84fc1bb4b3a66819b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / tinyvdb-0.9.1-cp311-abi3-win_amd64.whl
| Download URL | tinyvdb-0.9.1-cp311-abi3-win_amd64.whl |
|---|---|
| Size | 449.5 kB |
| Tags | CPython 3.11 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
e6d61d7cd650738e31a285c08f0e9c1cd78e56146175ede96f73d6b460acd21c
|
|
BLAKE2b-256 checksum How to use checksums |
8515311820b8874826156fb313531aefa4ea0cd72dccc4d2e410586849a1d2be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / tinyvdb-0.9.1-cp311-abi3-musllinux_1_2_x86_64.whl
| Download URL | tinyvdb-0.9.1-cp311-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 956.8 kB |
| Tags | CPython 3.11 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
b5022cb836f63cf046c107d5c4e180f4b44e42c1668896e40d1ecca7528d65cb
|
|
BLAKE2b-256 checksum How to use checksums |
e84f79c2139adaa0ec56dde6da492010d7dff8657ecc6cdf80fb5ef772bef7d7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / tinyvdb-0.9.1-cp311-abi3-musllinux_1_2_aarch64.whl
| Download URL | tinyvdb-0.9.1-cp311-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 918.5 kB |
| Tags | CPython 3.11 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
d266a89b4e59e9f6814c3d2ce47b820a7dea9f3ddb4fe5b94de883e9a5d1d746
|
|
BLAKE2b-256 checksum How to use checksums |
8665adeefd645e9831e761b9b955ca114fdaa503e28d2219ff5e85c8cec686d7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / tinyvdb-0.9.1-cp311-abi3-manylinux_2_28_x86_64.whl
| Download URL | tinyvdb-0.9.1-cp311-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 948.0 kB |
| Tags | CPython 3.11 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
edcca77bb49a0ce8200dd054719c7c9599dbc7cedaebaf702a203bd9e9586ad8
|
|
BLAKE2b-256 checksum How to use checksums |
203d1ed564bd3344df8d58c1747b2b535cf466fd5dc078b14f8086f8a0042943
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / tinyvdb-0.9.1-cp311-abi3-manylinux_2_28_aarch64.whl
| Download URL | tinyvdb-0.9.1-cp311-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 898.2 kB |
| Tags | CPython 3.11 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
a9657cf48222fde8dd4b34f2e5b22f22cf9f3f872a898f784d3978f87953dd7f
|
|
BLAKE2b-256 checksum How to use checksums |
1046f5794095e9d5a2874f33be91e622acd936fce64e46eabff429d4d064c669
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / tinyvdb-0.9.1-cp311-abi3-macosx_11_0_arm64.whl
| Download URL | tinyvdb-0.9.1-cp311-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 721.8 kB |
| Tags | CPython 3.11 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1010c85dc4d6539cd7e90fe7f33a3ed7e7f8e34bddef1ecb829f14a3b417432e
|
|
BLAKE2b-256 checksum How to use checksums |
14596bf5534b10e0bcb67d93ff751284ca2a7987167f4c433db51a3cf0350f85
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / tinyvdb-0.9.1-cp311-abi3-macosx_10_9_x86_64.whl
| Download URL | tinyvdb-0.9.1-cp311-abi3-macosx_10_9_x86_64.whl |
|---|---|
| Size | 822.9 kB |
| Tags | CPython 3.11 abi3 macOS 10.9+ x86-64 |
|
SHA-256 checksum How to use checksums |
ba0f0747140fb66ae214087c9e7b2099861729d046402b5ffb75b18b5ea3fa2e
|
|
BLAKE2b-256 checksum How to use checksums |
171e701055f888a9a97f36eacf635d468aea08d8e95c36b72bdea69ecc881b17
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logSecurity for tinyvdb 0.9.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 8 files in this release have been uploaded with provenance metadata.
Attestation for tinyvdb-0.9.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.