Skip to main content

C-Two is a resource-RPC framework that enables resource-oriented classes to be remotely invoked across different processes or machines.

Project description

C-Two

A resource-oriented RPC framework for Python — turn stateful classes into location-transparent distributed resources.

PyPI Downloads Python Free-threading CI License

中文版


Basic Idea

  • Resources, not services — C-Two doesn't expose RPC endpoints. It makes Python classes remotely accessible while preserving their stateful, object-oriented nature.

  • Zero-copy from process to data — Same-process calls skip serialization entirely. Cross-process IPC can hold shared-memory buffers alive, letting you read columnar data (NumPy, Arrow, …) directly from SHM — no deserialization, no copies.

  • Built for scientific Python — Native support for Apache Arrow, NumPy arrays, and large payloads (chunked streaming for data beyond 256 MB). Designed for computational workloads, not microservices.

  • Rust-powered transport — The IPC layer uses a Rust buddy allocator for shared memory and a Rust HTTP relay for high-throughput networking.


Performance

End-to-end cross-process IPC benchmark — same NumPy payload (row_id u32 + x,y,z f64), same machine, same aggregation. Three transport modes compared:

Rows C-Two hold (ms) Ray (ms) C-Two pickle (ms) Hold vs Ray
1 K 0.07 6.1 0.19 86×
10 K 0.09 7.1 0.82 79×
100 K 0.38 9.8 8.7 26×
1 M 3.7 58 150 15×
3 M 9.7 129 598 13×
  • C-Two hold — SHM zero-copy via np.frombuffer; no serialization on read
  • Ray — object store with zero-copy numpy support (Ray 2.55)
  • C-Two pickle — standard pickle over SHM; included to show serialization cost

Apple M1 Max · Python 3.13 · NumPy 2.4 · See benchmarks/unified_numpy_benchmark.py for full methodology.


Quick Start

pip install c-two

Define a resource contract and its implementation

import c_two as cc

# CRM contract — declares which methods are remotely accessible
@cc.crm(namespace='demo.counter', version='0.1.0')
class Counter:
    def increment(self, amount: int) -> int: ...

    @cc.read
    def value(self) -> int: ...

    def reset(self) -> int: ...


# Resource — a plain Python class implementing the contract
class CounterImpl:
    def __init__(self, initial: int = 0):
        self._value = initial

    def increment(self, amount: int) -> int:
        self._value += amount
        return self._value

    def value(self) -> int:
        return self._value

    def reset(self) -> int:
        old = self._value
        self._value = 0
        return old

Use it locally (zero serialization)

cc.register(Counter, CounterImpl(initial=100), name='counter')
counter = cc.connect(Counter, name='counter')

counter.increment(10)    # → 110
counter.value()          # → 110
counter.reset()          # → 110 (returns old value)
counter.value()          # → 0

cc.close(counter)

Or remotely — same API, different address

# Server process
cc.set_address('ipc:///tmp/my_server')
cc.register(Counter, CounterImpl(), name='counter')

# Client process (separate terminal)
counter = cc.connect(Counter, name='counter', address='ipc:///tmp/my_server')
counter.increment(5)     # works identically
cc.close(counter)

See examples/ for complete runnable demos.


Core Concepts

CRM — Contract

A CRM (Core Resource Model) declares which methods a remote resource exposes. It's decorated with @cc.crm(), and method bodies are ... (pure interface — no implementation).

@cc.crm(namespace='demo.greeter', version='0.1.0')
class Greeter:
    @cc.read                              # concurrent reads allowed
    def greet(self, name: str) -> str: ...

    @cc.read
    def language(self) -> str: ...

Methods can be annotated with @cc.read (concurrent access allowed) or left as default write (exclusive access).

Resource — Runtime Instance

A resource is a plain Python class that implements a CRM contract. It holds state and domain logic. It is not decorated — the framework discovers its methods through the CRM contract it was registered under. Name the class by what it is (GreeterImpl, PostgresGreeter, MultilingualGreeter), not the interface.

class GreeterImpl:
    def __init__(self, lang: str = 'en'):
        self._lang = lang
        self._templates = {'en': 'Hello, {}!', 'zh': '你好, {}!'}

    def greet(self, name: str) -> str:
        return self._templates.get(self._lang, 'Hi, {}!').format(name)

    def language(self) -> str:
        return self._lang

Client — Consumer

Anything that calls cc.connect(...) is a client (or consumer / application code). The returned proxy is location-transparent — it works the same whether the resource lives in the same process or on a remote machine.

greeter = cc.connect(Greeter, name='greeter')
greeter.greet('World')     # → 'Hello, World!'
cc.close(greeter)

# Or with context manager:
with cc.connect(Greeter, name='greeter') as greeter:
    greeter.greet('World')

Server — Resource Host

A server is any process that calls cc.register(...) to host one or more resources, then usually cc.serve() to block on the request loop. One server process can host many resources (each under a unique name), and will auto-bind an IPC endpoint the first time a resource is registered.

import c_two as cc

cc.set_address('ipc://my_server')              # optional — default is auto UUID path
cc.register(Greeter, GreeterImpl(), name='greeter')
cc.register(Counter, CounterImpl(), name='counter')
cc.serve()                                     # blocks; Ctrl-C triggers graceful shutdown
  • Address (ipc://...) is the local transport endpoint. Clients in the same process skip it entirely (zero serialization); clients in a different process on the same host connect to this address directly.
  • cc.serve() is optional — if your host process has its own event loop (web server, GUI, simulation), you can register resources and let them serve in the background while your main loop runs.
  • A process can be both a server and a client at the same time (register some resources, connect to others).

Relay — Distributed Discovery

An HTTP relay (c3 relay) is a lightweight broker that lets clients reach servers by name, across machines. Servers announce their IPC address to the relay when they register; clients ask the relay and get routed transparently.

# Start a relay anywhere reachable on your network
c3 relay --bind 0.0.0.0:8080
# Server side — announce resources to the relay
cc.set_relay('http://relay-host:8080')
cc.register(MeshStore, MeshStoreImpl(), name='mesh')
cc.serve()

# Client side — resolve by name, no address needed
cc.set_relay('http://relay-host:8080')
mesh = cc.connect(MeshStore, name='mesh')

Multiple relays can form a mesh cluster via gossip — any relay can resolve any resource registered anywhere in the mesh. See the Relay Mesh example below.

When do I need a relay? Only for cross-machine or name-based discovery. Same-process and same-host (IPC) usage work without any relay.

@transferable — Custom Serialization

For custom data types that need to cross the wire, use @cc.transferable. Without it, pickle is used as fallback.

A transferable class defines up to three static methods (written without @staticmethod — the framework adds it automatically):

Method Required Purpose
serialize(data) → bytes ✅ Yes Encode data for wire transfer (outbound)
deserialize(raw) → T ✅ Yes Decode wire bytes into an owned Python object (inbound)
from_buffer(buf) → T ❌ Optional Build a zero-copy view over the raw buffer (inbound, hold mode)
import numpy as np

@cc.transferable
class Matrix:
    rows: int
    cols: int
    data: np.ndarray

    def serialize(mat: 'Matrix') -> bytes:
        header = struct.pack('>II', mat.rows, mat.cols)
        return header + mat.data.tobytes()

    def deserialize(raw: bytes) -> 'Matrix':
        rows, cols = struct.unpack_from('>II', raw)
        arr = np.frombuffer(raw, dtype=np.float64, offset=8).reshape(rows, cols)
        return Matrix(rows=rows, cols=cols, data=arr.copy())  # owned copy

    def from_buffer(buf: memoryview) -> 'Matrix':
        header = bytes(buf[:8])
        rows, cols = struct.unpack('>II', header)
        arr = np.frombuffer(buf[8:], dtype=np.float64).reshape(rows, cols)
        return Matrix(rows=rows, cols=cols, data=arr)  # zero-copy view into SHM

When from_buffer is present, the server automatically uses hold mode — the SHM buffer stays alive so from_buffer can return a zero-copy view. Without from_buffer, the server uses view mode — the buffer is released immediately after deserialize.

@cc.transfer — Per-Method Control

Use @cc.transfer() on CRM contract methods to explicitly specify which transferable type handles serialization, or to override the buffer mode:

@cc.crm(namespace='demo.compute', version='0.1.0')
class Compute:
    @cc.transfer(input=Matrix, output=Matrix, buffer='hold')
    def transform(self, mat: Matrix) -> Matrix: ...

    @cc.transfer(input=Matrix, buffer='view')  # force copy even if from_buffer exists
    def ingest(self, mat: Matrix) -> None: ...

Without @cc.transfer, the framework automatically matches registered @transferable types by function signature and resolves the buffer mode from the input type's capabilities.

cc.hold() — Client-Side Zero-Copy

On the client side, cc.hold() requests that the response SHM buffer remain alive, enabling zero-copy reads of the result. The returned HeldResult wraps the value and provides a three-layer safety net for SHM lifecycle:

  1. Explicit .release() — preferred for complex workflows holding multiple buffers
  2. Context manager (with) — recommended for single-buffer scopes
  3. __del__ fallback — last resort, emits ResourceWarning if you forget to release
grid = cc.connect(Compute, name='compute', address='ipc://server')

# Normal call — buffer released immediately after deserialize
result = grid.transform(matrix)

# Option 1: Context manager — clean for single holds
with cc.hold(grid.transform)(matrix) as held:
    data = held.value          # zero-copy NumPy array backed by SHM
    process(data)              # read directly from shared memory
# SHM buffer released on context exit

# Option 2: Explicit release — better for multiple concurrent holds
a = cc.hold(grid.transform)(matrix_a)
b = cc.hold(grid.transform)(matrix_b)
try:
    combined = np.concatenate([a.value.data, b.value.data])
    process(combined)
finally:
    a.release()
    b.release()

When to use hold mode: Large array/columnar data where deserialization dominates cost. For small payloads (< 1 MB), the overhead of tracking SHM lifecycle exceeds the copy cost.


Examples

Single Process — Thread Preference

When cc.connect() targets a CRM registered in the same process, the proxy calls methods directly with zero serialization overhead.

import c_two as cc

cc.register(Greeter, Greeter(lang='en'), name='greeter')
cc.register(Counter, Counter(initial=100), name='counter')

greeter = cc.connect(Greeter, name='greeter')
counter = cc.connect(Counter, name='counter')

print(greeter.greet('World'))    # → Hello, World!
print(counter.value())           # → 100
counter.increment(10)

cc.close(greeter)
cc.close(counter)
cc.shutdown()

Best for: local prototyping, testing, single-machine computation.

Multi-Process IPC — with Custom Transferable

Separate server and client processes communicating over Unix domain sockets with shared memory.

Shared types (types.py):

import c_two as cc
import numpy as np, struct

@cc.transferable
class Mesh:
    n_vertices: int
    positions: np.ndarray   # (N, 3) float64

    def serialize(mesh: 'Mesh') -> bytes:
        header = struct.pack('>I', mesh.n_vertices)
        return header + mesh.positions.tobytes()

    def deserialize(raw: bytes) -> 'Mesh':
        (n,) = struct.unpack_from('>I', raw)
        arr = np.frombuffer(raw, dtype=np.float64, offset=4).reshape(n, 3).copy()
        return Mesh(n_vertices=n, positions=arr)

    def from_buffer(buf: memoryview) -> 'Mesh':
        header = bytes(buf[:4])
        (n,) = struct.unpack('>I', header)
        arr = np.frombuffer(buf[4:], dtype=np.float64).reshape(n, 3)
        return Mesh(n_vertices=n, positions=arr)  # zero-copy view

@cc.crm(namespace='demo.mesh', version='0.1.0')
class MeshStore:
    @cc.read
    def get_mesh(self) -> Mesh: ...

    def update_positions(self, mesh: Mesh) -> int: ...

    @cc.on_shutdown
    def cleanup(self) -> None: ...

Server (server.py):

import c_two as cc
from types import MeshStore, Mesh

class MeshStore:
    def __init__(self):
        self._mesh = Mesh(n_vertices=0, positions=np.empty((0, 3)))

    def get_mesh(self) -> Mesh:
        return self._mesh

    def update_positions(self, mesh: Mesh) -> int:
        self._mesh = mesh
        return mesh.n_vertices

    def cleanup(self):
        print('MeshStore shutting down')

cc.set_address('ipc://mesh_server')
cc.register(MeshStore, MeshStore(), name='mesh')
cc.serve()  # blocks until interrupted

Client (client.py):

import c_two as cc
from types import MeshStore, Mesh
import numpy as np

mesh_store = cc.connect(MeshStore, name='mesh', address='ipc://mesh_server')

# Upload data
big_mesh = Mesh(n_vertices=1_000_000,
                positions=np.random.randn(1_000_000, 3))
mesh_store.update_positions(big_mesh)

# Read with hold — zero-copy SHM access
with cc.hold(mesh_store.get_mesh)() as held:
    positions = held.value.positions  # np.ndarray backed by SHM, no copy
    centroid = positions.mean(axis=0)
    print(f'Centroid: {centroid}')
# SHM released here

cc.close(mesh_store)

Best for: multi-process on same host, worker isolation, high-throughput local IPC.

Cross-Machine — HTTP Relay

An HTTP relay bridges network requests to CRM processes running on IPC. CRM processes register with the relay, and clients discover resources by name.

CRM Server (resource.py):

import c_two as cc

cc.set_relay('http://relay-host:8080')
cc.set_address('ipc://mesh_server')
cc.register(MeshStore, MeshStore(), name='mesh')
cc.serve()  # blocks until Ctrl-C

Relay — start via the c3 CLI:

# Bind address from CLI flag, env var C2_RELAY_BIND, or .env file
c3 relay --bind 0.0.0.0:8080

Client (client.py):

import c_two as cc

cc.set_relay('http://relay-host:8080')
mesh = cc.connect(MeshStore, name='mesh')  # relay resolves the name
mesh.get_mesh()
cc.close(mesh)

Best for: network-accessible services, web integration, cross-machine deployment.

Relay Mesh — Multi-Relay Clusters

Multiple relays form a mesh network with gossip-based route propagation. CRMs register with their local relay; clients discover resources across the entire cluster.

# Start relay A (seeds point to peer relays for auto-join)
c3 relay --bind 0.0.0.0:8080 --relay-id relay-a \
    --advertise-url http://relay-a:8080 --seeds http://relay-b:8080

# Start relay B
c3 relay --bind 0.0.0.0:8080 --relay-id relay-b \
    --advertise-url http://relay-b:8080 --seeds http://relay-a:8080

CRM processes register with their local relay; the mesh propagates routes automatically. Clients can connect through any relay in the mesh.

Best for: multi-node clusters, high availability, geographic distribution.

See examples/relay_mesh/ for a complete runnable mesh demo.

Server-Side Monitoring

Use cc.hold_stats() to monitor SHM buffers held by resource methods in hold mode:

stats = cc.hold_stats()
# {'active_holds': 3, 'total_held_bytes': 52428800, 'oldest_hold_seconds': 12.5}

Architecture

The design philosophy of C-Two is not to define services, but to empower resources.

In scientific computation, resources encapsulating complex state and domain-specific operations need to be organized into cohesive units. We call the contracts describing these resources Core Resource Models (CRMs). Applications care more about how to interact with resources than where they are located. C-Two provides location transparency and uniform resource access, so any client can interact with a resource as if it were a local object.

graph LR
    subgraph Client Layer
        C1[Client] -->|cc.connect| P1[CRM Proxy]
        C2[Client] -->|cc.connect| P2[CRM Proxy]
    end

    subgraph Transport Layer
        P1 --> T{Protocol<br/>Auto-detect}
        P2 --> T
        T -->|thread://| TH[Thread<br/>Direct Call]
        T -->|ipc://| IPC[IPC<br/>UDS + SHM]
        T -->|http://| HTTP[HTTP<br/>Relay]
    end

    subgraph Resource Layer
        TH --> CRM1[Resource Instance]
        IPC --> CRM1
        HTTP --> CRM1
    end

Client Layer

Any code that calls cc.connect(...) to consume a resource. The returned proxy provides full type safety and location transparency — clients don't know (or care) where the resource is running.

  • cc.connect(CRMClass, name='...', address='...') returns a typed CRM proxy
  • The proxy supports context management: with cc.connect(...) as x: auto-closes

Resource Layer

Server-side stateful instances exposed through standardized CRM contracts.

  • CRM contract: Interface class decorated with @cc.crm(). Only methods declared here are remotely accessible.
  • Resource: Plain Python class implementing the contract — state + domain logic. Not decorated.
  • @transferable: Custom serialization for domain data types. Optionally provides from_buffer for zero-copy SHM views.
  • @cc.transfer: Per-method control over input/output transferable types and buffer mode.
  • @cc.read / @cc.write: Concurrency annotations — parallel reads, exclusive writes.
  • @cc.on_shutdown: Lifecycle callback invoked when a resource is unregistered (not exposed via RPC).

Transport Layer

Protocol-agnostic communication with automatic protocol detection based on address scheme:

Scheme Transport Use case
thread:// In-process direct call Zero serialization, testing
ipc:///path Unix domain socket + shared memory Multi-process, same host
http://host:port HTTP relay Cross-machine, web-compatible

The IPC transport uses a control-plane / data-plane separation: method routing flows through UDS inline frames while payload bytes are exchanged via shared memory — zero-copy on the data path. When from_buffer is available, hold mode keeps the SHM buffer alive across the CRM method call, enabling the CRM to operate directly on shared memory without deserialization.

Rust Native Layer

Performance-critical components are implemented in Rust and compiled as a Python extension via PyO3 + maturin:

The Rust workspace contains 7 crates organized in 4 layers (foundation → protocol → transport → bridge):

  • Buddy Allocator — Zero-syscall shared memory allocation for the IPC transport. Cross-process, lock-free on the fast path.
  • Wire Protocol — Frame encoding, chunk assembly, and chunk registry for large-payload lifecycle management.
  • HTTP Relay — High-throughput axum-based gateway bridging HTTP to IPC. Handles connection pooling and request multiplexing.

The Rust extension is compiled automatically during pip install c-two (from pre-built wheels) or uv sync (from source).


Installation

From PyPI

pip install c-two

Pre-built wheels are available for:

  • Linux: x86_64, aarch64
  • macOS: Apple Silicon (aarch64), Intel (x86_64)
  • Python: 3.10, 3.11, 3.12, 3.13, 3.14, 3.14t (free-threading)

If no pre-built wheel is available for your platform, pip will build from source (requires a Rust toolchain).

Development Setup

git clone https://github.com/world-in-progress/c-two.git
cd c-two
cp .env.example .env               # configure environment (optional)
uv sync                            # install dependencies + compile Rust extensions
uv sync --group examples           # install examples dependencies (pandas, pyarrow)
uv run pytest                      # run the test suite

Requires uv and a Rust toolchain.


Roadmap

Feature Status
Core RPC framework (CRM + Resource + Client) ✅ Stable
IPC transport with SHM buddy allocator ✅ Stable
HTTP relay (Rust-powered) ✅ Stable
Relay mesh with gossip-based discovery ✅ Stable
Chunked streaming (payloads > 256 MB) ✅ Stable
Heartbeat & connection management ✅ Stable
Read/write concurrency control ✅ Stable
Unified config architecture (Python SSOT) ✅ Stable
CI/CD & multi-platform PyPI publishing ✅ Stable
Disk spill for extreme payloads ✅ Stable
Hold mode with from_buffer zero-copy ✅ Stable
SHM residence monitoring (cc.hold_stats()) ✅ Stable
Async interfaces 🔜 Planned
Cross-language clients (TypeScript/Rust) 🔮 Future

See the full roadmap for details.


License

MIT


Built for scientific Python. Powered by Rust.

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

c_two-0.4.5.tar.gz (197.1 kB view details)

Uploaded Source

Built Distributions

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

c_two-0.4.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64

c_two-0.4.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARM64

c_two-0.4.5-cp314-cp314t-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

c_two-0.4.5-cp314-cp314t-macosx_10_12_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.14tmacOS 10.12+ x86-64

c_two-0.4.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

c_two-0.4.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

c_two-0.4.5-cp314-cp314-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

c_two-0.4.5-cp314-cp314-macosx_10_12_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.14macOS 10.12+ x86-64

c_two-0.4.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

c_two-0.4.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

c_two-0.4.5-cp313-cp313-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

c_two-0.4.5-cp313-cp313-macosx_10_12_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

c_two-0.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

c_two-0.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

c_two-0.4.5-cp312-cp312-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

c_two-0.4.5-cp312-cp312-macosx_10_12_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

c_two-0.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

c_two-0.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

c_two-0.4.5-cp311-cp311-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

c_two-0.4.5-cp311-cp311-macosx_10_12_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.11macOS 10.12+ x86-64

c_two-0.4.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

c_two-0.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

c_two-0.4.5-cp310-cp310-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

c_two-0.4.5-cp310-cp310-macosx_10_12_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.10macOS 10.12+ x86-64

File details

Details for the file c_two-0.4.5.tar.gz.

File metadata

  • Download URL: c_two-0.4.5.tar.gz
  • Upload date:
  • Size: 197.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for c_two-0.4.5.tar.gz
Algorithm Hash digest
SHA256 d17e2248af1333af4227c65e68af764167a443b6475305c2ffdda48bb3ca1ac2
MD5 c0b4d4c9df1917f303b73e7e1a15b24a
BLAKE2b-256 69ca237dce25734aa3b976c8f7de6caa70d693d312b8494182c5494785bb4789

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5.tar.gz:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 88844324899080d51cc91128e053ce7b87133ce56c7e7dda5364e660fc455f87
MD5 de0fa39c10eb88a3d264d772dcd09418
BLAKE2b-256 db4376de9d07b0e1a9275346f2f8c72c3d364a143d3ef0faac07d4cc1e04d267

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a747d83a19a3742b84b7c074a8cd6adf77c17ceb65764b48119bc60e8be508e1
MD5 f260b6c3edd00407648deff4e26777b0
BLAKE2b-256 1a2f228fa786d39f35efacab6877f1aa4c02826e0b96b83e34f305df493e7e27

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d8efbdd0befdce0f5ddb64a9af63ab2eea1140774b6084466091d8377f350901
MD5 fce95589d8fe8f40c3bf98744080ed6b
BLAKE2b-256 d73f78cc733baa10be7949a6be489e4b321cc9226bef6d2be2347c7bba8ebd31

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp314-cp314t-macosx_11_0_arm64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp314-cp314t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 6dcfe577df0997b826cb2d3f1adb5d48c5952cbc0d6deb29ea3f95da816ec404
MD5 77d5e7dfac91e615f33824aa26c10836
BLAKE2b-256 0e16193bbc31102daf2e41c59fb3928837d48a1443bf892c816da7d186fa4cc7

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp314-cp314t-macosx_10_12_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7993fe98e8511cb5eaa0b0444c0b5282979c980be8ee80ddcd79ef2f829811f9
MD5 1f4506dd0739aedf74c3ead051b95101
BLAKE2b-256 cc063be6135d21406b48d49a718d55a0c0f176a5aa7c439cbed81df098a9ed53

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 29991ee71c271cd4eec8b4485361377e11938b95f9d2eb12be2e61e5011c0934
MD5 6ef253230de234feda3ff517ce8e0ca8
BLAKE2b-256 c9b7c77e89e0ae028ab3f132d2503f99289b7e058931fe6bf6e216c6e47ab4f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8655878819e5bf64e4084344cc1eca523e69d8b987d359aac57482f7d6fff5aa
MD5 92b6ebe56a8183697b5c3f2d3a2271d6
BLAKE2b-256 4cb27dbe2d80477b630525c39dc1cfd2133ed1804eb52decb3353319b054f73c

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp314-cp314-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp314-cp314-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 7ffc1069303e044993448b58f942daa7d998089e2fb493e4871c405d0fa04174
MD5 2b8bea88f03aff815bce77f95cf953cc
BLAKE2b-256 a158b61f2472cf271cede72d5b42a54c2bb9d3c8b209e73e2287f96475625fe7

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp314-cp314-macosx_10_12_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ec5f3e8791a0feaf07ca9608eb7efc8c017c103c1d1d28e6e8bda291fae7e2b7
MD5 93a0d50e0fdc233365a872992ef77ae1
BLAKE2b-256 8bc4b3e1cdb7236d140a7045fdb0c79bfd596c22e6627ab387f384e458bc7bfb

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 58e4a42c599c24d81f199cdabaa95ca314b978b76a6e595ff4d5a2db577d3a54
MD5 7f545719303135d728ad004bf795531b
BLAKE2b-256 17db1c261c1b2c36e49cb292711f714ca7c7c3001cc68fadc74fcb2401043033

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f359499c19bc129848e646929de2e25b47f8db3ec3d17ce0bb0311b28619753a
MD5 3740fb84a766b132f401b3c356c8b9c1
BLAKE2b-256 f9de23c82027db60f218f8c1533b638a021df44351566c7ba06fe00be508ffb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp313-cp313-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 9d8eae14f6c89f62574744e0a9177e28803615644c381d89b153bd6ac0e1450d
MD5 2f1eaa3afe000f905718db37bd28fe8a
BLAKE2b-256 7737130d443d2a39118373d33bfce67d3a576f4cdff75c3ebd409b27cc07f759

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp313-cp313-macosx_10_12_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 89ad56a9102ee36356b19f25fd6c8139bee690fb6ccbb52d36e3195ca8b65d39
MD5 ac7a2e7fcce8b0729c3e85d9739fe478
BLAKE2b-256 f12648ec7044b8de933ffeb52ba0d749ab82f823a8ff68c57a51a25c9d9be854

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 48c58c0665a1bef843c412837c7d9c3bc0f0e9305bd31910aeb05cd48db906bd
MD5 a9d1cd4547af55731fd26f437241ebb8
BLAKE2b-256 948b0c5ffab2d1cff51bbbc1f5ffaf73d2e40d89c68cb741df3215b2990b00be

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 80a3c2fe632213056fa554e2d49555ab43b17efd5b0a3db531705b9f0e9eb38e
MD5 a53a43cfd6b225cfbe21023eab0e7aae
BLAKE2b-256 0a5ff74dc374cc2b0829d2becba8d7152d3985e79b70dc9394806a00514e47e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 989ee36a24646170aa64c2cc40a0ce39bff918e6c577db8bae570b05c864c2ce
MD5 2b1d579a892ae973957ce737428bb18d
BLAKE2b-256 71d0b09836a08b2a759215cac8a3a037fec59ead97547f69e7fcc6a7a5f745a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 50efa134a86bf007686fdf9136f4d448a3d8599cc7740331190f7e8f949f7445
MD5 e199da5ce61a0a866e70f400fe6583c9
BLAKE2b-256 7ee147406edb0a098ef86603e5bc317daa46e8fbdfdf34692c4b229562db999d

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 7dacb39ff798d21bcccfd0dbffcc84e1b38838a087cc092c0a27d1e026862daa
MD5 1a1d1c3d91251840690627222d855bd6
BLAKE2b-256 2666f69b195444d51c3cb252c31937527774a2fc59a237de21b1df6c47fc437e

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 810f894c37fae0ba6feca90b29cdbc32ead1dfdaaeee486d753496ef1d80d3a8
MD5 a86ae1299ecb428beb7947d2b67b8a96
BLAKE2b-256 8685fd3739d9884156be2981bdda441f21fca24c254b5d1a621c9ca059ecc453

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp311-cp311-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 836f185b00b3d41416273d98dc5a843b95bbfac4ced88468b7646765a9d5de74
MD5 265ac5802333495f56817d472fd6da07
BLAKE2b-256 277c90bc0e0c23d84cf448cc161f5aaf90c695e08b0316c0d821c8ef4af46f8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp311-cp311-macosx_10_12_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2fdc7af5b116e6c7923fcbcff390ead05c0951a9c84164b09fb1c53b1bf63c84
MD5 c0b3b65df3d361f14dcc50accb087b42
BLAKE2b-256 f5d2395b843de3b598006d9e4a8633de91e51efd581bfffd2e003112d5772ae0

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d5ae80c8889f2ecb2a207f594175dba3742c0015802d7231878161866be97580
MD5 d842d601965bf5030254c7f7d96e7d8d
BLAKE2b-256 257c3e8743615c8df485b91a0575cc3f95344c196bb27606814443e74dcad30d

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 494e478e6416ffab8e20a1c53686de66980e161815f78972818230b6afade8ec
MD5 fbd7c9aa68867e257b6623cc3031fdb5
BLAKE2b-256 9eeb68fbc644dfa934a16f49a273a068987720a88212266ef275aa97ab44c9e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: release.yml on world-in-progress/c-two

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

File details

Details for the file c_two-0.4.5-cp310-cp310-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for c_two-0.4.5-cp310-cp310-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 91d0c527391cf72e6a4431f9bad9263078392c33b323cd29ab3d5eacab03f5e3
MD5 ba6a9422d22d35de0e90509544d58795
BLAKE2b-256 7808aea151e0d186ecd398dc138cdd4b85e6c4a98d86a35ce44f1b4e2e33d6b1

See more details on using hashes here.

Provenance

The following attestation bundles were made for c_two-0.4.5-cp310-cp310-macosx_10_12_x86_64.whl:

Publisher: release.yml on world-in-progress/c-two

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