Skip to main content

Build Status Docs codecov License: Apache 2.0 PyPI Downloads Python 3.12 | 3.13 | 3.14

solvOR

Solvor all your optimization needs.

What's in the box?

Category Solvors Use Case
Linear/Integer solve_lp, solve_lp_interior, solve_milp, solve_cg, solve_bp Resource allocation, cutting stock
Constraint solve_sat, Model Sudoku, puzzles, and that one config problem that's been bugging you
Combinatorial solve_knapsack, solve_bin_pack, solve_job_shop, solve_vrptw Packing, scheduling, routing
Local Search anneal, tabu_search, lns, alns TSP, combinatorial optimization
Population evolve, differential_evolution, particle_swarm Global search, nature-inspired
Gradient gradient_descent, momentum, rmsprop, adam ML, curve fitting
Quasi-Newton bfgs, lbfgs Fast convergence, smooth functions
Derivative-Free nelder_mead, powell, bayesian_opt Black-box, expensive functions
Pathfinding bfs, dfs, dijkstra, astar, astar_grid, bellman_ford, floyd_warshall Shortest paths, graph traversal
Graph max_flow, min_cost_flow, kruskal, prim, topological_sort, strongly_connected_components, pagerank, louvain, articulation_points, bridges, kcore_decomposition Flow, MST, dependency, centrality, community detection
Assignment solve_assignment, solve_hungarian, network_simplex Matching, min-cost flow
Exact Cover solve_exact_cover N-Queens, tiling puzzles
Utilities FenwickTree, UnionFind Data structures for algorithms

Quickstart

uv add solvor
from solvor import solve_lp, solve_tsp, dijkstra, solve_hungarian

# Linear Programming
result = solve_lp(c=[1, 2], A=[[1, 1], [2, 1]], b=[4, 5])
print(result.solution)  # optimal x

# TSP with tabu search
distances = [[0, 10, 15], [10, 0, 20], [15, 20, 0]]
result = solve_tsp(distances)
print(result.solution)  # best tour found

# Shortest path
graph = {'A': [('B', 1), ('C', 4)], 'B': [('C', 2)], 'C': []}
result = dijkstra('A', 'C', lambda n: graph.get(n, []))
print(result.solution)  # ['A', 'B', 'C']

# Assignment
costs = [[10, 5], [3, 9]]
result = solve_hungarian(costs)
print(result.solution)  # [1, 0] - row 0 gets col 1, row 1 gets col 0

Solvors

Linear & Integer Programming

solve_lp

For resource allocation, blending, production planning. Finds the exact optimum for linear objectives with linear constraints.

# minimize 2x + 3y subject to x + y >= 4, x <= 3
result = solve_lp(
    c=[2, 3],
    A=[[-1, -1], [1, 0]],  # constraints as Ax <= b
    b=[-4, 3]
)

solve_milp

When some variables must be integers. Diet problems, scheduling with discrete slots, set covering.

# same as above, but x must be integer
result = solve_milp(c=[2, 3], A=[[-1, -1], [1, 0]], b=[-4, 3], integers=[0])

solve_cg

Column generation for problems with exponentially many variables. Cutting stock, bin packing, vehicle routing, crew scheduling.

# Cutting stock: minimize rolls to cut required pieces
result = solve_cg(
    demands=[97, 610, 395, 211],
    roll_width=100,
    piece_sizes=[45, 36, 31, 14],
)
print(result.objective)  # 454 rolls

solve_bp

Branch-and-price for optimal integer solutions. Combines column generation with branch-and-bound for proven optimality.

# Cutting stock with guaranteed integer optimality
result = solve_bp(
    demands=[97, 610, 395, 211],
    roll_width=100,
    piece_sizes=[45, 36, 31, 14],
)
print(result.objective)  # Integer optimal
Constraint Programming

solve_sat

For "is this configuration valid?" problems. Dependencies, exclusions, implications - anything that boils down to boolean constraints.

# (x1 OR x2) AND (NOT x1 OR x3) AND (NOT x2 OR NOT x3)
result = solve_sat([[1, 2], [-1, 3], [-2, -3]])
print(result.solution)  # {1: True, 2: False, 3: True}

Model

Constraint programming for puzzles and scheduling with "all different", arithmetic, and logical constraints. Sudoku, N-Queens, timetabling.

m = Model()
cells = [[m.int_var(1, 9, f'c{i}{j}') for j in range(9)] for i in range(9)]

# All different in each row
for row in cells:
    m.add(m.all_different(row))

result = m.solve()
Metaheuristics

anneal

Simulated annealing, sometimes you have to go downhill to find a higher peak.

result = anneal(
    initial=initial_solution,
    objective_fn=cost_function,
    neighbors=random_neighbor,
    temperature=1000,
    cooling=0.9995
)

Greedy local search with a "don't go back there" list. Simple but surprisingly effective.

result = tabu_search(
    initial=initial_solution,
    objective_fn=cost_function,
    neighbors=get_neighbors,  # returns [(move, solution), ...]
    cooldown=10
)

lns / alns

Large Neighborhood Search, destroy part of your solution and rebuild it better. ALNS learns which operators work best.

result = lns(initial, objective_fn, destroy_ops, repair_ops, max_iter=1000)
result = alns(initial, objective_fn, destroy_ops, repair_ops, max_iter=1000)  # adaptive

evolve / differential_evolution / particle_swarm

Population-based global search. Let a swarm of candidates explore for you. DE and PSO work on continuous spaces.

result = evolve(objective_fn=fitness, population=pop, crossover=cx, mutate=mut)
result = differential_evolution(objective_fn, bounds=[(0, 10)] * n, population_size=50)
result = particle_swarm(objective_fn, bounds=[(0, 10)] * n, n_particles=30)
Continuous Optimization

Gradient-Based

gradient_descent, momentum, rmsprop, adam - follow the slope. Adam adapts learning rates per parameter.

def grad_fn(x):
    return [2 * x[0], 2 * x[1]]  # gradient of x^2 + y^2

result = adam(grad_fn, x0=[5.0, 5.0])

Quasi-Newton

bfgs, lbfgs - approximate Hessian for faster convergence. L-BFGS uses limited memory.

result = bfgs(objective_fn, grad_fn, x0=[5.0, 5.0])
result = lbfgs(objective_fn, grad_fn, x0=[5.0, 5.0], memory=10)

Derivative-Free

nelder_mead, powell - no gradients needed. Good for noisy, non-smooth, or "I have no idea what this function looks like" situations.

result = nelder_mead(objective_fn, x0=[5.0, 5.0])
result = powell(objective_fn, x0=[5.0, 5.0])

bayesian_opt

When each evaluation is expensive. Builds a surrogate model to sample intelligently. Perfect for hyperparameter tuning or when your simulation takes 10 minutes per run.

result = bayesian_opt(expensive_fn, bounds=[(0, 1), (0, 1)], max_iter=30)
Pathfinding

bfs / dfs

Unweighted graph traversal. BFS finds shortest paths (fewest edges), DFS explores depth-first. Both work with any state type and neighbor function.

# Find shortest path in a grid
def neighbors(pos):
    x, y = pos
    return [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]

result = bfs(start=(0, 0), goal=(5, 5), neighbors=neighbors)
print(result.solution)  # path from start to goal

dijkstra

Weighted shortest paths. Classic algorithm for when edges have costs. Stops early when goal is found.

def neighbors(node):
    return graph[node]  # returns [(neighbor, cost), ...]

result = dijkstra(start='A', goal='Z', neighbors=neighbors)

astar / astar_grid

A* with heuristics. Faster than Dijkstra when you have a good distance estimate. astar_grid handles 2D grids with built-in heuristics.

# Grid pathfinding with obstacles
grid = [[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]]
result = astar_grid(grid, start=(0, 0), goal=(2, 3))

bellman_ford

Handles negative edge weights. Slower than Dijkstra but detects negative cycles, which is useful when costs can go negative.

result = bellman_ford(start=0, edges=[(0, 1, 5), (1, 2, -3), ...], n_nodes=4)

floyd_warshall

All-pairs shortest paths. O(n³) but gives you every shortest path at once. Worth it when you need the full picture.

result = floyd_warshall(n_nodes=4, edges=[(0, 1, 3), (1, 2, 1), ...])
# result.solution[i][j] = shortest distance from i to j
Network Flow & MST

max_flow

"How much can I push through this network?" Assigning workers to tasks, finding bottlenecks.

graph = {
    's': [('a', 10, 0), ('b', 5, 0)],
    'a': [('b', 15, 0), ('t', 10, 0)],
    'b': [('t', 10, 0)],
    't': []
}
result = max_flow(graph, 's', 't')

min_cost_flow / network_simplex

"What's the cheapest way to route X units?" Use min_cost_flow for simplicity, network_simplex for large instances.

# network_simplex for large min-cost flow
arcs = [(0, 1, 10, 2), (0, 2, 5, 3), (1, 2, 15, 1)]  # (from, to, cap, cost)
supplies = [10, 0, -10]  # positive = source, negative = sink
result = network_simplex(n_nodes=3, arcs=arcs, supplies=supplies)

kruskal / prim

Minimum spanning tree. Connect all nodes with minimum total edge weight. Kruskal sorts edges, Prim grows from a start node.

edges = [(0, 1, 4), (0, 2, 3), (1, 2, 2)]  # (u, v, weight)
result = kruskal(n_nodes=3, edges=edges)
# result.solution = [(1, 2, 2), (0, 2, 3)] - MST edges
Assignment

solve_assignment / solve_hungarian

Optimal one-to-one matching. solve_hungarian is O(n³), direct algorithm for assignment problems.

costs = [
    [10, 5, 13],
    [3, 9, 18],
    [10, 6, 12]
]
result = solve_hungarian(costs)
# result.solution[i] = column assigned to row i
# result.objective = total cost

# For maximization
result = solve_hungarian(costs, minimize=False)
Exact Cover

solve_exact_cover

For "place these pieces without overlap" problems. Sudoku, pentomino tiling, N-Queens, or any puzzle where you stare at a grid wondering why nothing fits.

# Tiling problem: cover all columns with non-overlapping rows
matrix = [
    [1, 1, 0, 0],  # row 0 covers columns 0, 1
    [0, 1, 1, 0],  # row 1 covers columns 1, 2
    [0, 0, 1, 1],  # row 2 covers columns 2, 3
    [1, 0, 0, 1],  # row 3 covers columns 0, 3
]
result = solve_exact_cover(matrix)
# result.solution = (0, 2) or (1, 3) - rows that cover all columns exactly once
Combinatorial Solvers

solve_knapsack

The classic "what fits in your bag" problem. Select items to maximize value within capacity.

values = [60, 100, 120]
weights = [10, 20, 30]
result = solve_knapsack(values, weights, capacity=50)
# result.solution = (1, 2) - indices of selected items

solve_bin_pack

Bin packing heuristics. Minimize bins needed for items.

items = [4, 8, 1, 4, 2, 1]
result = solve_bin_pack(items, bin_capacity=10)
# result.solution = (1, 0, 0, 1, 0, 0) - bin index for each item
# result.objective = 2 (number of bins)

solve_job_shop

Job shop scheduling. Minimize makespan for jobs on machines.

# jobs[i] = [(machine, duration), ...] - operations for job i
jobs = [[(0, 3), (1, 2)], [(1, 2), (0, 4)]]
result = solve_job_shop(jobs, n_machines=2)

solve_vrptw

Vehicle Routing with Time Windows. Serve customers with capacity and time constraints.

from solvor import Customer, solve_vrptw

customers = [
    Customer(1, 10, 10, demand=10, tw_start=0, tw_end=50, service_time=5),
    Customer(2, 20, 20, demand=10, tw_start=0, tw_end=50, service_time=5),
    Customer(3, 30, 30, demand=10, tw_start=0, tw_end=50, service_time=5),
]
result = solve_vrptw(customers, vehicles=2, vehicle_capacity=30)

Result Format

All solvors return a consistent Result dataclass:

Result(
    solution,     # best solution found
    objective,    # objective value
    iterations,   # solver iterations (pivots, generations, etc.)
    evaluations,  # function evaluations
    status,       # OPTIMAL, FEASIBLE, INFEASIBLE, UNBOUNDED, MAX_ITER
    error,        # error message if failed (None on success)
    solutions,    # multiple solutions when solution_limit > 1
)

When to use what?

Problem Solvor
Linear constraints, continuous solve_lp, solve_lp_interior
Linear constraints, integers solve_milp
Cutting stock, crew scheduling solve_cg, solve_bp
Boolean satisfiability solve_sat
Discrete vars, complex constraints Model
Knapsack, subset selection solve_knapsack
Bin packing solve_bin_pack
Job shop scheduling solve_job_shop
Vehicle routing solve_vrptw
Combinatorial, local search tabu_search, anneal
Combinatorial, destroy-repair lns, alns
Global search, continuous differential_evolution, particle_swarm
Global search, discrete evolve
Smooth, differentiable, fast bfgs, lbfgs
Smooth, differentiable, ML adam, rmsprop
Non-smooth, no gradients nelder_mead, powell
Expensive black-box bayesian_opt
Shortest path, unweighted bfs, dfs
Shortest path, weighted dijkstra, astar
Shortest path, negative weights bellman_ford
All-pairs shortest paths floyd_warshall
Minimum spanning tree kruskal, prim
Dependency ordering topological_sort
Circular dependencies strongly_connected_components
Node importance pagerank
Community detection louvain
Single points of failure articulation_points, bridges
Core vs periphery kcore_decomposition
Maximum flow max_flow
Min-cost flow min_cost_flow, network_simplex
Assignment, matching solve_hungarian, solve_assignment
Exact cover, tiling solve_exact_cover

Performance

Have your cake and eat it too. solvOR gives you both:

  • Readable Python - Every algorithm is implemented in clear, documented Python you can study and modify
  • Rust Performance - Optional drop-in Rust backends with 3-100x speedup for compute-heavy algorithms
from solvor import floyd_warshall

# "auto" (default) - Uses Rust if available, falls back to Python
result = floyd_warshall(n_nodes, edges)

# "python" - Force pure Python (for learning, debugging, or extending)
result = floyd_warshall(n_nodes, edges, backend="python")

Pre-built wheels include Rust extensions for Linux, macOS, and Windows: one abi3 wheel per platform that works on CPython 3.12 and newer. If Rust isn't available, solvOR falls back to Python automatically.

See the Performance docs for which algorithms have Rust backends and benchmarks.


Philosophy

  1. Readable first: every algorithm in clear Python you can actually understand
  2. Performance when needed: optional Rust backends, zero-copy where possible
  3. Consistent: same Result format, same minimize/maximize convention
  4. Practical: solves real problems (and AoC puzzles)

Documentation

Full docs at solvOR.ai: getting started, algorithm reference, cookbook with worked examples, and troubleshooting.


Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

Apache 2.0 License, free for personal and commercial use.

Background of solvOR

A little bit of history.. I learned about solvers back in 2011, working with some great minds at a startup in Paris. I started writing python myself around 2018, always as a hobby, and in 2024 I got back into solvers for an energy management system (EMS) and wrote a few tools (simplex, milp, genetic) myself mainly to improve my understanding.

Over time this toolbox got larger and larger, so I decided to publish it on GitHub so others can use it and improve it even further. Since I am learning Rust, I will eventually replace some performance critical operations with a high performance Rust implementation. But since I work on this project (and others) in my spare time, what and when is uncertain. The name solvOR is a mix of solver(s) and OR (Operations Research).

Disclaimer; I am not a professional software engineer, so there are probably some obvious improvements possible. If so let me know, or create a PR!

Metadata

Release files for solvor 0.6.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for solvor 0.6.3
File Size Uploaded
solvor-0.6.3.tar.gz 139.6 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for solvor 0.6.3
File
solvor-0.6.3-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details
solvor-0.6.3-cp312-abi3-musllinux_1_2_x86_64.whl CPython 3.12 abi3 Linux musl 1.2+ x86-64 Details
solvor-0.6.3-cp312-abi3-musllinux_1_2_aarch64.whl CPython 3.12 abi3 Linux musl 1.2+ ARM64 Details
solvor-0.6.3-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 abi3 Linux glibc 2.17+ x86-64 Details
solvor-0.6.3-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.12 abi3 Linux glibc 2.17+ ARM64 Details
solvor-0.6.3-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details
solvor-0.6.3-cp312-abi3-macosx_10_12_x86_64.whl CPython 3.12 abi3 macOS 10.12+ x86-64 Details

Total release size: 3.7 MB

Release files / solvor-0.6.3.tar.gz

Download URL solvor-0.6.3.tar.gz
Size 139.6 kB
Tags Source
SHA-256 checksum
How to use checksums
8a573e48c7c599e8937bc3fec41a36348dc75e02134b308a7795072ca29e706f
BLAKE2b-256 checksum
How to use checksums
f8ed6058d0820fa33860af78a29cb46420eebc8eae5ce2e44cbab4be0dc7db06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 6, 2026.

Transparency log

Release files / solvor-0.6.3-cp312-abi3-win_amd64.whl

Download URL solvor-0.6.3-cp312-abi3-win_amd64.whl
Size 365.1 kB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
313d7a6d7f5c3851377d0a5d7ce4441d1e35dbb6f29845f862ff4eef484dc238
BLAKE2b-256 checksum
How to use checksums
565f6e726106f382aa6854e559de4f7db72a2da5a7d05a246fe356a428dfd383
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 6, 2026.

Transparency log

Release files / solvor-0.6.3-cp312-abi3-musllinux_1_2_x86_64.whl

Download URL solvor-0.6.3-cp312-abi3-musllinux_1_2_x86_64.whl
Size 693.2 kB
Tags CPython 3.12 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
abfa593ada6d6e55d8609d6eb8760c93911248c080aab61e008b524548b91ea4
BLAKE2b-256 checksum
How to use checksums
2a78bd6ab8b6373cfa66a558df09aeaf6419876d9b416f49a34168f786efa828
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 6, 2026.

Transparency log

Release files / solvor-0.6.3-cp312-abi3-musllinux_1_2_aarch64.whl

Download URL solvor-0.6.3-cp312-abi3-musllinux_1_2_aarch64.whl
Size 653.4 kB
Tags CPython 3.12 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
1fb9731bd897088e1871e3553d2ac6c49d323ba45e202cbc9e9b9638fb9838d8
BLAKE2b-256 checksum
How to use checksums
28aa40cd2e7d43f91608fed077922da2164beec88687c4217b2a3534556352d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 6, 2026.

Transparency log

Release files / solvor-0.6.3-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL solvor-0.6.3-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 480.1 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
fb945a6067acd473d9cd2942109bbe50ad0c662f968db3d99fc01d0ebf1d6664
BLAKE2b-256 checksum
How to use checksums
5df8e0ec1726d4618164f0ff66cf103078e9e4f61b9de13e10786f7a59898872
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 6, 2026.

Transparency log

Release files / solvor-0.6.3-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL solvor-0.6.3-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 476.3 kB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
5d4ba9de2cb0a1bf269e06b67f98ecd38e27905ba8591b47417586be971f7d9e
BLAKE2b-256 checksum
How to use checksums
b03c3a4f93c978ed553e6f5a1d3e8fb8cdd9ea6cda540ede3b588405ef48b597
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 6, 2026.

Transparency log

Release files / solvor-0.6.3-cp312-abi3-macosx_11_0_arm64.whl

Download URL solvor-0.6.3-cp312-abi3-macosx_11_0_arm64.whl
Size 448.7 kB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
00623849c53aaabba10da350164915fe2e513c7a82e73c7082c9c9e4f56b5520
BLAKE2b-256 checksum
How to use checksums
aab6825484c7ef2d33d2fa493d03100edcd757321ad5ae582103b38bd1b21507
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 6, 2026.

Transparency log

Release files / solvor-0.6.3-cp312-abi3-macosx_10_12_x86_64.whl

Download URL solvor-0.6.3-cp312-abi3-macosx_10_12_x86_64.whl
Size 459.6 kB
Tags CPython 3.12 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
590b3c0099c7f184ae0ef4dc63a9cc1631788f52791b3b34d68232c8c7df2607
BLAKE2b-256 checksum
How to use checksums
6ffbfebbdeb8a0003a9b2bbe98466c23c69c4692cf8fb1dbc4b7f1670102d63e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.3 This release

8 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page