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

Installation

pip install bitbully

Usage

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.

🚀 BitBully: Getting Started with a Jupyter Notebook

Open In Colab

This notebook introduces the main building blocks of BitBully:

  • Board: represent and manipulate Connect Four positions
  • BitBully: analyze positions and choose strong moves

All examples are designed to be copy-pasteable and easy to adapt for your own experiments.

Jupyter Notebook: notebooks/getting_started.ipynb

🎮 Play a Game of Connect-4 with a simple Jupyter Notebook Widget

Open In Colab

screenshot_gui

BitBully includes an interactive Connect-4 widget for Jupyter built with ipywidgets + Matplotlib. GuiC4 renders a 6x7 board using image sprites, supports move evaluation, provides undo/redo, can trigger a computer move using the BitBully engine (optionally with an opening book database). It's intended for quick experimentation and demos inside notebooks (best with %matplotlib ipympl).

Jupyter Notebook: notebooks/game_widget.ipynb

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.74.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.74-pp311-pypy311_pp73-win_amd64.whl (481.2 kB view details)

Uploaded PyPyWindows x86-64

bitbully-0.0.74-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (357.7 kB view details)

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

bitbully-0.0.74-pp311-pypy311_pp73-macosx_11_0_arm64.whl (253.6 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

bitbully-0.0.74-pp310-pypy310_pp73-win_amd64.whl (479.8 kB view details)

Uploaded PyPyWindows x86-64

bitbully-0.0.74-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (356.3 kB view details)

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

bitbully-0.0.74-pp310-pypy310_pp73-macosx_11_0_arm64.whl (252.4 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

bitbully-0.0.74-cp314-cp314-win_amd64.whl (492.4 kB view details)

Uploaded CPython 3.14Windows x86-64

bitbully-0.0.74-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.74-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (360.4 kB view details)

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

bitbully-0.0.74-cp314-cp314-macosx_11_0_arm64.whl (254.5 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

bitbully-0.0.74-cp313-cp313-win_amd64.whl (482.7 kB view details)

Uploaded CPython 3.13Windows x86-64

bitbully-0.0.74-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.74-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (360.1 kB view details)

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

bitbully-0.0.74-cp313-cp313-macosx_11_0_arm64.whl (254.1 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

bitbully-0.0.74-cp312-cp312-win_amd64.whl (482.6 kB view details)

Uploaded CPython 3.12Windows x86-64

bitbully-0.0.74-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.74-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (360.0 kB view details)

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

bitbully-0.0.74-cp312-cp312-macosx_11_0_arm64.whl (254.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

bitbully-0.0.74-cp311-cp311-win_amd64.whl (481.7 kB view details)

Uploaded CPython 3.11Windows x86-64

bitbully-0.0.74-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.74-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (357.9 kB view details)

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

bitbully-0.0.74-cp311-cp311-macosx_11_0_arm64.whl (253.5 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

bitbully-0.0.74-cp310-cp310-win_amd64.whl (480.5 kB view details)

Uploaded CPython 3.10Windows x86-64

bitbully-0.0.74-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.74-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (356.4 kB view details)

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

bitbully-0.0.74-cp310-cp310-macosx_11_0_arm64.whl (252.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: bitbully-0.0.74.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.74.tar.gz
Algorithm Hash digest
SHA256 5a51c7f03487fd0e44502a1572879677719b02b70e3c72414b4567eee9da488f
MD5 ef401b8e7685183f13e50c113087db3d
BLAKE2b-256 aceba93e5b47e60bf40a1896653776d8e521c910a3ba8f2692fc3aab62caf05f

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74.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.74-pp311-pypy311_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-pp311-pypy311_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 b34296cbd21a1d0ba2e1131f0ab156d77199d2e154d3c4f550bf8291abd30417
MD5 f5a9c2542cf85be7c6cf2486e61cc607
BLAKE2b-256 1f52fa58e31c391a1b377d323ba2a0ee8c2540f2cf0bf1ebf742a58c6beb8ebf

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 58528df24f5a3a9722b104ec062d5d3f5792b37beceb79c104f90e4316f35462
MD5 1d208b65eab2ed2950ddda9bf91ab7aa
BLAKE2b-256 d83f498fcac62d15f15db32d69a66e603682129b32f51d3960aa38c800b7adc3

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-pp311-pypy311_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-pp311-pypy311_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c43515b3aef2865a5d03a8bd7c23e017750c7635d1431dde141c792183f91eef
MD5 1f165d16b72c0994e9fca28d31b4b077
BLAKE2b-256 d26e6d0eb2dd6f8d9c9101c0d474048c173a49c4c92314db6dc4e4352f50b96c

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-pp310-pypy310_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-pp310-pypy310_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 0af6d0d939d23d916ef2c679f790dad7ea46113c52038cc76f6de287188221a0
MD5 1311118bcd3d172965bee0e79190d7f3
BLAKE2b-256 70e33be71bd64f8be00b2d97e4b4514917cd578970f466301dbb881787755b7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4eb866e228399084d6ac3bc1d62f5f69307c3b37463cf5ee1afde3720d75c94b
MD5 54406156e1f36379f76cf44dd5f987e6
BLAKE2b-256 aaa963dd9a34781ee3fae94dd8ba4ddb7ed1e2053c0110c9ab34273daa3adeb1

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-pp310-pypy310_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-pp310-pypy310_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a816fd4844d2af627a1895a3597e4c9eeb88718a37897dea67f3e554a2286991
MD5 c7d6f0414025b06e20e059f645a52e2f
BLAKE2b-256 6eb91a7c5d0bb91acedb72a04872db9b5e56c5e0ba86b485611d0e0c6aa8267e

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.74-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 492.4 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.74-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 07a6e0940527ccc2e1656330b49e8ce1442e4628841783fe599acd7b96c6946c
MD5 ea024428e48dd1a952110ec27fdf97f3
BLAKE2b-256 d5ddb530c699b90bdad581e320ffb2c7358921b9c0d76794d2eac199980033fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp314-cp314-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 5721be3b791cad7fd8ec9a7fd80a9f126422156b7550ed3934714885ac3ce0f6
MD5 09207e72d43cf3fd01710f9b919d7fc6
BLAKE2b-256 d5e5c50f018cb4b24d0f83a17480735e78521875066edf2f3f22c409326e194f

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 cb4bae44752d9a298ea1338e3a0d903e7fe2f8cfe705cb9df1e1831a7591c67d
MD5 22db982ef768cce0e26ee0b42981e74e
BLAKE2b-256 611a835251e2595f8593cf7caf88b3ee8ea05929dcd9e5927c92451be58cacae

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cabba82482b80f19099723717c047c07c798c058956fe892e255e69d1cfc5f87
MD5 733d1f46857c860071a82bb1d1757bb5
BLAKE2b-256 6b7f8d0d0adb21be9ebf95618790c468a558cd11f372c0d6e39e01694fc230aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.74-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 482.7 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.74-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 ddcc95c31d861460547125dc3673f2d6572435293676bfd8462e2aae4f62ad28
MD5 c3aee5e206a492d54a92610bb15bed7e
BLAKE2b-256 57d87a669245c1caa4312d6a98ecc6de4ce9f5afa52eff14da69e01ec6a1da08

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 74bc870354b2ea9d10b4c2c7b42c71c88bf11faa118c57912dc6d9e49ffef803
MD5 c01903eb7152b409fd1be5713d1423be
BLAKE2b-256 ab79cb23a8ea306b7eb895db9bbaf6854a34e6d95a80c1abd57590ddaec76374

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d581b6d3d851c4f2cca9b9c877b4220d82d004abae9b5670684dac36b057346e
MD5 26a6da50939e3c9ca28281a698432302
BLAKE2b-256 466099d5eccaeca2f220d0901a91922bb8c0b7b355efbb5eab06074246a3fb81

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2ae6e4a1352a12944272bbcbc85bd4ea37e0e818125474875fe6248b2a496155
MD5 f219030df07c0f643ef25b0b4f2fb9b6
BLAKE2b-256 258d78d4fa943a46d1371f021641d4723d95b83517d3d5124ae06bc8a92185d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.74-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 482.6 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.74-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 45472fc3ba4a0c4842b7a9853f3cc9bbc5960094bf8b279fdb7ebcd16fabee62
MD5 79cbcd7644a280674169173b24a6a950
BLAKE2b-256 031fc6b87aa9f5d8739e9054fca5981ad923d5247b3285998fe04774049f7987

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 230b130915adc4c7c1174b877cab73c727e240eb31f08fa528e7fc75b1462da7
MD5 8ba064fd7b1e0b7ef43bf9899709ec9d
BLAKE2b-256 6cdf61900df8a618f0c43646ffa102c0dd790cd91532d66d90e5a7d4b7916091

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 04a33c6f6c0b097d2774ed8682030e2becb7002c55880bc89849525223ddacc3
MD5 7fa0bce9cad94d36c94b90d0e30c3fec
BLAKE2b-256 abbfa51fcf8e534147045349044d40c405cad01a8f0b899ced79faf7ccf1e26a

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 daf8729c1772f22a916cb4d82259a0b97219cf8777119eded72711c09087c4bc
MD5 70eb4086055e98dccece03dd9ac2e47f
BLAKE2b-256 1bba29f7ef443f9db4b5c76a36ce937bec33a533fbb3683d03e0167723e624ba

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.74-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 481.7 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.74-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 f23c44b153bcc00a302d408bc7bcdd0253db8bd2c2e23c3ca08bf66308c8301f
MD5 1466636022830a8baaece1fd1992a467
BLAKE2b-256 291e4821c17a09a10982c5f13c874339ee8d5c8cc8eee0f60e32b3dad001267f

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 2790db03a3bc74a7714126ed83a6db027df09b3ad40ae51e72730e33931fd05b
MD5 debe0233d6035fc7d34e52ca0b6b4399
BLAKE2b-256 28f93235cb48a40c624d45a3b44f3c4816fa873babcb05dabb209cd90fd79f43

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f3c36d009255eda98db78731332782aa0a5f44418663e8c282946d848a9a10a9
MD5 be3d27b2bcebe9487142794274107ba2
BLAKE2b-256 d4f6a98c9d22703470989be098046082d751b5afb817bcc8b4058ec8080c606d

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7f2ed73baff15a81d31bbb84d01f240fa2b0c3e7d8a3b071a19ecc306904f6af
MD5 122fe4ede539dbde424353cdf18003e1
BLAKE2b-256 f79a361e9b1fa9c0118c4265e039904bf4967c2f02544eec0368b14a7316dd05

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.74-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 480.5 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.74-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 c2af121162881703405aae233a0ba425ff91e7171d8ae6444d57468b0c049572
MD5 9ae4a38b528825f5de4eb20b6659002f
BLAKE2b-256 d2359f614ef9270ca3b08831847bfe5f3eabff125df627dedd3f938c183172cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 ee6ef850b50142d6438ae90ade5dfeb68bb8daae86b88a19cef81d75f8a665af
MD5 5c85e24e72e6599679447d4cf6ee275b
BLAKE2b-256 d13a8cda8cc06ee87961826d3a391c7a3a9d1b446c4a3039cf5608d14ced1fa9

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 665c05c750e773a869fc089e1172eb0dfdea305664e7f4a0c8d1f3f8e10ae301
MD5 e4d83d8a0872cab62d1895cc47b0fd6f
BLAKE2b-256 9cafb0b1646904bbf87ea6cb4fa43b6f0f0981816f976c08d15894d9ac17e6ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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.74-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.74-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 09b298bddd5cce70b7fa841d7f1443a7a5b141dd362cd8f7900a4a67dac69686
MD5 c72bab5f7bb9b2ce3ee64b377a974e00
BLAKE2b-256 ae7b98f212b62b66b70f9d55b6384cae0852b2230e0ddabc43876638aaa8a9b3

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.74-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