cucumber is a module that handles serialization and deserialization of Python objects.
Basically any object in Python will work, and it covers more types than pickle, cloudpickle, and dill combined.
cloudpickle and dill__main__To see a list of supported types, see the supported types page.
To see how stacks up against other serialization libraries, see the performance page.
is mainly meant for internal, cross-process communication, not for external or cross-language serialization.
However, you can convert the intermediate representation (IR) to JSON, and you are welcome to use that to send data to other languages using your own tools.
from suitkaise import cucumber
from suitkaise .cucumber import serialize , deserialize , serialize_ir , deserialize_ir , ir_to_jsonable , ir_to_json , to_jsonable , to_json , reconnect_all
serialize ()Serializes any Python object to bytes using 's intermediate representation (IR).
data = cucumber .serialize (obj)
Arguments
obj: Any Python object
Anydebug: Enables deep error context and path reporting.
bool = Falseverbose: Prints progress and handler selection information.
bool = FalseReturns
bytes: IR as bytes.
Raises
: If serialization fails.
This is a that appears when you try to serialize a point.
Traceback (most recent call last):
File "my_app.py", line 42, in <module>
payload = cucumber .serialize (obj)
File ".../suitkaise/cucumber/api.py", line 90, in serialize
return _default_serializer.serialize (obj)
File ".../suitkaise/cucumber/_int/serializer.py", line 113, in serialize
raise SerializationError (message)
suitkaise .cucumber ._int.serializer.SerializationError :
======================================================================
HANDLER FAILED
======================================================================
Path: Anchor
Handler: ClassInstanceHandler
Object: Anchor
The handler failed to extract state from this object.
Error: Locked pipe endpoint cannot be serialized. Keep it in the parent process.
======================================================================
debug and verboseNote: debug and verbose are keyword-only arguments.
When debug=True, shows you where it failed to serialize an object.
======================================================================
HANDLER FAILED
======================================================================
Path: Anchor@1234567890
Handler: ClassInstanceHandler
Object: Anchor
The handler failed to extract state from this object.
Error: Locked pipe endpoint cannot be serialized. Keep it in the parent process.
======================================================================
When verbose=True, prints the path it's taking through your object, color-coded by depth.
[CUCUMBER] Starting serialization of dict
[1] dict
[2] dict → Widget
↳ Handler: ClassInstanceHandler
[3] dict → Widget → dict
[4] dict → Widget → dict → dict
[5] dict → Widget → dict → dict → list
[5] dict → Widget → dict → dict → dict
[4] dict → Widget → dict → dict
[5] dict → Widget → dict → dict → tuple
[2] dict → dict
[3] dict → dict → list
[2] dict → list
[3] dict → list → dict
[4] dict → list → dict → set
[3] dict → list → tuple
[CUCUMBER] Built IR successfully, size: 1464 chars
[CUCUMBER] Serialization complete, bytes: 760
[5] dict → Widget → dict → dict → tuple colors:
dict is redWidget is orangedict is yellowdict is greentuple is blueColors will only display if your terminal supports color.
deserialize ()Reconstructs a Python object from bytes created by .
Will not work if the object was serialized with pickle, cloudpickle, or dill, as these libraries do not use 's IR.
Reconnector objects are returned for certain typesdata = cucumber .serialize (obj)
restored = cucumber .deserialize (data)
Arguments
data: Serialized bytes from .
bytesdebug: Enables deep error context and path reporting.
bool = Falseverbose: Prints progress and handler selection information.
bool = FalseReturns
obj: Reconstructed Python object.
AnyRaises
: If deserialization/reconstruction fails.
This is a that appears when you try to deserialize an object that is missing a required key.
Traceback (most recent call last):
File "my_app.py", line 44, in <module>
restored = cucumber .deserialize (data)
File ".../suitkaise/cucumber/api.py", line 177, in deserialize
return _default_deserializer.deserialize (data)
File ".../suitkaise/cucumber/_int/deserializer.py", line 88, in deserialize
raise DeserializationError (message)
suitkaise .cucumber ._int.deserializer.DeserializationError :
======================================================================
DESERIALIZATION FAILED
======================================================================
Path: Payload -> 1 -> state
Handler: ClassInstanceHandler
Object: dict
The handler failed to reconstruct this object.
Error: Missing key 'state' for class reconstruction
======================================================================
reconnect_all () and ReconnectorsReconnector objects are returned for certain types when you deserialize an object.
These objects are placeholders for certain objects that cannot be directly serialized and deserialized for various reasons.
DbReconnector --> database connectionsSocketReconnector --> network socketsPipeReconnector --> OS pipes (not suitkaise .processing .Pipe objects)ThreadReconnector --> threadsSubprocessReconnector --> subprocessesMatchReconnector --> compiled regex matchesEach Reconnector has a reconnect() method that creates a new live resource, using stored metadata. If the resource requires authentication, you must provide it again. We do not store secrets in the IR for security reasons.
For more information on each Reconnector, see the how it works page.
allows you to reconnect all Reconnectors in an object at once.
Arguments
obj: Object or container to traverse for Reconnectors.
Anystart_threads: Auto-start reconnected threads.
bool = False**auth: Mapping of type key to secrets (authentication).
dict[str, dict[str, str]]{} (no auth)Returns
obj: Object with all Reconnectors replaced by live resources.
AnyRaises
reconnect_all () swallows reconnect errors and keeps the original Reconnector in place if reconnect fails.**auth**auth is a mapping of type key to secrets (authentication).
Type keys are the actual connection types (module.ClassName strings).
"psycopg2.Connection", "redis.Redis", ...
Each of these type keys maps to a dict.
"*" to provide the default authentication for all instances of that typeauth = {
"psycopg2.Connection": {
"*": "default_psycopg2_password",
"analytics_db": "analytics_password" # used for obj.analytics_db specifically
},
"redis.Redis": {
"*": "default_redis_password"
}
}
restored = cucumber .deserialize (data)
restored = cucumber .reconnect_all (restored, start_threads=True, **auth)
If no auth is provided for a reconnector, reconnect() and are still called.
This is fine in most cases unless you are using database connections that require authentication (a password, token, ...).
DbReconnector supported database typespsycopg2.Connection (PostgreSQL / psycopg2): auth requiredpsycopg.Connection (PostgreSQL / psycopg3): auth requiredpymysql.Connection (MySQL / PyMySQL): auth requiredmysql.connector.connection.MySQLConnection (MySQL / mysql-connector): auth requiredmariadb.Connection (MariaDB): auth requiredsqlite3.Connection (SQLite): no auth (file/":memory:" path)pymongo.MongoClient (MongoDB): auth required for protected deploymentsredis.Redis (Redis): auth required for protected deploymentssqlalchemy.Engine (SQLAlchemy): auth required if the URL requires itcassandra.Cluster (Cassandra): auth required for protected deploymentselasticsearch.Elasticsearch (Elasticsearch): auth required for protected deploymentsneo4j.Driver (Neo4j): auth requiredinfluxdb_client.InfluxDBClient (InfluxDB): auth required (token)pyodbc.Connection (ODBC): auth requiredclickhouse_driver.Client (ClickHouse): auth required for protected deploymentspymssql.Connection (MS SQL Server): auth requiredoracledb.Connection (Oracle): auth requiredcx_Oracle.Connection (Oracle / cx_Oracle): auth requiredsnowflake.Connection (Snowflake): auth requiredduckdb.Connection (DuckDB): no auth (file/":memory:" path)serialize_ir () and deserializing an IR converts Python objects into an intermediate representation (IR) that is solely comprised of pickle native types. Then, pickle is used to serialize the IR to bytes.
{
"__cucumber_type__": "class_instance",
"__handler__": "ClassInstanceHandler",
"__object_id__": 140123456789232,
"module": "my_app.models",
"class_name": "User",
"state": {
"id": 1,
"name": "alice",
"roles": ["admin", "editor"],
}
}
serialize_ir ()Returns
the IR without converting to bytes.
Use this to inspect the IR of an object.
ir = cucumber .serialize_ir (obj)
Arguments
obj: Any Python object
Anydebug: Enables deep error context and path reporting.
bool = Falseverbose: Prints progress and handler selection information.
bool = FalseReturns
A pickle native IR (nested dict/list structure)
Raises
: If serialization fails.
In order to deserialize an IR, you must first convert it to bytes using pickle.dumps().
Generally, when serializing to an ir, you are doing it to inspect it, or directly work with it.
ir = cucumber .serialize_ir (obj)
data = pickle.dumps(ir)
restored = cucumber .deserialize_ir (ir)
Raises
: If deserialization fails.
provides 4 ways to convert an IR to JSON.
2 of them convert the IR to a JSON-serializable structure, and the other 2 convert the IR directly to a JSON string.
A JSON-serializable structure is a Python dict/list tree that only uses JSON-safe types (dict, list, str, int, float, bool, None).
A JSON string is the final serialized text output (the result of json.dumps()). The structure is useful if you want to inspect or modify the IR in Python before turning it into a string.
to_jsonable ()Serialize an object to IR and return a JSON-serializable structure.
jsonable = cucumber .to_jsonable (obj)
Arguments
obj: Any Python object to convert to IR before JSON conversion.
Anydebug: Enables deep error context and path reporting.
bool = Falseverbose: Prints progress and handler selection information.
bool = FalseReturns
Any: A JSON-serializable structure.
Raises
: If serialization fails.
to_json ()Serialize an object to IR and return a JSON string.
json_text = cucumber .to_json (obj)
Arguments
obj: Any Python object to convert to IR before JSON conversion.
Anyindent: The number of spaces to use for indentation.
int | None = 2sort_keys: Sort keys in the JSON output.
bool = Truedebug: Enables deep error context and path reporting.
bool = Falseverbose: Prints progress and handler selection information.
bool = FalseReturns
str: A JSON string.
Raises
: If serialization fails.
ir_to_jsonable ()Convert an IR to a JSON-serializable structure.
ir = cucumber .serialize_ir (obj)
jsonable = cucumber .ir_to_jsonable (ir)
Arguments
ir: The IR to convert.
AnyReturns
Any: A JSON-serializable structure.
Raises
: If conversion fails.
ir_to_json ()Convert an IR to a JSON string.
ir = cucumber .serialize_ir (obj)
json_text = cucumber .ir_to_json (ir)
Arguments
ir: The IR to convert.
Anyindent: The number of spaces to use for indentation.
int | None = 2sort_keys: Sort keys in the JSON output.
bool = TrueReturns
str: A JSON string.
Raises
: If conversion fails.
is meant to work solely within Python.
Here are the steps to convert a Python object to an object in another programming language:
cucumber .to_jsonable () (or directly to text using cucumber .to_json ()), then write it out.class Counter:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
def decrement(self):
self.count -= 1
counter = Counter()
jsonable = cucumber .to_jsonable (counter)
with open("counter.json", "w") as f:
json.dump(jsonable, f)
__cucumber_type__, __handler__) and map them to equivalent types or a custom schema.