Vendor qroissant 0.3.0 baseline

This commit is contained in:
Cam Zalewski 2026-05-20 14:11:30 +01:00
commit 53ac90fe84
56 changed files with 18309 additions and 0 deletions

View file

@ -0,0 +1,68 @@
"""Public Python API for qroissant."""
import importlib
__all__ = [
"AsyncConnection",
"AsyncPool",
"AsyncRawResponse",
"Atom",
"Attribute",
"Compression",
"Connection",
"DecodeError",
"DecodeOptions",
"DecodeOptionsBuilder",
"Dictionary",
"EncodeField",
"EncodeFieldBuilder",
"EncodeOptions",
"EncodeOptionsBuilder",
"Encoding",
"Endpoint",
"List",
"ListInterpretation",
"MessageHeader",
"MessageType",
"OperationError",
"Pool",
"PoolClosedError",
"PoolError",
"PoolMetrics",
"PoolOptions",
"Primitive",
"ProtocolError",
"QRuntimeError",
"QroissantError",
"RawResponse",
"Shape",
"StringInterpretation",
"SymbolInterpretation",
"Table",
"TransportError",
"Type",
"UnionMode",
"Value",
"Vector",
"__native_available__",
"FormattingOptions",
"FormattingOptionsBuilder",
"RowDisplay",
"decode",
"encode",
"get_formatting_options",
"reset_formatting_options",
"set_formatting_options",
]
try:
_native = importlib.import_module("qroissant._native")
for _name in __all__:
if _name != "__native_available__":
globals()[_name] = getattr(_native, _name)
__native_available__ = True
except ImportError: # pragma: no cover
__native_available__ = False
if not __native_available__:
__all__ = ["__native_available__"]

View file

@ -0,0 +1,50 @@
from qroissant._client import AsyncConnection as AsyncConnection
from qroissant._client import AsyncPool as AsyncPool
from qroissant._client import AsyncRawResponse as AsyncRawResponse
from qroissant._client import Connection as Connection
from qroissant._client import Pool as Pool
from qroissant._client import PoolMetrics as PoolMetrics
from qroissant._client import RawResponse as RawResponse
from qroissant._config import DecodeOptions as DecodeOptions
from qroissant._config import DecodeOptionsBuilder as DecodeOptionsBuilder
from qroissant._config import EncodeField as EncodeField
from qroissant._config import EncodeFieldBuilder as EncodeFieldBuilder
from qroissant._config import EncodeOptions as EncodeOptions
from qroissant._config import EncodeOptionsBuilder as EncodeOptionsBuilder
from qroissant._config import Endpoint as Endpoint
from qroissant._config import ListInterpretation as ListInterpretation
from qroissant._config import PoolOptions as PoolOptions
from qroissant._config import StringInterpretation as StringInterpretation
from qroissant._config import SymbolInterpretation as SymbolInterpretation
from qroissant._config import UnionMode as UnionMode
from qroissant._errors import DecodeError as DecodeError
from qroissant._errors import OperationError as OperationError
from qroissant._errors import PoolClosedError as PoolClosedError
from qroissant._errors import PoolError as PoolError
from qroissant._errors import ProtocolError as ProtocolError
from qroissant._errors import QroissantError as QroissantError
from qroissant._errors import QRuntimeError as QRuntimeError
from qroissant._errors import TransportError as TransportError
from qroissant._message import Compression as Compression
from qroissant._message import Encoding as Encoding
from qroissant._message import MessageHeader as MessageHeader
from qroissant._message import MessageType as MessageType
from qroissant._repr import FormattingOptions as FormattingOptions
from qroissant._repr import FormattingOptionsBuilder as FormattingOptionsBuilder
from qroissant._repr import RowDisplay as RowDisplay
from qroissant._repr import get_formatting_options as get_formatting_options
from qroissant._repr import reset_formatting_options as reset_formatting_options
from qroissant._repr import set_formatting_options as set_formatting_options
from qroissant._serde import decode as decode
from qroissant._serde import encode as encode
from qroissant._values import Atom as Atom
from qroissant._values import Attribute as Attribute
from qroissant._values import Dictionary as Dictionary
from qroissant._values import List as List
from qroissant._values import Primitive as Primitive
from qroissant._values import Shape as Shape
from qroissant._values import Table as Table
from qroissant._values import Type as Type
from qroissant._values import Value as Value
from qroissant._values import Vector as Vector

View file

@ -0,0 +1,453 @@
from __future__ import annotations
from types import TracebackType
from typing import Literal, overload
from qroissant._config import DecodeOptions, Endpoint, PoolOptions
from qroissant._message import MessageHeader
from qroissant._values import Value
class RawResponse:
"""Read-only file-like wrapper over raw q IPC response bytes.
Notes
-----
Raw queries stream responses forward-only, decoding them on demand.
Thread Safety
-------------
**Not thread-safe.** Each ``RawResponse`` holds an exclusive lease on its
parent connection the connection cannot be reused until the response is
fully consumed or explicitly closed.
"""
def __enter__(self) -> RawResponse: ...
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None: ...
@property
def closed(self) -> bool:
"""Check if the response is closed."""
...
@property
def header(self) -> MessageHeader:
"""Retrieve the IPC message header."""
...
def close(self) -> None:
"""Close the underlying response stream."""
...
def readable(self) -> bool:
"""Return True if the stream is readable."""
...
def seekable(self) -> bool:
"""Return True if the stream supports random access (returns False)."""
...
def tell(self) -> int:
"""Return the current stream position."""
...
def read(self, size: int | None = None, /) -> bytes:
"""Read bytes from the response payload."""
...
def read1(self, size: int | None = None, /) -> bytes:
"""Read bytes from the response payload with minimal blocking."""
...
def readinto(self, buffer: bytearray | memoryview, /) -> int:
"""Read payload bytes into a pre-allocated buffer."""
...
def readinto1(self, buffer: bytearray | memoryview, /) -> int:
"""Read payload bytes into a pre-allocated buffer with minimal blocking."""
...
def decode(self, *, options: DecodeOptions | None = None) -> Value:
"""Decode the remaining payload bytes into a qroissant value."""
...
class AsyncRawResponse:
"""Asynchronous read-only wrapper over raw q IPC response bytes."""
async def __aenter__(self) -> AsyncRawResponse: ...
async def __aexit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None: ...
@property
def closed(self) -> bool:
"""Check if the response is closed."""
...
@property
def header(self) -> MessageHeader:
"""Retrieve the IPC message header."""
...
async def close(self) -> None:
"""Close the underlying response stream."""
...
async def read(self, size: int | None = None, /) -> bytes:
"""Read bytes from the response payload asynchronously."""
...
async def read1(self, size: int | None = None, /) -> bytes:
"""Read bytes with minimal blocking asynchronously."""
...
async def readinto(self, buffer: bytearray | memoryview, /) -> int:
"""Read payload bytes into a buffer asynchronously."""
...
async def readinto1(self, buffer: bytearray | memoryview, /) -> int:
"""Read payload bytes into a buffer with minimal blocking asynchronously."""
...
async def decode(self, *, options: DecodeOptions | None = None) -> Value:
"""Decode the remaining payload bytes into a qroissant value asynchronously."""
...
class PoolMetrics:
"""Snapshot of a pool's occupancy, configuration, and lifecycle state."""
@property
def connections(self) -> int:
"""Total number of currently tracked connections."""
...
@property
def idle_connections(self) -> int:
"""Number of tracked connections that are currently idle."""
...
@property
def max_size(self) -> int:
"""Configured maximum pool size."""
...
@property
def min_idle(self) -> int | None:
"""Configured minimum idle target."""
...
@property
def initialized(self) -> bool:
"""Whether the underlying pool has been created yet."""
...
@property
def closed(self) -> bool:
"""Whether the pool has been explicitly closed."""
...
class Connection:
"""Synchronous connection capable of executing q IPC requests.
Parameters
----------
endpoint : Endpoint
Addressing and transport configuration.
options : DecodeOptions | None, optional
Default options to apply to decoded queried wrapper objects.
Thread Safety
-------------
**Not thread-safe.** Use one connection per thread, or use :class:`Pool`
for safe multi-threaded access.
"""
def __init__(
self,
endpoint: Endpoint,
*,
options: DecodeOptions | None = None,
) -> None: ...
def __enter__(self) -> Connection: ...
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None: ...
def close(self) -> None:
"""Close the underlying connection."""
...
@overload
def query(
self,
expr: str,
/,
*,
raw: Literal[False] = False,
decode: DecodeOptions | None = None,
) -> Value: ...
@overload
def query(
self,
expr: str,
/,
*,
raw: Literal[True],
) -> RawResponse: ...
def query(
self,
expr: str,
/,
*,
raw: bool = False,
decode: DecodeOptions | None = None,
) -> Value | RawResponse:
"""Execute a synchronous q expression.
Parameters
----------
expr : str
The q expression to evaluate remotely.
raw : bool, default=False
If True, returns a `RawResponse` stream instead of decoding.
decode : DecodeOptions | None, optional
Decoding options for this specific query, overriding connection defaults.
Returns
-------
Value | RawResponse
Decoded wrapper value or a file-like raw response if `raw=True`.
"""
...
class AsyncConnection:
"""Asynchronous connection capable of executing q IPC requests.
Parameters
----------
endpoint : Endpoint
Addressing and transport configuration.
options : DecodeOptions | None, optional
Default options to apply to decoded queried wrapper objects.
Thread Safety
-------------
**Not thread-safe.** Must be driven from a single async task. Use
:class:`AsyncPool` for concurrent access.
"""
def __init__(
self,
endpoint: Endpoint,
*,
options: DecodeOptions | None = None,
) -> None: ...
async def __aenter__(self) -> AsyncConnection: ...
async def __aexit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None: ...
async def close(self) -> None:
"""Close the underlying connection."""
...
@overload
async def query(
self,
expr: str,
/,
*,
raw: Literal[False] = False,
decode: DecodeOptions | None = None,
) -> Value: ...
@overload
async def query(
self,
expr: str,
/,
*,
raw: Literal[True],
) -> AsyncRawResponse: ...
async def query(
self,
expr: str,
/,
*,
raw: bool = False,
decode: DecodeOptions | None = None,
) -> Value | AsyncRawResponse:
"""Execute an asynchronous q expression.
Parameters
----------
expr : str
The q expression to evaluate remotely.
raw : bool, default=False
If True, returns a `AsyncRawResponse` stream instead of decoding.
decode : DecodeOptions | None, optional
Decoding options for this specific query, overriding connection defaults.
Returns
-------
Value | AsyncRawResponse
Decoded wrapper value or a file-like raw response if `raw=True`.
"""
...
class Pool:
"""Synchronous connection pool for issuing q IPC requests.
Parameters
----------
endpoint : Endpoint
Addressing and transport configuration.
options : DecodeOptions | None, optional
Default options to apply to decoded queried wrapper objects.
pool : PoolOptions | None, optional
Pool lifecycle and retry configuration.
Thread Safety
-------------
**Thread-safe.** Designed for multi-threaded use each call checks out a
connection, uses it, and returns it to the pool automatically.
"""
def __init__(
self,
endpoint: Endpoint,
*,
options: DecodeOptions | None = None,
pool: PoolOptions | None = None,
) -> None: ...
def __enter__(self) -> Pool: ...
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None: ...
def close(self) -> None:
"""Close the pool and reject future checkouts."""
...
def prewarm(self) -> PoolMetrics:
"""Create and validate idle connections ahead of the next query."""
...
def metrics(self) -> PoolMetrics:
"""Return a snapshot of occupancy, configuration, and lifecycle state."""
...
@overload
def query(
self,
expr: str,
/,
*,
raw: Literal[False] = False,
decode: DecodeOptions | None = None,
) -> Value: ...
@overload
def query(
self,
expr: str,
/,
*,
raw: Literal[True],
) -> RawResponse: ...
def query(
self,
expr: str,
/,
*,
raw: bool = False,
decode: DecodeOptions | None = None,
) -> Value | RawResponse:
"""Execute a pooled synchronous q expression.
Parameters
----------
expr : str
The q expression to evaluate remotely.
raw : bool, default=False
If True, returns a `RawResponse` stream instead of decoding.
decode : DecodeOptions | None, optional
Decoding options for this specific query, overriding connection defaults.
Returns
-------
Value | RawResponse
Decoded wrapper value or a file-like raw response if `raw=True`.
"""
...
class AsyncPool:
"""Asynchronous connection pool for issuing q IPC requests.
Parameters
----------
endpoint : Endpoint
Addressing and transport configuration.
options : DecodeOptions | None, optional
Default options to apply to decoded queried wrapper objects.
pool : PoolOptions | None, optional
Pool lifecycle and retry configuration.
Thread Safety
-------------
**Thread-safe.** Designed for concurrent use across multiple async tasks.
"""
def __init__(
self,
endpoint: Endpoint,
*,
options: DecodeOptions | None = None,
pool: PoolOptions | None = None,
) -> None: ...
async def __aenter__(self) -> AsyncPool: ...
async def __aexit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None: ...
async def close(self) -> None:
"""Close the pool and reject future checkouts."""
...
async def prewarm(self) -> PoolMetrics:
"""Create and validate idle connections ahead of the next query."""
...
async def metrics(self) -> PoolMetrics:
"""Return a snapshot of occupancy, configuration, and lifecycle state."""
...
@overload
async def query(
self,
expr: str,
/,
*,
raw: Literal[False] = False,
decode: DecodeOptions | None = None,
) -> Value: ...
@overload
async def query(
self,
expr: str,
/,
*,
raw: Literal[True],
) -> AsyncRawResponse: ...
async def query(
self,
expr: str,
/,
*,
raw: bool = False,
decode: DecodeOptions | None = None,
) -> Value | AsyncRawResponse:
"""Execute a pooled asynchronous q expression.
Parameters
----------
expr : str
The q expression to evaluate remotely.
raw : bool, default=False
If True, returns a `AsyncRawResponse` stream instead of decoding.
decode : DecodeOptions | None, optional
Decoding options for this specific query, overriding connection defaults.
Returns
-------
Value | AsyncRawResponse
Decoded wrapper value or a file-like raw response if `raw=True`.
"""
...

View file

@ -0,0 +1,416 @@
from __future__ import annotations
import enum
from qroissant._values import Attribute, Primitive, Shape
class Endpoint:
"""Connection destination configuration for a q process.
Notes
-----
An endpoint describes how to connect to a q process, including the transport
protocol (TCP or Unix socket), address, and authentication credentials.
"""
@staticmethod
def tcp(
host: str,
port: int,
*,
username: str | None = None,
password: str | None = None,
timeout_ms: int | None = None,
) -> Endpoint:
"""Create a TCP endpoint configuration.
Parameters
----------
host : str
Hostname or IP address of the q process.
port : int
TCP port exposed by the q process.
username : str | None, optional
Username used during the q IPC handshake.
password : str | None, optional
Password used during the q IPC handshake.
timeout_ms : int | None, optional
Connection timeout in milliseconds.
Returns
-------
Endpoint
TCP endpoint configuration.
"""
...
@staticmethod
def unix(
path: str,
*,
username: str | None = None,
password: str | None = None,
timeout_ms: int | None = None,
) -> Endpoint:
"""Create a Unix-domain socket endpoint configuration.
Parameters
----------
path : str
Filesystem path to the q Unix domain socket.
username : str | None, optional
Username used during the q IPC handshake.
password : str | None, optional
Password used during the q IPC handshake.
timeout_ms : int | None, optional
Connection timeout in milliseconds.
Returns
-------
Endpoint
Unix domain socket endpoint configuration.
"""
...
@property
def scheme(self) -> str:
"""The transport scheme ('tcp' or 'unix')."""
...
@property
def host(self) -> str | None:
"""The hostname, if applicable."""
...
@property
def port(self) -> int | None:
"""The port, if applicable."""
...
@property
def path(self) -> str | None:
"""The socket path, if applicable."""
...
@property
def username(self) -> str | None:
"""The configured username."""
...
@property
def password(self) -> str | None:
"""The configured password."""
...
@property
def timeout_ms(self) -> int | None:
"""The connection timeout in milliseconds."""
...
class PoolOptions:
"""Connection pool configuration shared by sync and async pool types.
Parameters
----------
max_size : int, default=10
Maximum number of connections managed by the pool.
min_idle : int | None, optional
Minimum number of idle connections to retain when the pool is warmed.
checkout_timeout_ms : int, default=30000
Maximum time spent waiting for a pooled connection checkout.
idle_timeout_ms : int | None, optional
Maximum idle lifetime for an unused pooled connection.
max_lifetime_ms : int | None, optional
Maximum total lifetime for a pooled connection.
test_on_checkout : bool, default=True
Whether connections should be validated before they are handed out.
healthcheck_query : str | None, default="::"
Optional q expression used to validate live pooled connections.
Set to ``None`` to disable active q health checks.
retry_attempts : int, default=0
Number of retry attempts after the initial pooled query failure.
retry_backoff_ms : int, default=0
Delay between retry attempts, expressed in milliseconds.
"""
def __init__(
self,
*,
max_size: int = 10,
min_idle: int | None = None,
checkout_timeout_ms: int = 30_000,
idle_timeout_ms: int | None = None,
max_lifetime_ms: int | None = None,
test_on_checkout: bool = True,
healthcheck_query: str | None = "::",
retry_attempts: int = 0,
retry_backoff_ms: int = 0,
) -> None: ...
@property
def max_size(self) -> int:
"""Configured maximum number of connections managed by the pool."""
...
@property
def min_idle(self) -> int | None:
"""Configured minimum number of idle connections to retain."""
...
@property
def checkout_timeout_ms(self) -> int:
"""Configured maximum wait time for a connection checkout, in milliseconds."""
...
@property
def idle_timeout_ms(self) -> int | None:
"""Configured maximum idle lifetime for an unused connection, in milliseconds."""
...
@property
def max_lifetime_ms(self) -> int | None:
"""Configured maximum total lifetime for a connection, in milliseconds."""
...
@property
def test_on_checkout(self) -> bool:
"""Whether connections are validated before being handed out."""
...
@property
def healthcheck_query(self) -> str | None:
"""q expression used to validate live pooled connections, or ``None`` to disable."""
...
@property
def retry_attempts(self) -> int:
"""Number of retry attempts after the initial pooled query failure."""
...
@property
def retry_backoff_ms(self) -> int:
"""Delay between retry attempts, in milliseconds."""
...
class SymbolInterpretation(enum.Enum):
"""Arrow representation used for q symbols."""
UTF8 = ...
LARGE_UTF8 = ...
UTF8_VIEW = ...
DICTIONARY = ...
RAW_BYTES = ...
class ListInterpretation(enum.Enum):
"""Arrow representation used for q lists."""
LIST = ...
LARGE_LIST = ...
LIST_VIEW = ...
class StringInterpretation(enum.Enum):
"""Arrow representation used for q char data."""
UTF8 = ...
BINARY = ...
class UnionMode(enum.Enum):
"""Arrow union representation used for mixed general lists."""
DENSE = ...
SPARSE = ...
class DecodeOptions:
"""Deserialization and Arrow conversion options.
Notes
-----
Construct instances through :meth:`builder` and finish with
:meth:`DecodeOptionsBuilder.build`.
"""
@staticmethod
def builder() -> DecodeOptionsBuilder:
"""Create a builder initialized with qroissant's default options."""
...
@property
def list_interpretation(self) -> ListInterpretation:
"""Arrow container type used when projecting q lists."""
...
@property
def union_mode(self) -> UnionMode:
"""Arrow union encoding used for mixed general lists."""
...
@property
def string_interpretation(self) -> StringInterpretation:
"""Arrow type used when projecting q char vectors."""
...
@property
def symbol_interpretation(self) -> SymbolInterpretation:
"""Arrow type used when projecting q symbol vectors and atoms."""
...
@property
def assume_symbol_utf8(self) -> bool:
"""Whether q symbols are assumed to be valid UTF-8."""
...
@property
def parallel(self) -> bool:
"""Whether table columns are decoded in parallel using multiple threads."""
...
@property
def preserve_original_body(self) -> bool:
"""Whether the raw IPC payload bytes are retained on the decoded value."""
...
@property
def validate_compressed_trailing_bytes(self) -> bool:
"""Whether trailing zero bytes after LZW-decompressed output are validated."""
...
@property
def temporal_nulls(self) -> bool:
"""Whether temporal null sentinels are mapped to ``None`` in Arrow arrays."""
...
@property
def treat_infinity_as_null(self) -> bool:
"""Whether ±∞ sentinels are mapped to ``None`` in Arrow arrays."""
...
class DecodeOptionsBuilder:
"""Builder for :class:`DecodeOptions`."""
def with_list_interpretation(
self, value: ListInterpretation, /
) -> DecodeOptionsBuilder:
"""Set the Arrow container type for q list projection."""
...
def with_union_mode(self, value: UnionMode, /) -> DecodeOptionsBuilder:
"""Set the Arrow union encoding for mixed general lists."""
...
def with_string_interpretation(
self, value: StringInterpretation, /
) -> DecodeOptionsBuilder:
"""Set the Arrow type for q char vector projection."""
...
def with_symbol_interpretation(
self, value: SymbolInterpretation, /
) -> DecodeOptionsBuilder:
"""Set the Arrow type for q symbol projection."""
...
def with_assume_symbol_utf8(self, value: bool, /) -> DecodeOptionsBuilder:
"""Set whether q symbols are assumed to be valid UTF-8."""
...
def with_parallel(self, value: bool, /) -> DecodeOptionsBuilder:
"""Set whether table columns are decoded in parallel."""
...
def with_preserve_original_body(self, value: bool, /) -> DecodeOptionsBuilder:
"""Set whether the raw IPC payload bytes are retained on decoded values."""
...
def with_validate_compressed_trailing_bytes(
self, value: bool, /
) -> DecodeOptionsBuilder:
"""Set whether trailing zero bytes after LZW decompression are validated."""
...
def with_temporal_nulls(self, value: bool, /) -> DecodeOptionsBuilder:
"""Set whether temporal null sentinels are mapped to ``None`` in Arrow arrays."""
...
def with_treat_infinity_as_null(self, value: bool, /) -> DecodeOptionsBuilder:
"""Set whether ±∞ sentinels are mapped to ``None`` in Arrow arrays."""
...
def build(self) -> DecodeOptions:
"""Finalize the builder into an immutable :class:`DecodeOptions` instance."""
...
class EncodeField:
"""q serialization hints for a single Arrow value or table column."""
@staticmethod
def builder() -> EncodeFieldBuilder:
"""Create a builder initialized with empty serialization hints."""
...
@property
def primitive(self) -> Primitive | None:
"""Forced q primitive type for this field, or ``None`` to infer."""
...
@property
def shape(self) -> Shape | None:
"""Forced q structural shape for this field, or ``None`` to infer."""
...
@property
def attribute(self) -> Attribute | None:
"""q attribute to apply to this field, or ``None`` for no attribute."""
...
@property
def sorted(self) -> bool | None:
"""Whether this field is sorted, or ``None`` to infer from the attribute."""
...
class EncodeFieldBuilder:
"""Builder for :class:`EncodeField`."""
def with_primitive(self, value: Primitive, /) -> EncodeFieldBuilder:
"""Force the q primitive type for this field."""
...
def with_shape(self, value: Shape, /) -> EncodeFieldBuilder:
"""Force the q structural shape for this field."""
...
def with_attribute(self, value: Attribute, /) -> EncodeFieldBuilder:
"""Set the q attribute to apply to this field."""
...
def with_sorted(self, value: bool, /) -> EncodeFieldBuilder:
"""Set whether this field is sorted."""
...
def build(self) -> EncodeField:
"""Finalize the builder into immutable per-field encoding hints."""
...
class EncodeOptions:
"""Encoding options for Arrow-backed :func:`qroissant.encode` calls.
Notes
-----
qroissant resolves Arrow inputs in the following order:
1. qroissant metadata embedded on the Arrow field or schema
2. per-field overrides attached through :meth:`EncodeOptionsBuilder.with_field`
3. global defaults on :class:`EncodeOptions`
4. generic Arrow type inference
"""
@staticmethod
def builder() -> EncodeOptionsBuilder:
"""Create a builder initialized with qroissant's default encoding policy."""
...
@property
def primitive(self) -> Primitive | None:
"""Global fallback q primitive type, or ``None`` to infer per-field."""
...
@property
def shape(self) -> Shape | None:
"""Global fallback q structural shape, or ``None`` to infer per-field."""
...
@property
def attribute(self) -> Attribute | None:
"""Global fallback q attribute, or ``None`` for no attribute."""
...
@property
def strict(self) -> bool:
"""Whether unknown Arrow types raise an error instead of being inferred."""
...
def field(self, name: str, /) -> EncodeField | None:
"""Return per-field encoding hints for the given column name, if any."""
...
class EncodeOptionsBuilder:
"""Builder for :class:`EncodeOptions`."""
def with_primitive(self, value: Primitive, /) -> EncodeOptionsBuilder:
"""Set the global fallback q primitive type."""
...
def with_shape(self, value: Shape, /) -> EncodeOptionsBuilder:
"""Set the global fallback q structural shape."""
...
def with_attribute(self, value: Attribute, /) -> EncodeOptionsBuilder:
"""Set the global fallback q attribute."""
...
def with_strict(self, value: bool, /) -> EncodeOptionsBuilder:
"""Set whether unknown Arrow types raise an error instead of being inferred."""
...
def with_field(
self, name: str, field: EncodeField, /
) -> EncodeOptionsBuilder:
"""Attach per-field encoding hints for the given column name."""
...
def build(self) -> EncodeOptions:
"""Finalize the builder into immutable Arrow-to-q encoding options."""
...

View file

@ -0,0 +1,24 @@
class QroissantError(Exception):
"""Base class for qroissant-specific failures."""
class DecodeError(QroissantError):
"""Raised when q IPC payload decoding fails."""
class ProtocolError(QroissantError):
"""Raised when q IPC framing or message validation fails."""
class TransportError(QroissantError):
"""Raised when transport IO or socket operations fail."""
class OperationError(QroissantError):
"""Raised when a qroissant operation is unsupported."""
class QRuntimeError(QroissantError):
"""Raised when the remote q process returns an error response."""
class PoolError(QroissantError):
"""Raised when connection pool management fails."""
class PoolClosedError(PoolError):
"""Raised when a closed connection pool is used."""

View file

@ -0,0 +1,43 @@
from __future__ import annotations
import enum
class Encoding(enum.Enum):
"""Endianness of the q IPC message payload."""
LITTLE_ENDIAN = ...
BIG_ENDIAN = ...
class Compression(enum.Enum):
"""Compression mode of the q IPC message payload."""
UNCOMPRESSED = ...
COMPRESSED = ...
COMPRESSED_LARGE = ...
class MessageType(enum.Enum):
"""IPC message type tag."""
ASYNCHRONOUS = ...
SYNCHRONOUS = ...
RESPONSE = ...
class MessageHeader:
"""Header information extracted from a q IPC frame."""
@property
def encoding(self) -> Encoding:
"""The endianness of the payload."""
...
@property
def message_type(self) -> MessageType:
"""The message type tag."""
...
@property
def compression(self) -> Compression:
"""The compression mode."""
...
@property
def size(self) -> int:
"""The total size of the message frame in bytes."""
...

View file

@ -0,0 +1,67 @@
from __future__ import annotations
import enum
class RowDisplay(enum.Enum):
"""Row selection strategy used by qroissant repr formatting."""
HEAD = ...
HEAD_TAIL = ...
class FormattingOptions:
"""Formatting options for user-facing qroissant string representations.
Notes
-----
These options control how qroissant values render through :func:`str` and
:func:`repr`. Apply them process-wide through
:func:`qroissant.set_formatting_options`.
"""
@staticmethod
def builder() -> FormattingOptionsBuilder:
"""Create a builder initialized with qroissant's default formatting policy."""
...
@property
def max_rows(self) -> int:
"""Maximum number of rows displayed in table repr."""
...
@property
def max_columns(self) -> int:
"""Maximum number of columns displayed in table repr."""
...
@property
def row_display(self) -> RowDisplay:
"""Row selection strategy used when the row limit is exceeded."""
...
class FormattingOptionsBuilder:
"""Builder for :class:`FormattingOptions`."""
def with_max_rows(self, value: int, /) -> FormattingOptionsBuilder:
"""Set the maximum number of rows displayed in table repr."""
...
def with_max_columns(self, value: int, /) -> FormattingOptionsBuilder:
"""Set the maximum number of columns displayed in table repr."""
...
def with_row_display(self, value: RowDisplay, /) -> FormattingOptionsBuilder:
"""Set the row selection strategy used when the row limit is exceeded."""
...
def build(self) -> FormattingOptions:
"""Finalize the builder into immutable repr formatting options."""
...
def get_formatting_options() -> FormattingOptions:
"""Get the current process-wide formatting options."""
...
def set_formatting_options(options: FormattingOptions, /) -> None:
"""Set the process-wide formatting options."""
...
def reset_formatting_options() -> None:
"""Reset the formatting options to their default values."""
...

View file

@ -0,0 +1,72 @@
from __future__ import annotations
from qroissant._config import DecodeOptions, EncodeOptions
from qroissant._message import Compression, Encoding, MessageType
from qroissant._values import Value
def decode(
payload: object,
/,
*,
options: DecodeOptions | None = None,
) -> Value:
"""Decode an IPC payload into a typed qroissant value.
Parameters
----------
payload : object
Raw q IPC payload as ``bytes``, a read-only contiguous buffer,
or an object exposing such a buffer via ``.data``.
options : DecodeOptions | None, optional
Decoding and Arrow projection options. When omitted, the default
qroissant options are used.
Returns
-------
Value
Decoded q object represented by qroissant wrapper types.
Raises
------
DecodeError
Raised when the IPC payload cannot be decoded into a valid q value.
ProtocolError
Raised when the frame header is malformed or unsupported.
"""
...
def encode(
value: object,
/,
*,
options: EncodeOptions | None = None,
encoding: Encoding = Encoding.LITTLE_ENDIAN,
message_type: MessageType = MessageType.ASYNCHRONOUS,
compression: Compression = Compression.UNCOMPRESSED,
) -> bytes:
"""Encode a qroissant value into q IPC bytes.
Parameters
----------
value : object
A qroissant wrapper value, ``None`` for q null, any object exposing a
compatible ``serialize`` method, or an object implementing the Arrow
PyCapsule interface.
options : EncodeOptions | None, optional
Arrow-to-q encoding hints applied when ``value`` is encoded
from an Arrow array or stream.
encoding : Encoding, default=Encoding.LITTLE_ENDIAN
Endianness used in the generated IPC payload.
message_type : MessageType, default=MessageType.ASYNCHRONOUS
IPC message type tag written into the frame header.
compression : Compression, default=Compression.UNCOMPRESSED
Compression mode for payload encoding.
Returns
-------
bytes
Encoded q IPC payload.
"""
...

View file

@ -0,0 +1,234 @@
from __future__ import annotations
import enum
from collections.abc import Iterator
from qroissant._config import EncodeOptions
from qroissant._message import Compression, Encoding, MessageType
class Attribute(enum.Enum):
"""q attribute applied to a value (e.g., sorted, unique, parted, grouped)."""
NONE = ...
SORTED = ...
UNIQUE = ...
PARTED = ...
GROUPED = ...
class Shape(enum.Enum):
"""Structural shape of the q value."""
ATOM = ...
VECTOR = ...
LIST = ...
DICTIONARY = ...
TABLE = ...
UNARY_PRIMITIVE = ...
class Primitive(enum.Enum):
"""Underlying primitive domain of the q value."""
BOOLEAN = ...
GUID = ...
BYTE = ...
SHORT = ...
INT = ...
LONG = ...
REAL = ...
FLOAT = ...
CHAR = ...
SYMBOL = ...
TIMESTAMP = ...
MONTH = ...
DATE = ...
DATETIME = ...
TIMESPAN = ...
MINUTE = ...
SECOND = ...
TIME = ...
MIXED = ...
class Type:
"""Type descriptor for a qroissant value."""
@property
def primitive(self) -> Primitive | None:
"""The underlying q primitive, or None if mixed."""
...
@property
def shape(self) -> Shape:
"""The structural shape of the value."""
...
@property
def attribute(self) -> Attribute | None:
"""The q attribute applied to the value, if any."""
...
@property
def sorted(self) -> bool | None:
"""Whether the value is sorted."""
...
class Value:
"""Base class for decoded qroissant wrapper objects."""
@property
def qtype(self) -> Type:
"""The full q type descriptor."""
...
@property
def primitive(self) -> Primitive | None:
"""The underlying q primitive, or None if mixed."""
...
@property
def shape(self) -> Shape:
"""The structural shape of the value."""
...
@property
def attribute(self) -> Attribute | None:
"""The q attribute applied to the value, if any."""
...
def serialize(
self,
*,
options: EncodeOptions | None = None,
encoding: Encoding = ...,
message_type: MessageType = ...,
compression: Compression = ...,
) -> bytes:
"""Serialize the value into a q IPC frame.
Parameters
----------
options : EncodeOptions | None, optional
Arrow-to-q encoding hints. When omitted, the default encoding
policy is used.
encoding : Encoding, default=Encoding.LITTLE_ENDIAN
Endianness of the generated IPC payload.
message_type : MessageType, default=MessageType.ASYNCHRONOUS
IPC message type tag written into the frame header.
compression : Compression, default=Compression.UNCOMPRESSED
Compression mode applied to the payload.
Returns
-------
bytes
Encoded q IPC payload.
"""
...
class Atom(Value):
"""Scalar q value (e.g., integer, float, symbol)."""
def as_py(self) -> object:
"""Convert the atom to a native Python type."""
...
@property
def value(self) -> object:
"""The atom's native Python value (equivalent to ``as_py()``)."""
...
def is_null(self) -> bool:
"""Return ``True`` if this atom holds the q null sentinel for its type."""
...
def is_infinite(self) -> bool:
"""``True`` if this atom is a q infinity sentinel (±∞)."""
...
def __arrow_c_array__(
self, requested_schema: object | None = None, /
) -> object:
"""Export the atom as an Arrow array via the PyCapsule Protocol."""
...
def __repr__(self) -> str: ...
def __str__(self) -> str: ...
class Vector(Value):
"""Homogeneous q list of primitive values."""
def __len__(self) -> int:
"""Return the length of the vector."""
...
def __iter__(self) -> Iterator[object]:
"""Iterate over the elements of the vector."""
...
def __getitem__(self, index: int, /) -> object:
"""Get an element by index."""
...
def to_list(self) -> list[object]:
"""Convert the vector to a Python list."""
...
def __arrow_c_array__(
self, requested_schema: object | None = None, /
) -> object:
"""Export the vector as an Arrow array via the PyCapsule Protocol."""
...
def __repr__(self) -> str: ...
def __str__(self) -> str: ...
class List(Value):
"""Heterogeneous/mixed q list of general values."""
def __len__(self) -> int:
"""Return the length of the list."""
...
def __iter__(self) -> Iterator[Value]:
"""Iterate over the elements of the list."""
...
def __getitem__(self, index: int, /) -> Value:
"""Get an element by index."""
...
def to_list(self) -> list[Value]:
"""Convert the list to a Python list of values."""
...
def __arrow_c_array__(
self, requested_schema: object | None = None, /
) -> object:
"""Export the list as an Arrow array via the PyCapsule Protocol."""
...
def __repr__(self) -> str: ...
def __str__(self) -> str: ...
class Dictionary(Value):
"""q dictionary mapping keys to values."""
@property
def keys(self) -> Value:
"""The dictionary keys."""
...
@property
def values(self) -> Value:
"""The dictionary values."""
...
def __len__(self) -> int:
"""Return the number of key-value pairs."""
...
def __arrow_c_array__(
self, requested_schema: object | None = None, /
) -> object:
"""Export the dictionary as an Arrow StructArray via the PyCapsule Protocol."""
...
def __repr__(self) -> str: ...
def __str__(self) -> str: ...
class Table(Value):
"""q table representing tabular data."""
@property
def columns(self) -> list[str]:
"""The column names."""
...
@property
def num_rows(self) -> int:
"""The number of rows."""
...
@property
def num_columns(self) -> int:
"""The number of columns."""
...
def column(self, name: str, /) -> Value:
"""Get a column by name."""
...
def __arrow_c_stream__(
self, requested_schema: object | None = None, /
) -> object:
"""Export the table as an Arrow stream via the PyCapsule Protocol."""
...
def __repr__(self) -> str: ...
def __str__(self) -> str: ...

View file

@ -0,0 +1 @@