Skip to main content

A fast Connect-4 Solver for Python & C++

Project description

BitBully: A fast and perfect-playing Connect-4 Agent for Python 3 & C/C++

bitbully-logo-full


GitHub Repo stars GitHub forks Python Python Python Docs pre-commit PyPI - Version PyPI - Downloads PyPI - License Coverage Status Wheels Doxygen CMake Build Buy Me a Coffee

BitBully is a high-performance Connect-4 solver built using C++ and Python bindings, leveraging advanced algorithms and optimized bitwise operations. It provides tools for solving and analyzing Connect-4 games efficiently, designed for both developers and researchers.

BitBully evaluates millions of nodes per second in pure C++ and supports constant-time opening book lookups for early-game positions.

Connect4 opening Connect4 mid-game Connect4 victory

From opening to victory: three key stages of a Connect 4 match — early game, mid-game tension, and the final winning position.

Quickstart

import bitbully as bb

agent = bb.BitBully()
board = bb.Board()

while not board.is_game_over():
    board.play(agent.best_move(board))

print(board)
print("Winner:", board.winner())

Table of Contents


Features

  • Fast Solver: Implements MTD(f) and null-window search algorithms for Connect-4.
  • Bitboard Representation: Efficiently manages board states using bitwise operations.
  • Advanced Features: Includes transposition tables, threat detection, and move prioritization.
  • Python Bindings: Exposes core functionality through the bitbully_core Python module using pybind11.
  • Cross-Platform: Build and run on Linux, Windows, and macOS.
  • Open-Source: Fully accessible codebase for learning and contribution.

Who is this for?

  • Just want to play or analyze Connect-4 in Python? → Read Quickstart + Usage (High-level Python API)

  • Interested in performance, algorithms, or C++ integration? → See Low-level C++ bindings (advanced)

  • Working on research, solvers, or databases? → See Opening Books and BoardCore

Installation

Prerequisites

  • Python: Version 3.10 or higher, PyPy 3.10 or higher

Build and Install

From PyPI (Recommended)

The easiest way to install the BitBully package is via PyPI:

pip install bitbully

This will automatically download and install the pre-built package, including the Python bindings.


Python API Docs

Please refer to the docs here: https://markusthill.github.io/BitBully/.

The docs for the opening databases can be found here: https://markusthill.github.io/bitbully-databases/


Usage

⚠️ Note bitbully_core exposes low-level C++ bindings intended for advanced users. Most users should use the high-level bitbully Python API with the classes Board and BitBully.

BitBully currently supports standard Connect-4 (7 columns × 6 rows). Generalized board sizes are not supported.

Start with a simple Widget on Colab

Open In Colab

High-level Python API (recommended)

Empty board + play moves incrementally

import bitbully as bb

board = bb.Board()
assert board.play(3)          # single move (int)
assert board.play([2, 4, 3])  # multiple moves (list)
assert board.play("001122")   # multiple moves (string)

print(board)

Initialize directly from a move sequence

import bitbully as bb

board_a = bb.Board([3, 3, 3, 1, 1])
board_b = bb.Board("33311")

assert board_a == board_b
print(board_a)

Create positions (moves, strings, arrays) and round-trip them

import bitbully as bb

# From a move list
b1 = bb.Board([3, 3, 3, 1, 1])

# From a compact move string
b2 = bb.Board("33311")

assert b1 == b2
print(b1)

# From a 2D array (row-major 6x7 or column-major 7x6 both work)
arr = b1.to_array()  # default: column-major 7x6
b3 = bb.Board(arr)

assert b1 == b3

Legal moves and remaining moves

import bitbully as bb

board = bb.Board("33333111")

print(board.legal_moves())                 # all legal columns
print(board.legal_moves(order_moves=True)) # ordered (center-first)
print("Moves left:", board.moves_left())
print("Tokens:", board.count_tokens())

Some board utilities

import bitbully as bb

board = bb.Board("332311")
print(board)

print("Can win next (any):", board.can_win_next())
print("Can win next in col 4:", board.can_win_next(4))

assert board.play(4)  # play winning move
print(board)

print("Has win:", board.has_win())
print("Game over:", board.is_game_over())
print("Winner:", board.winner())  # 1

Solver Quickstart: evaluate a position and pick a move

import bitbully as bb

agent = bb.BitBully()          # loads default opening book ("12-ply-dist")
board = bb.Board()             # empty board

print(board)

scores = agent.score_all_moves(board)
print("Move scores:", scores)

best_col = agent.best_move(board)
print("Best move:", best_col)

Play a small game loop (agent vs. itself)

import bitbully as bb

agent = bb.BitBully()
board = bb.Board()

while not board.is_game_over():
    col = agent.best_move(board, tie_break="random")
    assert board.play(col)

print(board)
print("Winner:", board.winner())  # 1, 2, or None for draw

Tie-breaking strategies for best_move

import bitbully as bb
import random

agent = bb.BitBully()
board = bb.Board("341")  # arbitrary position

print(board)

print("Center tie-break:", agent.best_move(board, tie_break="center"))
print("Leftmost tie-break:", agent.best_move(board, tie_break="leftmost"))

rng = random.Random(42) # optional own random generator
print("Random tie-break (seeded):", agent.best_move(board, tie_break="random", rng=rng))

Different Search Algorithms

import bitbully as bb

agent = bb.BitBully()
board, _ = bb.Board.random_board(n_ply=14, forbid_direct_win=True)

s1 = agent.mtdf(board)
s2 = agent.negamax(board)
s3 = agent.null_window(board)

assert s1 == s2 == s3
print("Score:", s1)

Low-level C++ bindings (advanced)

Use the BitBullyCore and BoardCore classes directly in Python:

BoardCore Examples

The low-level BoardCore API gives you full control over Connect-4 positions: you can play moves, generate random boards, mirror positions, and query win conditions or hashes.

Create and Print a Board
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()
print(board)          # Human-readable 7x6 board
print(board.movesLeft())   # 42 on an empty board
print(board.countTokens()) # 0 on an empty board

Play Moves and Check for Winning Positions
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()

# Play a small sequence of moves (columns 0–6)
for col in [3, 2, 3, 2, 3, 4, 3]:
    assert board.play(col)

print(board)

# Check if the side to move has an immediate winning move
print(board.canWin())      # False
print(board.hasWin())      # True, since the last move created 4-in-a-row

You can also check if a specific column is a winning move:

board = bbc.BoardCore()
board.setBoard([3, 3, 3, 3, 2, 2, 4, 4])

print(board.canWin())  # True
print(board.canWin(1))  # True  – playing in column 1 wins
print(board.canWin(3))  # False – no win in column 3

Set a Board from a Move List or Array
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()

# From a move sequence (recommended)
assert board.setBoard([0, 1, 2, 3, 3, 2, 1, 0])

# Convert to 7x6 array (columns × rows)
array = board.toArray()
print(len(array), len(array[0]))  # 7 x 6

# From a 7x6 array of tokens (1 = Yellow, 2 = Red)
array_board = [[0 for _ in range(6)] for _ in range(7)]
array_board[3][0] = 1  # Yellow in center column bottom row
b2 = bbc.BoardCore()
assert b2.setBoard(array_board)

Generate Random Boards
import bitbully.bitbully_core as bbc

board, moves = bbc.BoardCore.randomBoard(10, True)

print(board)   # Random, valid board
print(moves)   # List of 10 column indices
print(board.canWin())  # Usually False for random boards in this setup

Mirroring Boards and Symmetry
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()
board.setBoard([0, 1, 2])      # Left side

mirrored = board.mirror()      # Mirror around center column
print(board)
print(mirrored)

# Double-mirroring returns the original position
assert board == mirrored.mirror()

Hashing, Equality, and Copies
import bitbully.bitbully_core as bbc

b1 = bbc.BoardCore()
b2 = bbc.BoardCore()

moves = [0, 1, 2, 3]
for m in moves:
    b1.play(m)
    b2.play(m)

assert b1 == b2
assert b1.hash() == b2.hash()
assert b1.uid() == b2.uid()

# Copying a board
b3 = b1.copy()           # or bbc.BoardCore(b1)
assert b3 == b1

b3.play(4)               # Modify the copy
assert b3 != b1
assert b3.hash() != b1.hash()

These examples are based on the internal test suite and show typical ways of interacting with BoardCore programmatically.

BitBullyCore: Connect-4 Solver Examples

The BitBullyCore module provides a high-performance Connect-4 solver written in C++ and exposed to Python. You can evaluate positions, score all legal moves, or run the full MTD(f) search.


Solve a Position with MTD(f)
import bitbully.bitbully_core as bbc

# Construct a position: alternate moves into the center column
board = bbc.BoardCore()
for _ in range(6):
    board.play(3)  # Column 3

solver = bbc.BitBullyCore()
score = solver.mtdf(board, first_guess=0)

print("Best score:", score)

mtdf returns an integer score from the perspective of the side to move (positive = winning, negative = losing).


Score All Moves in a Position

scoreMoves(board) returns a list of 7 integers: the evaluated score for playing in each column (0–6). Illegal moves (full columns) are still included in the list.

import bitbully.bitbully_core as bbc

board = bbc.BoardCore()
board.setBoard([3, 4, 1, 1, 0, 2, 2, 2])

solver = bbc.BitBullyCore()
scores = solver.scoreMoves(board)

print("Move scores:", scores)
# Example output:
# [-3, -3, 1, -4, 3, -2, -2]

Using the Solver in a Loop (Move Selection)
import bitbully.bitbully_core as bbc
import time

board = bbc.BoardCore()
solver = bbc.BitBullyCore()

for move in [3, 4, 1, 1, 0, 2, 2, 2]:  # Example opening
    board.play(move)

start = time.perf_counter()
scores = solver.scoreMoves(board)
best_move = max(range(7), key=lambda c: scores[c])
print(f"Time: {round(time.perf_counter() - start, 2)} seconds!")
print("Scores:", scores)
print("Best move suggestion:", best_move)
# best move is into column 4

Further Examples using the BitBully Solver

You can initialize a board using an array with shape (7, 6) (columns first) and solve it:

from bitbully import bitbully_core

# Define a Connect-4 board as an array (7 columns x 6 rows)
# You may also define the board using a numpy array if numpy is installed
# 0 = Empty, 1 = Yellow, 2 = Red
# Here, the left column represents the bottom row of the board
board_array = [
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [1, 2, 1, 2, 1, 0],
    [0, 0, 0, 0, 0, 0],
    [2, 1, 2, 0, 0, 0],
    [0, 0, 0, 0, 0, 0]
]

# Convert the array to the BoardCore board
board = bitbully_core.BoardCore()
assert board.setBoard(board_array), "Invalid board!"

print(board)

# Solve the position
solver = bitbully_core.BitBullyCore()
score = solver.mtdf(board, first_guess=0)
print(f"Best score for the current board: {score}") # expected score: 1

Run the Bitbully solver with an opening book (here: 12-ply opening book with winning distances):

from bitbully import bitbully_core as bbc
import bitbully_databases as bbd
import importlib.resources

db_path = bbd.BitBullyDatabases.get_database_path("12-ply-dist")
bitbully = bbc.BitBullyCore(db_path)
b = bbc.BoardCore()  # Empty board
bitbully.scoreMoves(b)  # expected result: [-2, -1, 0, 1, 0, -1, -2]

Further Usage Examples for BitBully Core

Create all Positions with (up to) n tokens starting from Board b:

from bitbully import bitbully_core as bbc

b = bbc.BoardCore()  # empty board
board_list_3ply = b.allPositions(3, True)  # All positions with exactly 3 tokens
len(board_list_3ply)  # should be 238 according to https://oeis.org/A212693

Opening Book Examples

BitBully Databases provide fast lookup tables (opening books) for Connect-4, allowing you to query evaluated positions, check if a board is known, and retrieve win/loss/distance values.

Load an Opening Book
import bitbully_databases as bbd
import bitbully.bitbully_core as bbc

# Load the 8-ply opening book (no distances)
db_path = bbd.BitBullyDatabases.get_database_path("8-ply")
book = bbc.OpeningBookCore(db_path, is_8ply=True, with_distances=False)

print(book.getBookSize())  # e.g., 34515
print(book.getNPly())      # -> 8

Accessing Entries

Each entry consists of (key, value) where:

  • key is the Huffman-encoded board state
  • value is the evaluation (win/loss/draw or distance)
k, v = book.getEntry(0)
print(k, v)

Evaluating a Board Position
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()
board.setBoard([2, 3, 3, 3, 3, 3, 5, 5])  # Sequence of column moves

value = book.getBoardValue(board)
print("Evaluation:", value)

Check Whether a Position Is in the Opening Book

The books only contain one variant for mirror-symmetric positions:

board = bbc.BoardCore()
board.setBoard([1, 3, 4, 3, 4, 4, 3, 3])

print(book.isInBook(board))              # e.g., False
print(book.isInBook(board.mirror()))     # e.g., True, checks symmetric position

Advanced Build and Install

Prerequisites

  • Python: Version 3.10 or higher
  • CMake: Version 3.15 or higher
  • C++ Compiler: A compiler supporting C++-17 (e.g., GCC, Clang, MSVC)
  • Python Development Headers: Required for building the Python bindings

From Source

  1. Clone the repository:

    git clone https://github.com/MarkusThill/BitBully.git
    cd BitBully
    git submodule update --init --recursive # – Initialize and update submodules.
    
  2. Build and install the Python package:

    pip install .
    

Building Static Library with CMake

  1. Create a build directory and configure the project:

    mkdir build && cd build
    cmake .. -DCMAKE_BUILD_TYPE=Release
    
  2. Build the a static library:

    cmake --build . --target cppBitBully
    

Contributing & Development

Whether you're fixing a bug, optimizing performance, or extending BitBully with new features, contributions are highly appreciated. The full development guide provides everything you need to work on the project efficiently:

📘 Complete Development Documentation https://markusthill.github.io/BitBully/develop/

It covers all essential workflows, including:

  • Repository setup: cloning, submodules, virtual environments
  • Development environment: installing dev dependencies, using editable mode
  • Code quality tools: ruff, mypy/pyrefly, clang-format, pre-commit, commitizen
  • Building the project: local wheels, CMake, cibuildwheel, sdist
  • Testing: running pytest, filtering tests, coverage, CI integration
  • Release workflow: semantic versioning, version bumping, tagging, PyPI/TestPyPI publishing
  • Debugging & tooling: GDB, Doxygen, mkdocs, stub generation for pybind11
  • Platform notes: Debian/Linux setup, gcov matching, MSVC quirks
  • Cheatsheets: Git, submodules, CMake, Docker, Ruby/Jekyll, npm, environment management

If you're contributing code, please:

  1. Follow the coding standards and formatting tools (ruff, mypy, clang-format).
  2. Install and run pre-commit hooks before committing.
  3. Write or update tests for all behavioral changes.
  4. Use Commitizen for semantic commit messages and versioning.
  5. Open an issue or discussion for major changes.

Pull requests are welcome — thank you for helping improve BitBully! 🚀


License

This project is licensed under the AGPL-3.0 license.


Contact

If you have any questions or feedback, feel free to reach out:


Further Ressources

Acknowledgments

Many of the concepts and techniques used in this project are inspired by the outstanding Connect-4 solvers developed by Pascal Pons and John Tromp. Their work has been invaluable in shaping this effort:


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bitbully-0.0.72.tar.gz (8.1 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

bitbully-0.0.72-pp311-pypy311_pp73-win_amd64.whl (475.0 kB view details)

Uploaded PyPyWindows x86-64

bitbully-0.0.72-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (351.2 kB view details)

Uploaded PyPymanylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.72-pp311-pypy311_pp73-macosx_11_0_arm64.whl (247.3 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

bitbully-0.0.72-pp310-pypy310_pp73-win_amd64.whl (473.5 kB view details)

Uploaded PyPyWindows x86-64

bitbully-0.0.72-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (349.8 kB view details)

Uploaded PyPymanylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.72-pp310-pypy310_pp73-macosx_11_0_arm64.whl (246.1 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

bitbully-0.0.72-cp314-cp314-win_amd64.whl (486.1 kB view details)

Uploaded CPython 3.14Windows x86-64

bitbully-0.0.72-cp314-cp314-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ x86-64

bitbully-0.0.72-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (353.8 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.72-cp314-cp314-macosx_11_0_arm64.whl (248.2 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

bitbully-0.0.72-cp313-cp313-win_amd64.whl (476.4 kB view details)

Uploaded CPython 3.13Windows x86-64

bitbully-0.0.72-cp313-cp313-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

bitbully-0.0.72-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (353.5 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.72-cp313-cp313-macosx_11_0_arm64.whl (247.7 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

bitbully-0.0.72-cp312-cp312-win_amd64.whl (476.4 kB view details)

Uploaded CPython 3.12Windows x86-64

bitbully-0.0.72-cp312-cp312-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

bitbully-0.0.72-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (353.8 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.72-cp312-cp312-macosx_11_0_arm64.whl (247.7 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

bitbully-0.0.72-cp311-cp311-win_amd64.whl (475.5 kB view details)

Uploaded CPython 3.11Windows x86-64

bitbully-0.0.72-cp311-cp311-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

bitbully-0.0.72-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (351.3 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.72-cp311-cp311-macosx_11_0_arm64.whl (247.1 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

bitbully-0.0.72-cp310-cp310-win_amd64.whl (474.3 kB view details)

Uploaded CPython 3.10Windows x86-64

bitbully-0.0.72-cp310-cp310-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ x86-64

bitbully-0.0.72-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (349.9 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.72-cp310-cp310-macosx_11_0_arm64.whl (245.9 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file bitbully-0.0.72.tar.gz.

File metadata

  • Download URL: bitbully-0.0.72.tar.gz
  • Upload date:
  • Size: 8.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.72.tar.gz
Algorithm Hash digest
SHA256 cdeed3eadb22ac738b6e00bd23afbd18d45a48464467ede5be1ed408532136dc
MD5 fbf4dda6ab4b6e026ae1b98467bdec01
BLAKE2b-256 1af53c60bc928bfe31540c310b879585711823e2b7e8514a2940b3d9d57726b1

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72.tar.gz:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-pp311-pypy311_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-pp311-pypy311_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 658d23ae57359b0266988147da9298f73b54b81fd45c10d910da733b60b41547
MD5 9e5f2cc2dfa73accbd72e03faa091a70
BLAKE2b-256 ebf6c4fbb6eb888ec265b20c64f055adaedc407cf95227fdcef38e54303d2539

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-pp311-pypy311_pp73-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b565bb40f89ae481b9527ad01500154a66be6a68df250e5855a500d0984f897c
MD5 dcbf13845b3e108d3d0281012f14c109
BLAKE2b-256 bc4e1d61ea6cb1fa0822a67c3ce6c6750a27917c2df1d8a24a8243eb78033bbe

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-pp311-pypy311_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-pp311-pypy311_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 95f4dbc74374c60fe16a7609f2453c1b6cb16c6e1ee9cee4fbb227b090c245ab
MD5 ecab81b93e1447f4ed2266ec1e16063c
BLAKE2b-256 414879a1be2a576adc09b9d97f74d3ff4bca4a7a3d96db6a4e2db30cdd95aa2a

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-pp311-pypy311_pp73-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-pp310-pypy310_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-pp310-pypy310_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 1f049451106ac98765e88a399ad6d008fa21dc92f0a7cc651c600098a998d187
MD5 bd6e7b26ff0e24d0fb3c04a91c05722b
BLAKE2b-256 dbeeb3433a34b7731fb67920b3a48bdd962a14fcddc75360c480667545de5aa0

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-pp310-pypy310_pp73-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1b7ea9a43a0912e4c4ee1cc0fdeae697da2eac76c84d7ae7d01e829a1c8c6da4
MD5 6d7c136c0e7ad0cc97b8938e5b0de6d7
BLAKE2b-256 1e33c84a703ddffb3d3f228c050af90259fc199b88fe188eb54c5f900c9c236f

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-pp310-pypy310_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-pp310-pypy310_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 44984a00a09415a7adc9ed41dbeb54b0e4470c956de0d595b3d3c00b0591e199
MD5 532398858deefd0970ae5fc8a33efa1e
BLAKE2b-256 adec5216b4a8a4b91ae729606203f2680ca5034e00f4126e1f3e90b9a3ff0420

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-pp310-pypy310_pp73-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.72-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 486.1 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.72-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 a6e3a7a6f13b7bdffa223f392bad2df549183093df9aad3e47fc19d304b37cd0
MD5 5fd64c1cdbb1514bac68dcdc9105138e
BLAKE2b-256 11e70324195f27ea88cbfea71e7184f418be8a243937fa5339ac1073e251aba2

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp314-cp314-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp314-cp314-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d572f1cbdb706edc482f28ddc9869cfdcf2a029c1b6bb1f10a179a0729cabf6b
MD5 6e8e154788ac75674c2742967adbb6a4
BLAKE2b-256 4aef30ec92474686e4b115d9b44733ffbcb1f2218d4ae805e768beb4c60b9149

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp314-cp314-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7b013ff8de01e6f353b0f9672df2029969099b96687854b6e3c994b0ed0a107c
MD5 7689c8a69fd9f5ab5b69319d426f4298
BLAKE2b-256 cff450c044c0ca677b76a5e4faefae569c346ae578512cbb17efac02f705a6df

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 da05c6dc254e62452310f5915f275e89665e0e312446f8467dfa95784a2c03d2
MD5 c4fe68ec93cd29a5400a3c36d95ebff4
BLAKE2b-256 ee3a3f137f7c562cbccce914a1a0a828517ee877dca223dafa17b12c5b028eb7

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.72-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 476.4 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.72-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 6d59a6726a377d857de9350277577f15a041192f775f328fdda3cd98424c2396
MD5 6845853d70cedfa2699e990325a2c47c
BLAKE2b-256 31b3b4aa81bb13652aa052c66156f7365c8c5ff6892a1e00c8b1de4e2bba5a50

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp313-cp313-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 5c52285d4172caa1aff87f32cee3af359b82329bd61213b57244bc09cf51dd60
MD5 ae81b3075c64c2bf960ae91f0e6f4ba4
BLAKE2b-256 070fea4c9e1a6eec2c1a424e99ba7551e1f82096e8a793255a0a8158a1a3a9cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp313-cp313-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f9d37b7a5ad27a7bfa2d89d002334c18aa645f6fb90da9134e85ef04289d6195
MD5 29393623f87418ab0768480515c8b747
BLAKE2b-256 dfef275649a7d56fa673a249ba6b1d8367d426878c95af188aef585a90576017

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3bff4b1d698bc2ba0e8b64e56a34dd91d26986232d81568b5e569876525e936f
MD5 b5284e5f63ebceb40b046efeba2cde0c
BLAKE2b-256 4c6753058f62c219209eabc849a160479cee3fc223d0a81da986615e93c1f60a

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.72-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 476.4 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.72-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 5d2c89cb8b78d6dff60f2a3d456b7cc9ab0b95e57cfe292c60b430b3b1300e12
MD5 296aa8ed07e667ff7a2a238933434217
BLAKE2b-256 71facb55f0d9448745e30b6a93a7aef883b8920f5d347ad7a88e1a6e6945e80d

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp312-cp312-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 81bb0d40e93028a845eb2fd3cac824f3b1fb430c55e16248806c4e184fe792b5
MD5 7d114a19e50b52c37d862af771955b35
BLAKE2b-256 e881c51fcb0f8a98198f52378b9ddde63638b71be86c2e373a7a710a840bbb6f

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp312-cp312-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a6aa903ee6c5884b64bac940d559788b128bb1c6c48b196242f8dab33b1a7177
MD5 e1b70088b21afc50473615bba710da9a
BLAKE2b-256 8bd7475806d3ac39f371b274477fcd7a7253ee7c78cc6e275223cb3249b26dfc

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5da475f0d839343a809efb6ba6b5d39b63a732c18c0050dbbe2a74b1d272e1a9
MD5 a1038da08d79a012d688a7587f2d47d6
BLAKE2b-256 e97bd83f5486f38549fb374ea574c05c8c7bb256d227672d3f0a628a14d1fdf4

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.72-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 475.5 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.72-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 54a0d874bd0dd21d21933c5649b72426e12382b91b5afde62b327cbddc0b9e07
MD5 17fa5d7bca964d5a185b352dd0ecd9f0
BLAKE2b-256 c11faf718e7a717480a47d8cc51fc6d8259a4084a8cec2b47ad7fe890022a49c

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp311-cp311-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 3e2621ad22a067ae1793ea1765024a03359c22b470eee95d4b44560fe5cb1458
MD5 f179b1af2925910460f85e54039b43ef
BLAKE2b-256 41c4ca45b777ce08ada63bdb093ee4bab6249c7ef6ef7c5b896316ed446e8408

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp311-cp311-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4a4d42e642a452cfcdc3183e199dd22f04e49a37c0bb3472e15d81e1e65b3111
MD5 a3fc08e425145264302b0dfa32c0d79c
BLAKE2b-256 5486a6998717c6a9cd888da71c4e9a4875e1fc83b66e1f0d9b2704084f2dbce2

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 41b9965b35b0d40e714c9a585645d030efb2674db56c4a17c04c776c606ed067
MD5 1a6235be57178055517c94050c224055
BLAKE2b-256 f84c1d4c65c0b9ae1399abdb8f1a3490a654aa4af5a2607182306be93d84ab2d

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.72-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 474.3 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.72-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 35df59957b75543dc19924470231c57679418ddb6ebdc50f01280da2dff0d32e
MD5 c8449ba156183e3343aa4b6969d2c585
BLAKE2b-256 ccd427f2c98ff617247c02fac3e35353bb33f00b6638d6bab1d0255d61c9bac4

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp310-cp310-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1ff749765bdb4660de288be2ff59ac2a3c8e363990ccf5ab708b052eddb6893a
MD5 16a57cd43ef732891df8d42efb1ccca3
BLAKE2b-256 b2f709c5f14e51bb90fca8976c579d4463b409154acd21b2f26a29bda84922fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp310-cp310-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 eb5396eb482209024f4393b2bdf4d3483c3a182420232ba53ff4b6c52e7dc13d
MD5 52c092ffb8be71b1558e6a4d0d0958ff
BLAKE2b-256 1e27ac836fd70171def1c690637983001e6e741544117771ef60cdbb6381517b

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.72-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.72-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 19a71d1cc831278838190a34ed47f4c6dd660f61c7319dfb1f3e4fde9d6d37c0
MD5 a3285756ccf92836c46594c58dc6efc8
BLAKE2b-256 4cf29cd79c88c3e0e8bc4f515ddc108bb98a38d7d932974be59507d77aa63860

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.72-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page