Skip to main content

bocpy is a Python extension that adds Behavior-oriented concurrency built on top of cross-interpreter data.

Project description

bocpy

BOC Logo

Behavior-Oriented Concurrency (BOC) is a new paradigm for parallel and concurrent programming which is particularly well-suited to Python. In a BOC program, data is shared such that each behavior has unique temporal ownership of the data, removing the need for locks to coordinate access. For Python programmers, this brings a lot of benefits. Behaviors are implemented as decorated functions, and from the programmer's perspective, those functions work like normal. Importantly, the programmer's task shifts from solving concurrent data access problems to organizing data flow through functions. The resulting programs are easier to understand, easier to support, easier to extend, and unlock multi-core performance due to the ability to schedule behaviors to run efficiently across multiple sub-interpreters.

BOC has been implemented in several languages, including as a foundational aspect of the research language Verona, and now has been implemented in Python.

Getting Started

You can install bocpy via PyPi:

pip install bocpy

We provide pre-compiled wheels for Python 3.10 onwards on most platforms, but if you have problems with your particular platform/version combination, please file an issue on this repository.

[!NOTE] We provide wheels for Python 3.10 and newer, but bocpy only achieves true parallelism on Python 3.12+, where each sub-interpreter has its own GIL. On 3.10 and 3.11 behaviors still run, but they are serialised by the global GIL. The library may not work on Python versions older than 3.10.

Python version support

The mainline (main) branch in the diagram is the standard CPython build:

  • 3.10 / 3.11 — wheels are published and @when works, but every sub-interpreter still shares one process-wide GIL, so behaviors execute one at a time. Use these versions for portability rather than performance.
  • 3.12+ — each sub-interpreter gets its own GIL (PEP 684), so worker behaviors run in parallel across cores. This is where bocpy delivers on its concurrency story.
  • 3.14 is the current default development and CI target; 3.15 is validated as it stabilises.

The free-threaded branch tracks the no-GIL CPython builds (informally "3.13t", "3.14t", "3.15t" — see PEP 703). bocpy runs unmodified on these interpreters today: we don't re-enable the GIL, and the cown / 2PL protocol gives the same data-race-free guarantees you get on the GIL build. The catch is overhead — on free-threaded Python, the sub-interpreter and XIData machinery is pure ceremony, since plain threads in the main interpreter would already run in parallel.

Issue #5 tracks adding an alternative direct-threading backend that detects a free-threaded interpreter at runtime and skips the sub-interpreter / transpiler / XIData path entirely, while keeping the public Cown / @when API unchanged. We're holding off on that work until the free-threaded build and the relevant CPython APIs stabilise.

Scaling with cores

The chart below shows BOC runtime throughput as the worker count grows from 1 to 8, plotted as speedup relative to a single worker. Numbers come from examples/benchmark.py — a chain-ring workload that exercises the scheduler, two-phase locking, sub-interpreter crossings and the message queue together — run on CPython 3.14 (mean of 3 repeats, 8 s each).

Up to 8 workers, BOC delivers roughly linear scaling on this microbenchmark (≈7.5× at 8 workers). Real applications carry serial costs that this benchmark deliberately strips out — see the docstring at the top of examples/benchmark.py for the load-bearing caveats. To reproduce:

python examples/benchmark.py \
    --sweep-axis workers --sweep-values 1,2,3,4,5,6,7,8 \
    --duration 8 --warmup 2 --repeats 3 \
    --output scaling.json

A behavior can be thought of as a function which depends on zero or more concurrently-owned data objects (which we call cowns). As a programmer, you indicate that you want the function to be called once all of those resources are available. For example, let's say that you had two complex and time-consuming operations, and you needed to act on the basis of both of their outcomes:

def buy_cheese():
    logger = logging.getLogger("cheese_shop")
    for name in all_known_cheeses():
        if is_available(logger, name):
            return name
    
    cleanup_shop(logger)
    return None


def order_meal(exclude: str):
    logger = logging.getLogger("greasy_spoon")
    for dish in menu():
        logger.info(dish)
        if exclude.lower() not in dish.lower():
            logger.info(f"That doesn't have much {exclude} in it")
            return dish

        vikings(logger)
        if random.random() < 0.3:
            logger.info("<bloody vikings>")

    return None


cheese = buy_cheese()
meal = order_meal(exclude="spam")

if meal is not None:
    eat(meal)
elif cheese is not None:
    eat(cheese)

if meal is not None:
    print("I really wanted some cheese...")
elif cheese is not None:
    print("Cheesy comestibles")

return_to_library()

The code above will work, but requires the purveying of cheese and the navigation of the menu for non-spam options to happen sequentially. If we wanted to do these tasks in parallel, we will end up with some version of nested waiting, which can result in deadlock. With BOC, we would write the above like this:

from bocpy import wait, when, Cown

# ...

def buy_cheese():
    cheese = Cown(None)

    @when(cheese)
    def _(cheese):
        logger = logging.getLogger("cheese_shop")
        for name in all_known_cheeses():
            if is_available(logger, name):
                cheese.value = name
                return

        cleanup_shop(logger)

    return cheese


def order_meal(exclude: str):
    order = Cown(None)

    @when(order)
    def _(order):
        logger = logging.getLogger("greasy_spoon")
        logger.info("We have...")
        for dish in menu():
            logger.info(dish)
            if exclude.lower() not in dish.lower():
                logger.info(f"That doesn't have much {exclude} in it")
                order.value = dish
                return

            vikings(logger)
            if random.random() < 0.3:
                logger.info("<bloody vikings>")

    return order


cheese = buy_cheese()
meal = order_meal(exclude="spam")


@when(cheese, meal)
def _(cheese, meal):
    if meal.value is not None:
        eat(meal.value)
    elif cheese.value is not None:
        eat(cheese.value)
    else:
        print("<stomach rumbles>")


@when(cheese, meal)
def _(cheese, meal):
    if meal.value is not None:
        print("I really wanted cheese...")
    elif cheese.value is not None:
        print("Cheesy comestibles!")

    return_to_library()


wait()

You can view the full example here

The BOC runtime ensures that this operates without deadlock, by construction.

Talking to main-thread objects

Some values can't survive an XIData round-trip — pyglet shapes, Tk widgets, open file handles, ctypes pointers into a library loaded by __main__, a GPU context. Wrap those in a PinnedCown. Behaviors whose request set contains any pinned cown run on the main thread, drained by pump() from your event loop (or implicitly by wait()).

Keep dispatch coarse — one pinned @when per frame, not per item — so the single-consumer main thread doesn't serialise your worker parallelism. The pump() call drains whatever pinned behaviors are queued and returns immediately when the queue is empty (it never blocks), so it is safe to call from a tight render-loop tick. Hosts that want a starvation warning when the queue stays non-empty can enable it explicitly with set_pump_watchdog(); with no call, the runtime stays silent.

from bocpy import Cown, PinnedCown, pump, start, when

start()
canvas = PinnedCown(MyCanvas())  # main-thread-only handle

def update(dt):
    pump()                                     # drains prior frame's write-back; returns immediately if nothing is queued
    results = [worker_compute(i) for i in range(n)]  # per-item worker @whens

    @when(*results, canvas)                    # one pinned behavior per frame
    def _writeback(*args):
        *cells, canvas = args
        for cell in cells:
            canvas.value.draw(cell.value)

See the Pinned Cowns guide for the coarse-grained dispatch pattern, event-loop integration recipes (pyglet, Tk, asyncio), and the starvation watchdog.

Examples

We provide a few examples to show different ways of using BOC in a program:

  1. bocpy-bank: Shows an example where two objects (in this case, bank accounts), interact in an atomic way.
  2. bocpy-dining-philosophers: The classic Dining Philosphers problem implemented using BOC.
  3. bocpy-fibonacci: A parallel implementation of Fibonacci calculation.
  4. bocpy-cooking-boc: The example from the BOC tutorial.
  5. bocpy-boids: An agent-based bird flocking example demonstrating the Matrix class for parallel per-cell physics on workers, with one PinnedCown-driven @when per frame batching the pyglet-visible write-back (the coarse-grained pinned-dispatch pattern). Note: you'll need to install pyglet first in order to run the bocpy-boids example.
  6. bocpy-primes and bocpy-prime-factor: parallel prime sieve and Pollard's rho factorisation, the latter coordinating early termination via the noticeboard.
  7. bocpy-calculator: a small Erlang-style calculator service driven by send/receive.
  8. bocpy-cooking-threads: the cooking example written with plain threads, for comparison with bocpy-cooking-boc.
  9. bocpy-sketches: the cheese-and-spam sketch shown above as a runnable script.

Why BOC for Python?

Python has always had data races — compound operations like x += 1 are not atomic, even under the GIL — and with the arrival of free-threaded builds (Python 3.13t+) the surface area for concurrency bugs is only growing. BOC eliminates these problems by construction: because behaviors interact with shared data exclusively through cowns, each behavior operates over its data as if it were single-threaded. There is no lock ordering to get right, no forgotten acquire()/release(), and no possibility of deadlock. This holds whether your program runs under the GIL, on per-interpreter GIL (3.12+), or on a free-threaded interpreter.

This library

Our implementation is built on top of the sub-interpreters mechanism and the Cross-Interpreter Data (XIData) API. As of Python 3.12 each sub-interpreter has its own GIL, so behaviors scheduled by bocpy run truly in parallel.

The core scheduling engine is written in C — it is not a wrapper around locks, message queues, or asyncio. Each Cown is backed by a C-level capsule that embeds an MCS-style queue of pending behaviors. When you call @when(a, b), the runtime performs two-phase locking (2PL) over the sorted cown IDs entirely in C (releasing the GIL across the lock-free link loops). Once all cowns in a behavior's request set are acquired, the behavior is dispatched directly to a worker — there is no central scheduler thread and no OS-level lock acquisition on the fast path. Releasing a cown unlinks the MCS node and hands ownership to the next waiting behavior in O(1), which is then dispatched without touching any shared queue. This gives bocpy the same deadlock-freedom-by-construction guarantee as the original Verona runtime.

For cross-behavior data sharing that does not warrant a Cown, the library also provides a small noticeboard — a global key-value store of up to 64 entries. Behaviors can notice_write, notice_update (atomic read-modify-write) and notice_delete keys without acquiring any cowns, and read a frozen snapshot via noticeboard() / notice_read(). The bocpy-prime-factor example uses it to coordinate early termination across worker behaviors.

For values that can't survive an XIData round-trip — UI handles, GPU contexts, file descriptors — the library provides PinnedCown, a cown whose value lives permanently in the main interpreter. Behaviors against a pinned cown run on the main thread, drained by pump() from your event loop or implicitly by wait(). The full surface is PinnedCown, pump, PumpResult, set_pump_watchdog, and set_wait_pump_poll; the bocpy-boids example drives a pyglet window through one pinned @when per frame. See the Pinned Cowns guide for the coarse-grained dispatch pattern, watchdog, and free-threaded support trajectory.

The library also includes lower-level Erlang-style messaging primitives (send / receive) for channel-based communication patterns; see the API documentation for details.

Waiting for completion

Call wait() after scheduling all your behaviors. It blocks the calling thread until every scheduled behavior has finished, then tears down the runtime (joins workers, closes the noticeboard). The next @when call will spin up a fresh runtime automatically.

wait()          # block indefinitely
wait(timeout=5) # raise TimeoutError if not done in 5 s

For a synchronization checkpoint that does not tear the runtime down — e.g. a parallel search that inspects a best-so-far cown between rounds and then continues — use quiesce() instead. It blocks until every in-flight behavior completes, optionally returns a per-worker stats or noticeboard snapshot, and leaves the worker pool and the noticeboard thread running so the next @when call dispatches immediately.

from bocpy import quiesce

snap = quiesce(noticeboard=True)  # dict[str, Any]
print("best so far:", snap.get("best"))
# ... schedule the next round of @when calls ...

Additional Info

BOC is built on a solid foundation of serious scholarship and engineering. For further reading, please see:

  1. When Concurrency Matters: Behaviour-Oriented Concurrency
  2. Reference implementation in C#
  3. OOPSLA23 Talk

C API stability

bocpy is implemented as a CPython C extension that links against the private cross-interpreter data API — _PyXIData_* on 3.14+, _PyCrossInterpreterData_* on 3.12 / 3.13, and on 3.13+ the internal header internal/pycore_crossinterp.h (which requires Py_BUILD_CORE). Under PEP 689 these symbols are explicitly unstable: they may change shape, semantics, or disappear entirely between CPython minor releases, and there is no PyPI / setuptools metadata field that advertises this kind of dependency. The practical consequences are:

  • Per-minor wheels. Because we do not target the limited API (Py_LIMITED_API / abi3), every wheel carries a version-specific ABI tag (cp310, cp311, …, cp315). pip will only install a wheel that matches the running interpreter's minor version. The Programming Language :: Python :: 3.x classifiers in pyproject.toml mirror this set.
  • Source builds may lag CPython. Alpha / beta / RC builds of a new CPython minor frequently rename or reshape these private symbols. When that happens, bocpy's xidata.h shim needs an update before it will compile against the new headers; until then, install on a released minor version.
  • No CPython implementation other than CPython itself. The internal cross-interpreter machinery is CPython-specific, which is why the only implementation classifier we set is Programming Language :: Python :: Implementation :: CPython. PyPy, GraalPy, and other alternatives are not supported.

The compatibility ladder lives in src/bocpy/include/bocpy/xidata.h; the Py_BUILD_CORE #define / #undef save-and-restore there is scoped narrowly to the one #include that needs it, so downstream C extensions that pull in bocpy.h do not inherit it.

Trademarks This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.

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

bocpy-0.9.0.tar.gz (401.9 kB view details)

Uploaded Source

Built Distributions

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

bocpy-0.9.0-cp314-cp314-win_amd64.whl (204.9 kB view details)

Uploaded CPython 3.14Windows x86-64

bocpy-0.9.0-cp314-cp314-win32.whl (198.0 kB view details)

Uploaded CPython 3.14Windows x86

bocpy-0.9.0-cp314-cp314-musllinux_1_2_x86_64.whl (491.6 kB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ x86-64

bocpy-0.9.0-cp314-cp314-manylinux_2_28_x86_64.whl (497.2 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ x86-64

bocpy-0.9.0-cp314-cp314-macosx_14_0_x86_64.whl (208.4 kB view details)

Uploaded CPython 3.14macOS 14.0+ x86-64

bocpy-0.9.0-cp314-cp314-macosx_11_0_arm64.whl (202.0 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

bocpy-0.9.0-cp313-cp313-win_amd64.whl (202.1 kB view details)

Uploaded CPython 3.13Windows x86-64

bocpy-0.9.0-cp313-cp313-win32.whl (195.4 kB view details)

Uploaded CPython 3.13Windows x86

bocpy-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl (490.5 kB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

bocpy-0.9.0-cp313-cp313-manylinux_2_28_x86_64.whl (496.6 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

bocpy-0.9.0-cp313-cp313-macosx_14_0_x86_64.whl (208.3 kB view details)

Uploaded CPython 3.13macOS 14.0+ x86-64

bocpy-0.9.0-cp313-cp313-macosx_11_0_arm64.whl (201.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

bocpy-0.9.0-cp312-cp312-win_amd64.whl (202.3 kB view details)

Uploaded CPython 3.12Windows x86-64

bocpy-0.9.0-cp312-cp312-win32.whl (195.6 kB view details)

Uploaded CPython 3.12Windows x86

bocpy-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl (492.2 kB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

bocpy-0.9.0-cp312-cp312-manylinux_2_28_x86_64.whl (498.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

bocpy-0.9.0-cp312-cp312-macosx_14_0_x86_64.whl (208.7 kB view details)

Uploaded CPython 3.12macOS 14.0+ x86-64

bocpy-0.9.0-cp312-cp312-macosx_11_0_arm64.whl (202.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

bocpy-0.9.0-cp311-cp311-win_amd64.whl (202.4 kB view details)

Uploaded CPython 3.11Windows x86-64

bocpy-0.9.0-cp311-cp311-win32.whl (195.5 kB view details)

Uploaded CPython 3.11Windows x86

bocpy-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl (487.1 kB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

bocpy-0.9.0-cp311-cp311-manylinux_2_28_x86_64.whl (492.4 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

bocpy-0.9.0-cp311-cp311-macosx_14_0_x86_64.whl (208.5 kB view details)

Uploaded CPython 3.11macOS 14.0+ x86-64

bocpy-0.9.0-cp311-cp311-macosx_11_0_arm64.whl (202.3 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

bocpy-0.9.0-cp310-cp310-win_amd64.whl (202.4 kB view details)

Uploaded CPython 3.10Windows x86-64

bocpy-0.9.0-cp310-cp310-win32.whl (195.4 kB view details)

Uploaded CPython 3.10Windows x86

bocpy-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl (477.8 kB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ x86-64

bocpy-0.9.0-cp310-cp310-manylinux_2_28_x86_64.whl (482.9 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64

bocpy-0.9.0-cp310-cp310-macosx_14_0_x86_64.whl (208.7 kB view details)

Uploaded CPython 3.10macOS 14.0+ x86-64

bocpy-0.9.0-cp310-cp310-macosx_11_0_arm64.whl (202.5 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file bocpy-0.9.0.tar.gz.

File metadata

  • Download URL: bocpy-0.9.0.tar.gz
  • Upload date:
  • Size: 401.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0.tar.gz
Algorithm Hash digest
SHA256 d223af1f399e502da45f4177defffa3c7b48f73c93f16f5adcb7412aa9968397
MD5 410c9155947f54a58c8defb232715132
BLAKE2b-256 e240570e62ada0a3241db62317ae7a9b12e64f54b7f292793a412be7ac6bab0e

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 204.9 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 903b07751283ebf9eaafe84a13c8270d844fd7a551f054f2195af58fbe153fc7
MD5 f8d2694d93d1c3e2ede3e3c0bb687752
BLAKE2b-256 7ec4c2f0aed325a47b054a28602d808b9f3e85e61d678cd450ab9fda96c34042

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp314-cp314-win32.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp314-cp314-win32.whl
  • Upload date:
  • Size: 198.0 kB
  • Tags: CPython 3.14, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp314-cp314-win32.whl
Algorithm Hash digest
SHA256 ff798dc89e003b2bd4da9101b7eabc3dd2a19440847b20d51393bbeff0e7f504
MD5 0f1c2f7a91890f5f4c28a671504e9e81
BLAKE2b-256 5786385687297144d70ef7b12f36b2d8d29e1637541962ffc8847e929dab3b95

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp314-cp314-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d9a4b493895c7c9028b911520b284badd2634c7abcbefe609417c079093b1722
MD5 46290dd762b06dd1ea8a6eaa2654c8fc
BLAKE2b-256 218f700dea8a31cb95a4050e52b1db97e31c19891f3a65751f78d7b1cb30df29

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp314-cp314-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp314-cp314-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 22484a6635f832e27d81098cfd59ade794e921d4dc43c3f2bbca2379fddeff79
MD5 cbf4584e65864431388319e2716f830a
BLAKE2b-256 6e9700bf6383a8127dbe2ff6759d55e429499c64b3db783a1739e174570a8da9

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp314-cp314-macosx_14_0_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp314-cp314-macosx_14_0_x86_64.whl
Algorithm Hash digest
SHA256 f78dd1294a7f6b86aeb2b4303c8566cc9aa53926d8b770f141c22fa3feadbd9a
MD5 efe603779be00efb0cdd1d2ec0c0e7e6
BLAKE2b-256 2a97874af15392a5602ab09bd79e7d9e248042ff214d639d187931afee389f3d

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a6569267e91f5181426bc7fae4478224e0209b85288acd80f395cd5a4ea48bb0
MD5 b6965b2ead91bd24b4c746e2b17656a5
BLAKE2b-256 025edb6278837bfbba54b8b8276487dc5712d93965af2528c2086192158fdfed

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 202.1 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 8bd965e033405bc55fea4819a01064af7f219c40199c60e781943827f1217c07
MD5 1d862a0eb13a9bcf6fd55ec3c49fb40c
BLAKE2b-256 0c6546f2b4078bc479f034954cbb8b119b55d36eb244ff76d3f9be67babd967a

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp313-cp313-win32.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp313-cp313-win32.whl
  • Upload date:
  • Size: 195.4 kB
  • Tags: CPython 3.13, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp313-cp313-win32.whl
Algorithm Hash digest
SHA256 63abf305938c5a4a98a418c81e65648cd4704dc8145355db023c9db8898fa4c4
MD5 ad2786a4d41bdc4b0eb8950216682606
BLAKE2b-256 1af88ff7331f2a94f015a49a7ce1b7494785d5964d5b39c25905bd281bddcccc

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 88cc36cef408a6b6550ded72e3555b332fa90f1a256d9ec88bc0396b5e5d4ce0
MD5 db6505f43c2d2c9dda10270498ff4658
BLAKE2b-256 5d6c57dbc45f6e1cd1dcee5e5ddf8e9213a9562c7632e92c351eb383e118abbe

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c0d9669467d30759d760d6249bd59080be8ed4b61e7f59764f5f182d0af27c95
MD5 9388092365995eb4b20e12c0e273e258
BLAKE2b-256 0e00d2739472e3edc4d95c3e774dd605bccb98947069cce9d6258674a8dbd553

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp313-cp313-macosx_14_0_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp313-cp313-macosx_14_0_x86_64.whl
Algorithm Hash digest
SHA256 895eaf7f8b1b9887cb064604db15ac262ed191b86ee28c42bc7a581c0a62b39e
MD5 c26960d5ae77063c1b469b4ac8ea5437
BLAKE2b-256 93795da5a3bf958aa1fbea44a95a12b6633f6e77691602f6b6ef7be0fdd00c41

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 665dcdbcf95b5ab43ffd370bd5c61f7ba67259f1476def5469e9e0ea15f6ff1a
MD5 93c13231283e84fe9dd229d33ed40383
BLAKE2b-256 c730c51ad35723d6b495deecfbc6a584089083d961dd672592231025189f59a5

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 202.3 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 6ad41c1628535f9e9df0e056524af032ce407d3ae5a81b2ffffdb09e54b5bc04
MD5 bf22988602a54c17a71dca2b65b4535f
BLAKE2b-256 9b9f594ba0c5fbece66f44e39532ecb2eb142c8c9f986cbddf6ce79d15eb9fe2

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp312-cp312-win32.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp312-cp312-win32.whl
  • Upload date:
  • Size: 195.6 kB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 8c56b001ff122df8cefe7f730f2553fc0a68726d77786c53e85b5d8184f2acba
MD5 be3797573cb7df7a204a025692b23079
BLAKE2b-256 81280756ab69913f82e1c854bf4fd4c114c60c9d096f8b3495a78e41f5ca8009

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 630863071acb9081c5fbffacb5d15fca569ccc58f0a6ca94ae3a6f30efd52004
MD5 4045ccbf366232b9f8b80e9ecd3b7d42
BLAKE2b-256 f2bcda303dc80449f698ba7c963aa8f7a0e2398d09be172a416d60c7210adf36

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5d9b019da318fc4bac20dab6573d842dadc5f8aa2ce687bf33ade57ecfee84b6
MD5 d2b9a8f3d79e31670db1856b7e480759
BLAKE2b-256 7e5866511293686850d155ca27311ae41998fec43d8abe3e2d08c22b144ea9dd

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp312-cp312-macosx_14_0_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp312-cp312-macosx_14_0_x86_64.whl
Algorithm Hash digest
SHA256 19c05bb8b664d99678fb1013a04a703e81f050619dcfc7e3e3ec788c899a861e
MD5 b164808212dbcd12fb31e4c90f8492bc
BLAKE2b-256 4c859ddf17fd5f8bdb1431facaf1f8683215e136dd8fbb0bef71c67f59cbdbcf

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4ea867da08872c3292be47cd83a02c386a79fb7719a901079b2cdb68df672704
MD5 5e3c478f6dfe677b1d5bd4fcf1242ae2
BLAKE2b-256 524014bec1c513a8ab8d7a4e76d9ce9b22ed4965e65af4b1f6b253e1799dd8e5

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 202.4 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 8ca2ed8c955d382cbb82504800c3eef5063ab8146f5ab5c7180d8c26233acd15
MD5 32bb0129de720b4ed2c7a97ba257a0bd
BLAKE2b-256 5d795300108134bd28967f89693ed961401088c82df665ed7fbab6a8d8b62aac

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp311-cp311-win32.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp311-cp311-win32.whl
  • Upload date:
  • Size: 195.5 kB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 69faf9046e6524f398fca3f9f5b2568c53d629588a500496cca0cc4789bbb329
MD5 87780bb3f2b816e0b8817d2baf0b4900
BLAKE2b-256 95f0560cbd5db4e695942d136c68cf71e801d165aa48bdffeffa9279b08b6db7

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 16fe65d32a7d2467cbbc67a62ef5bb22151272d099ab6e7fec3b970b0b0ceb8f
MD5 31c1e9166fe01feed887326e6d1ac51b
BLAKE2b-256 05acf6be2cdb45b2f905fa23060945af32fb444a4d0a273f0559ec3ec71b38ab

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0cb5e7dd67944732ae82801191b33b8de5b0d039aa461b497e175a29d1be40da
MD5 909ce38b990a539e8e42347d2dca4af9
BLAKE2b-256 7aa2c59b125ca0a5af6f2abc3eb2bf657fcacd9eec40197f5ee268f9b877a2c2

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp311-cp311-macosx_14_0_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp311-cp311-macosx_14_0_x86_64.whl
Algorithm Hash digest
SHA256 136b0439ca1fd80ce1f494844b3ddc9d3d50f3be21c5d1d9f302727d2065f1db
MD5 326c0a9684bd339ed3283af2eca5e2e7
BLAKE2b-256 fb3cb4458b8222049a229c1a4db9973c8c6ed2323a460ff2b6183121cabcdec2

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3b18024e781675abb6970bf738bcea10b4d676acbc842310f9ff9696d22124e2
MD5 018d7761a102ca5e3ed5fd592e3f133b
BLAKE2b-256 f9c019431449b02cfa5b5be3ad0b590b433b767fde5a3e46a2282dddbd34f733

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 202.4 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 6ef7ad42602420995575fa99023dabe929f1bf7b871c88539eced72905f5f12f
MD5 df578e7b05910bdc637c364e43120248
BLAKE2b-256 3b592ab5fac13eae312eb3cf62b4a62cb784640ee36ed55b957b5bdf5f9b571c

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp310-cp310-win32.whl.

File metadata

  • Download URL: bocpy-0.9.0-cp310-cp310-win32.whl
  • Upload date:
  • Size: 195.4 kB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for bocpy-0.9.0-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 8b1d5d78122cbe626de9b3c9072e5c133b1817476f4eb68eaeaa1a6b640a4ef5
MD5 7f24028e1f5b9ca804513efc02cc07fd
BLAKE2b-256 fc8e6a7cd73113eea5269515bb5623cf76f6018af6706d55b33279ce5438ed29

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 cfd903437ce6ed0168e8a2bef3266e5325da2aa5243ef05b51fd704240ee7714
MD5 8a687a07278ec3df4a1ace2c7b342abd
BLAKE2b-256 badde37abd4041222da2169104d7c41c8db7015c82e1aab415481edd33ebe7c7

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ea1be331f513ba13d36be0041787350b1ef6ab83aa9f4ab506a093d2a4c83e2e
MD5 577461392cd8c3b4be6d21cf622aa909
BLAKE2b-256 4c274dcf139ade55ca91623abf8433efa7b4c3538301ff2d320a111668b9c97a

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp310-cp310-macosx_14_0_x86_64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp310-cp310-macosx_14_0_x86_64.whl
Algorithm Hash digest
SHA256 1481e56510bd2ffdbe5e1dcf0434879643812a116997bfdfa6c8904ac5ffffa2
MD5 01812031eff02fdc79a389ce1e0a0975
BLAKE2b-256 daf081062452dd3aada74defbf463a489a5e146d75b408e7c227cab34d1cec17

See more details on using hashes here.

File details

Details for the file bocpy-0.9.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bocpy-0.9.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0f4380b2878e2f729e4b001554bee2407e15d707bf0a13ae02a65a287a53d74e
MD5 724e597cea0f77ee40eeb0f07f038424
BLAKE2b-256 d714f7c7d5ce4659595c140b53feffcc2c6a29326a0e58b205398c7c4301a19b

See more details on using hashes here.

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