API

This part of the documentation covers all the interfaces of bocpy.

bocpy.__version__ = '0.9.0'

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.

Behaviors

class bocpy.Cown(value)

Lightweight wrapper around the underlying cown capsule.

acquire()

Acquires the cown (required for reading and writing).

property acquired: bool

Whether the cown is currently acquired.

property exception: bool

Whether the held value is the result of an unhandled exception.

release()

Releases the cown.

property value: T

Return the current stored value.

@bocpy.when

Decorator to schedule a function as a behavior using given cowns.

This decorator takes a list of zero or more cown objects, which will be passed in the order in which they were provided to the decorated function. The function itself is extracted and run as a behavior once all the cowns are available (i.e., not acquired by other behaviors). Behaviors are scheduled such that deadlock will not occur.

The function itself will be replaced by a Cown which will hold the result of executing the behavior. This Cown can be used for further coordination.

The transpiler recognises module-level aliases for the decorator, so from bocpy import when as boc_when and @boc_when(...), as well as import bocpy [as alias] followed by @bocpy.when(...) / @alias.when(...), are all supported. Aliases declared inside a function body are not tracked.

bocpy.wait(timeout=None, *, stats=False, noticeboard=False)

Block until all behaviors complete, with optional timeout.

When stats=True, captures the per-worker _core.scheduler_stats snapshot. When noticeboard=True, captures the noticeboard contents as a plain dict at the quiescence point (NOT after teardown — the two are equivalent in single-caller programs but the quiescence snapshot is the documented one). See the stub in __init__.pyi for the full contract.

Return value:

  • neither flag: None.

  • stats=True only: list[dict] (or []).

  • noticeboard=True only: dict[str, Any] (or {}).

  • both flags: WaitResult.

Internally a thin wrapper around quiesce() + Behaviors.stop; quiescence timeout warns rather than raising.

class bocpy.WaitResult(stats: list[dict], noticeboard: dict[str, Any])

Bundle of optional artifacts returned by wait().

Only produced when both stats=True and noticeboard=True are passed (e.g. wait(stats=True, noticeboard=True)).

Variables:
  • stats – Per-worker scheduler-stats snapshot.

  • noticeboard – Final noticeboard contents as a plain dict.

noticeboard: dict[str, Any]

Alias for field number 1

stats: list[dict]

Alias for field number 0

bocpy.quiesce(timeout=None, *, stats=False, noticeboard=False)

Block until in-flight behaviors complete without tearing down the runtime.

Parameters:
  • timeout (Optional[float]) – Upper bound (seconds). None waits forever.

  • stats (bool) – If True, capture per-worker scheduler stats.

  • noticeboard (bool) – If True, capture a noticeboard snapshot via a thread cycle.

Raises:
  • TimeoutError – If quiescence is not reached within timeout.

  • RuntimeError – If called from a non-primary interpreter while pinned cowns are live.

bocpy.start(worker_count=None, module=None)

Start the behavior runtime: worker pool plus noticeboard thread.

Idempotent: bare start() on a running runtime is a silent no-op; mismatched worker_count/module raise.

The runtime distributes scheduling (2PL link/release) across caller and worker threads; there is no central scheduler thread.

The runtime distributes scheduling (2PL link/release) across caller and worker threads; there is no central scheduler thread.

Parameters:
  • worker_count (Optional[int]) – The number of worker interpreters to start. If None, defaults to the number of available cores minus one.

  • module (Optional[tuple[str, str]]) – A tuple of the target module name and file path to export for worker import. If None, the caller’s module will be used.

Raises:

RuntimeError – If called from a non-primary interpreter, or if the runtime is already up under a different worker_count / module than the one supplied.

Cown Groups

In addition to passing individual cowns to @when, you can pass a list of cowns to acquire an entire group atomically. The list is delivered to the behavior parameter as a list[Cown]:

from bocpy import Cown, when, wait

items = [Cown(i) for i in range(5)]

@when(items)
def _(items):
    # `items` is a list[Cown] — all five acquired together
    total = sum(c.value for c in items)
    print("Sum:", total)

wait()

You can mix individual cowns and groups freely:

summary = Cown(0)
items = [Cown(i) for i in range(5)]

@when(summary, items)
def _(summary, items):
    summary.value = sum(c.value for c in items)

Each argument to @when becomes one parameter of the decorated function: a single Cown is passed directly, while a list is delivered as a list[Cown].

Runtime Lifecycle

The bocpy runtime follows a simple lifecycle:

  1. Start — the first @when call (or an explicit start()) spawns the worker sub-interpreters and the noticeboard thread.

  2. Schedule@when / whencall() schedules behaviors against cowns. Scheduling and release run on the caller and worker threads; there is no central scheduler thread.

  3. Waitwait() blocks until all scheduled behaviors complete, then tears down the runtime (joins workers, closes the noticeboard). For a non-tearing-down checkpoint (e.g. parallel-search inspection between rounds), use quiesce() instead — it blocks until the runtime is quiescent, returns optional stats / noticeboard snapshots, and leaves workers and the noticeboard thread running so further @when calls work immediately.

  4. Re-start — after wait() returns, the next @when call spins up a fresh runtime. The noticeboard is cleared and worker statistics are reset; existing Cown objects survive and can be scheduled against the new runtime.

bocpy.WORKER_COUNT = 3

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4

Advanced

bocpy.whencall(thunk, args, captures)

Invoke a behavior by name with cown args and captured values.

Return type:

Cown

Pinned Cowns

See Pinned Cowns for the conceptual overview, the coarse-grained dispatch pattern, event-loop integration recipes, and the free-threaded support trajectory.

class bocpy.PinnedCown(value)

A cown whose value never leaves the main interpreter.

Behaviors whose request set contains any PinnedCown run on the main interpreter, scheduled onto a pump queue that the runtime drains under wait() and that hosts may drive explicitly via bocpy.pump().

A regular Cown stores its value as cross-interpreter data: every time a worker acquires the cown the value is unpickled into the worker’s interpreter, mutated, and re-pickled on release. That round-trip is the reason a cown can be acquired by any worker – but it also means the value must be picklable and that the same Python object is never observed twice in a worker.

Many useful values cannot survive that round-trip: pyglet shapes, Tk widgets, open file handles, ctypes pointers into a library loaded by __main__, an asyncio event loop, a GPU context. Their __reduce__ either raises or silently reconstructs a broken object on the other side.

A PinnedCown holds its value as a plain PyObject reference in the main interpreter. The value never goes through XIData; the same Python object is observed on every acquire. The trade-off: every behavior whose request set contains a pinned cown runs on the main thread, drained by pump() (called from your event loop) or implicitly by wait().

Pattern: coarse-grained pinned dispatch

The pinned arm is single-consumer (the main thread). If you schedule a pinned behavior per item, those behaviors serialise on the main thread and you lose worker parallelism. Schedule pinned behaviors coarsely – one per logical frame or batch, not per item. Do per-item computation on workers against per-item Cown slices, then dispatch one pinned @when per frame that captures all of them together with the main-thread canvas / handle and performs the batched write-back.

Thread affinity

Pinned cowns may only be constructed from the main interpreter. Constructing one from a worker raises RuntimeError; the value would have no home interpreter to live in. pump() likewise requires the main interpreter – any thread within it on classic CPython; on free-threaded builds (Py_GIL_DISABLED) a single thread at a time, enforced by a CAS on pump entry that raises RuntimeError if a second thread tries to pump concurrently. The CAS is cleared on every exit path, including BaseException propagation from a pinned body.

Mixed request sets

A behavior may freely combine pinned and unpinned cowns; the 2PL acquisition order is unchanged. As soon as the request set contains any pinned cown, the body runs on the main thread. Unpinned cowns in the set still travel through XIData into the main interpreter for the body’s duration.

Exception model

Body exceptions follow the same rules as worker behaviors: captured on the result Cown and surfaced through cown.exception. The default pump() does not re-raise; pass raise_on_error=True to opt into fail-fast propagation.

Nested pumping

Calling pump() from inside a pinned-behavior body raises RuntimeError (v1).

Handle vs. value

A PinnedCown handle (the Python wrapper object and its C capsule) is a normal cross-interpreter shareable. It travels via the same XIData mechanism as a regular Cown and may be:

  • shipped as a captured variable to a worker behavior,

  • embedded in any value graph stored in a regular Cown (Cown(PinnedCown(x)) is supported),

  • placed in a noticeboard entry via notice_write() or notice_update().

What never crosses interpreter boundaries is the value x. A worker that ends up holding a pinned-cown handle can do exactly one useful thing with it: schedule pinned behaviors against it (which the runtime auto-routes to the main pump queue). Any attempt to acquire the value from a worker is rejected by the C-level owner CAS – the value’s owner is permanently the main interpreter.

Restrictions
  • Constructible only on the main interpreter (see Thread affinity above).

  • The pinning interpreter is the main interpreter, by design. There is one pinned queue per process and one consumer of that queue (the main pumper); pinned cowns do not split across interpreters.

bocpy.pump(deadline_ms=None, max_behaviors=None, raise_on_error=False)

Run pinned behaviors that are ready, then return.

Drains the main-thread queue of behaviors whose request sets contain at least one PinnedCown. Each behavior runs to completion before the next starts. The pump is non-preemptive: deadline_ms gates starting the next behavior, not interrupting one already running.

Call pump() from your event loop’s idle / on-tick hook. Script-mode programs need not call it explicitly – wait() pumps internally when any PinnedCown exists in the process.

Bounding
  • deadline_ms: wall-clock budget. None drains to empty; otherwise a positive int.

  • max_behaviors: hard count. None drains to empty; otherwise a positive int.

0 is rejected for both bounds (use if budget: at the call site instead of relying on the pump to no-op).

Exception model

By default body exceptions land on the result cown; pump continues. With raise_on_error=True, the first body exception re-raises on the pump thread after the queue finishes draining. BaseException (KeyboardInterrupt, SystemExit, GeneratorExit) propagates immediately after the offending behavior’s per-iteration cleanup completes; any behaviors still queued are left in place for the next pump() call.

Thread affinity

pump() must run on the main interpreter. Calling from a worker interpreter raises RuntimeError immediately. On free-threaded builds (Py_GIL_DISABLED) only one thread may pump at a time: a concurrent call from a different thread raises RuntimeError. Calling pump() when no PinnedCown exists is a no-op returning PumpResult(0, False, 0).

Reentrance

Not reentrant. Calling from inside a pinned-behavior body raises RuntimeError (v1).

Parameters:
  • deadline_ms (Optional[int]) – Wall-clock budget in milliseconds. None for unbounded; otherwise a positive int. Must not be bool.

  • max_behaviors (Optional[int]) – Maximum behaviors to start this call. None for unbounded; otherwise a positive int. Must not be bool.

  • raise_on_error (bool) – Re-raise the first body exception after drain.

Returns:

PumpResult (executed, deadline_reached, raised). On BaseException propagation, pump() raises and no PumpResult is returned.

Return type:

PumpResult

Raises:
  • TypeError – if deadline_ms or max_behaviors is not None, a positive int, or is bool.

  • RuntimeError – wrong interpreter, concurrent pump on free-threaded, nested pump, no live runtime (start() has not been called), or watchdog raise threshold tripped.

class bocpy.PumpResult(executed: int, deadline_reached: bool, raised: int)

Result of a pump() call.

Variables:
  • executed – Pinned behaviors whose lifecycle ran to completion this call. Counts the iteration even if the body raised or the acquire failed (the MCS chain still drained).

  • deadline_reachedTrue iff the loop exited because deadline_ms tripped before the queue drained and before max_behaviors capped. False on drain, on max_behaviors cap, or when deadline_ms is None.

  • raised – Pinned behaviors whose body raised an Exception captured to the result cown’s .exception. Cleanup-path failures (acquire, release, noticeboard cache-clear) do not count: they are logged via PyErr_WriteUnraisable and the iteration is still counted in executed. On BaseException propagation, pump() raises and no PumpResult is returned.

deadline_reached: bool

Alias for field number 1

executed: int

Alias for field number 0

raised: int

Alias for field number 2

bocpy.set_pump_watchdog(warn_ms=1000, on_starve=None)

Configure the pinned-queue starvation watchdog.

The watchdog is disabled until this function is called. No call means no warnings, regardless of how long the pinned queue has been non-empty. warn_ms=1000 is the kwarg default that applies if and when you opt in, not the runtime default.

Warn-side sampling fires from pump() on entry (so wait()’s auto-pump loop counts). The threshold gates on queue-non-empty time: a program that runs only unpinned work indefinitely never trips it.

  • warn_ms (kwarg default 1000): logs a warning carrying the queue’s non-empty duration (ms) and current depth. Pass None to disable. Must be a positive int when set.

  • on_starve: optional callable (severity, message) to replace the default logger. Use this to escalate (for example on_starve=lambda s, m: pytest.fail(m) in tests, or a counter / alert hook in production).

Parameters:
  • warn_ms (Optional[int]) – Warn-after threshold in milliseconds, or None to disable warnings.

  • on_starve (Optional[Callable[[int, str], None]]) – Optional (severity, message) callback that replaces the default logger sink.

Raises:
  • TypeError – if warn_ms is not None or a positive int, or on_starve is not callable.

  • OverflowError – if warn_ms exceeds the maximum representable nanosecond value.

Return type:

None

bocpy.set_wait_pump_poll(ms=50)

Set the poll cadence for wait()’s auto-pump loop.

Default cadence is 50 ms — the upper bound on how long the auto-pump loop will park between checks when no broadcast wakes it. The setting is process-global and may be changed at any time; the active wait() loop picks up the new value on its next iteration.

Parameters:

ms (int) – Poll cadence in milliseconds. Must be positive.

Return type:

None

Noticeboard

See the Noticeboard guide for a conceptual overview, consistency model, and worked examples.

bocpy.notice_write(key, value)

Write a value to the noticeboard.

The write is fire-and-forget: the value is serialized immediately and handed to a dedicated noticeboard thread, which applies it under mutex. notice_write returns as soon as the message is enqueued.

No ordering guarantee. A subsequent behavior — even one that chains directly off the writer through a shared cown — is not guaranteed to observe this write. The noticeboard mutator runs on its own thread and may not have processed the message by the time the next behavior reads. Treat the noticeboard as eventually consistent shared state, never as a synchronization channel between behaviors. Use cowns or send/receive for that.

The noticeboard supports up to 64 distinct keys. Writes beyond the limit are not applied; the noticeboard thread catches the resulting error and logs a warning. No exception propagates to the caller.

Values may embed Cown references; the noticeboard keeps each embedded cown alive for as long as the entry remains in the noticeboard.

Parameters:
  • key (str) – The noticeboard key (max 63 UTF-8 bytes).

  • value (Any) – The value to store.

Return type:

None

bocpy.notice_update(key, fn, default=None)

Atomically update a noticeboard entry.

Reads the current value for key (or default if absent), applies fn to it, and writes the result back. The read-modify-write is atomic because the single-threaded noticeboard mutator performs all three steps without interleaving.

Like notice_write(), the call is fire-and-forget and carries no ordering guarantee with respect to other behaviors. The update is processed on the noticeboard thread; subsequent behaviors may or may not observe the result.

Both fn and default must be picklable — they are serialized and sent to the noticeboard thread via the message queue. Lambdas and closures are not picklable; use functools.partial with a module-level function or an operator function instead:

import operator
from functools import partial
notice_update("total", partial(operator.add, 5), default=0)
notice_update("best", partial(max, 42), default=float("-inf"))

If fn raises, the key retains its previous value and a warning is logged by the noticeboard thread.

Important: fn runs synchronously on the single-threaded noticeboard mutator. It must be fast, pure (no side effects), and must not call any bocpy API (notice_write, send, when, etc.). A blocking or expensive fn will stall every other noticeboard mutation.

If fn returns the REMOVED sentinel, the entry is deleted from the noticeboard instead of being updated.

The value returned by fn may embed Cown references; the noticeboard retains them until the entry is overwritten or deleted, identical to notice_write().

Warning

fn and default are pickled and sent to the noticeboard thread for execution. Anyone with permission to call this function can therefore cause arbitrary Python code to run on the noticeboard thread, which holds the privileged noticeboard-mutator role. In the current threat model bocpy treats all code running in the runtime (primary and sub-interpreters) as equally trusted, so this is no worse than any other cross-interpreter message. If you need to run untrusted behavior code, restrict what can reach boc_noticeboard and audit callers of notice_update().

Parameters:
  • key (str) – The noticeboard key (max 63 UTF-8 bytes).

  • fn (Callable[[Any], Any]) – A picklable callable taking the current value, returning the new.

  • default (Any) – Value used when key does not yet exist.

Return type:

None

bocpy.notice_delete(key)

Delete a single noticeboard entry.

The deletion is fire-and-forget: the request is sent to the noticeboard thread, which removes the entry under mutex. If the key does not exist, the operation is a no-op. Like notice_write(), this carries no ordering guarantee with respect to other behaviors.

Alternatively, use notice_update with a function that returns REMOVED to conditionally delete an entry based on its current value.

Parameters:

key (str) – The noticeboard key to delete (max 63 UTF-8 bytes).

Return type:

None

bocpy.noticeboard()

Return a cached snapshot of the noticeboard.

The noticeboard is a behavior-scope read surface. The supported use is from inside a @when body: the first call captures all entries under mutex and caches them, and every subsequent call in the same behavior returns the same cached view.

The returned mapping is read-only.

The only supported way to read the noticeboard from the main thread is to ask wait() for it via wait(noticeboard=True) (or wait(stats=True, noticeboard=True)); that snapshot is taken on the main thread between joining the noticeboard mutator thread and clearing the C-side entries.

Calling noticeboard() or notice_read() from any other main-thread context (outside a behavior, outside wait(noticeboard=True)) is undefined behavior: the cached proxy is never re-anchored on a behavior boundary, so subsequent calls may observe either a stale snapshot or partially-applied writes.

Seeding the noticeboard with notice_write() from the main thread before scheduling behaviors is fine and is the recommended pattern for installing read-mostly configuration.

Returns:

A read-only mapping of keys to their stored values.

Return type:

Mapping[str, Any]

bocpy.notice_read(key, default=None)

Read a single key from the noticeboard.

Convenience wrapper over noticeboard() that takes a snapshot and returns one value. The same supported-usage contract applies: call from inside a @when behavior, or read the final state on main via wait(noticeboard=True). Calling notice_read() from any other main-thread context is undefined behavior.

Parameters:
  • key (str) – The noticeboard key to read.

  • default (Any) – Value returned when key is absent.

Returns:

The stored value, or default if the key does not exist.

Return type:

Any

bocpy.notice_sync(timeout=30.0)

Block until the caller’s prior noticeboard mutations are committed.

Because notice_write(), notice_update(), and notice_delete() are fire-and-forget, a behavior that wants read-your-writes ordering against a subsequent behavior must call notice_sync() after its writes. The call posts a sentinel onto the boc_noticeboard tag (which is FIFO per producer) and blocks until the noticeboard thread has drained that sentinel. By the time this returns, every write/update/delete posted from the calling thread before the sentinel has been applied to the noticeboard.

The barrier carries no ordering guarantee with respect to writes posted from other threads or behaviors interleaved with the caller’s; it only flushes the caller’s own queued mutations.

Parameters:

timeout (Optional[float]) – Maximum seconds to wait. None waits forever. Defaults to 30 seconds.

Raises:
  • TimeoutError – If the noticeboard thread does not drain the caller’s sentinel within timeout seconds.

  • RuntimeError – If the runtime is not started.

Return type:

None

bocpy.REMOVED = REMOVED

Sentinel returned by notice_update fn to delete the entry.

Math

class bocpy.Matrix(rows, columns, values=None)

A dense 2-D matrix of double-precision floats.

T

Return a new matrix that is the transpose of this one.

__init__(*args, **kwargs)

Create a new rows x columns matrix.

Parameters:
  • rows – Number of rows (must be ≥ 1).

  • columns – Number of columns (must be ≥ 1).

  • values – Initial values. May be None (zero-filled), a scalar (broadcast to every element), or a flat sequence of rows x columns numbers in row-major order.

abs(in_place=False)

Element-wise absolute value.

Return type:

Matrix

acquired

Whether the matrix is currently acquired.

classmethod allclose(lhs, rhs, /, rtol=1e-05, atol=1e-08, equal_nan=False)

Check element-wise equality within tolerance.

angle(axis=None)

Polar angle (atan2(y, x)) of every 2D vector. Returns a float for a single 2D vector, an Mx1 column matrix for an Nx2 row batch, or a 1xN row matrix for a 2xN column batch. On the ambiguous 2x2 shape the default is per-row; pass axis=0 to force per-column.

Return type:

Union[float, Matrix]

ceil(in_place=False)

Element-wise ceiling.

Return type:

Matrix

clip(min_or_maxval, /, maxval=None)

Clip elements to a range.

Return type:

Matrix

columns

The number of columns in the matrix.

classmethod concat(values, /, axis=0)

Concatenate matrices along an axis.

Return type:

Matrix

copy()

Return a deep copy.

Return type:

Matrix

cross(other, /, axis=None)

2D (scalar z-component) or 3D cross product against another vector or batch. 1x2 / 2x1 inputs return a float; 1x3 / 3x1 return a Matrix preserving self’s orientation. Nx2 / 2xN row/column batches return per-vector scalars (Mx1 / 1xN); Nx3 / 3xN return same-shape batches. Batch operands accept either a same-shape other or a single 2D/3D vector (1xK / Kx1) broadcast against every per-vector slot — self must be the batch (cross is anticommutative). axis disambiguates the 2x2 / 3x3 squares (default rows, axis=0 for columns).

Return type:

Union[float, Matrix]

floor(in_place=False)

Element-wise floor.

Return type:

Matrix

length

Frobenius (L2) magnitude of the matrix as a read-only property.

Equivalent to magnitude() called with no axis argument: sqrt(sum(x**2 for x in m)) over all elements. Exposed as a @property so that vector-like code reads naturally (direction.length, velocity.length) without the extra parentheses of a method call.

Note: this is not the element count. For rows * columns use size (or len(), which returns rows).

magnitude(axis=None)

Euclidean magnitude.

Return type:

Union[float, Matrix]

magnitude_squared(axis=None)

Sum of squared elements (Euclidean magnitude without the sqrt).

Return type:

Union[float, Matrix]

max(axis=None)

Maximum of elements.

Return type:

Union[float, Matrix]

mean(axis=None)

Mean of elements.

Return type:

Union[float, Matrix]

min(axis=None)

Minimum of elements.

Return type:

Union[float, Matrix]

negate(in_place=False)

Element-wise negation.

Return type:

Matrix

classmethod normal(mean=0.0, stddev=1.0, /, size=None)

Sample from a normal distribution.

Return type:

Union[float, Matrix]

normalize(axis=None, in_place=False)

Divide elements by their magnitude. axis=None divides by the matrix’s total magnitude; axis=0 divides each column by its own magnitude; axis=1 divides each row by its own magnitude. Rows or columns whose magnitude is zero are left as the all-zero vector. Sub-normal magnitudes may overflow during division; threshold with magnitude_squared() if safety matters. When in_place=True, mutates self and returns it.

Return type:

Matrix

classmethod ones(size, /)

Create a matrix of ones.

perpendicular(axis=None, in_place=False)

Rotate every 2D vector 90 degrees counter-clockwise: (x, y) -> (-y, x). Accepts a single 2D vector (1x2 or 2x1), a row batch (Nx2), or a column batch (2xN). On the ambiguous 2x2 shape the default is per-row; pass axis=0 to force per-column. When in_place=True, mutates self and returns it.

Return type:

Matrix

round(in_place=False)

Element-wise rounding (banker’s; IEEE round-half-to-even).

Return type:

Matrix

rows

The number of rows in the matrix.

select(indices, /, axis=0)

Select rows or columns by index.

shape

The (rows, columns) shape of the matrix.

size

The total element count of the matrix (rows * columns).

sum(axis=None)

Sum of elements.

Return type:

Union[float, Matrix]

transpose(in_place=False)

Return a transposed copy, or transpose self in place when in_place=True (in which case self is returned).

Return type:

Matrix

classmethod uniform(minval=0.0, maxval=1.0, /, size=None)

Sample from a uniform distribution.

Return type:

Union[float, Matrix]

vecdot(other, /, axis=None)

Axis-aware inner product: sum of element-wise products. Equivalent to numpy.linalg.vecdot for 1-D inputs with axis=None; not equivalent to numpy.dot.

Return type:

Union[float, Matrix]

classmethod vector(values, /, as_column=False)

Create a vector from a sequence.

Return type:

Matrix

w

Set the fourth vector component.

x

Set the first vector component.

y

Set the second vector component.

z

Set the third vector component.

classmethod zeros(size, /)

Create a zero-filled matrix.

Messaging

See the Messaging guide for a conceptual overview, the selective-receive pattern, timeouts, and a worked calculator example.

bocpy.send(tag, contents, /)

Sends a message.

bocpy.receive(tags, /, timeout=-1, after=None)

Receives a message.

bocpy.set_tags(tags, /)

Assigns tags to message queues.

bocpy.drain(tags, /)

Drains all messages for the given tags.

bocpy.TIMEOUT = '__timeout__'

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.

C ABI

See C ABI for the full usage contract for downstream C extensions that want to interoperate with bocpy at the C level.

bocpy.get_include()

Return the absolute path to the bocpy public C header root.

Use the returned path as an additional include_dirs entry on a downstream setuptools.Extension so its translation units can #include <bocpy/bocpy.h>. The directory contains a single bocpy/ subdirectory holding the public ABI surface; bocpy’s private headers are not exposed.

Returns:

Absolute filesystem path to the include root (the parent of the bocpy/ subdirectory containing bocpy.h and xidata.h).

Return type:

str

bocpy.get_sources()

Return platform-specific extra C sources for downstream extensions.

On Windows the returned list contains the absolute path to bocpy_msvc.c, which provides MSVC out-of-line bodies for the atomic ops declared in <bocpy/bocpy.h>. On non-Windows platforms the list is empty (<stdatomic.h> provides everything).

Returns:

A list of absolute paths to add to a downstream setuptools.Extension’s sources= list.

Return type:

list[str]