Serialize and deserialize almost anything easily.
Project description
Packify
This is a simple package that allows one to serialize and deserialize practically any data structure to and from bytes.
Installation
pip install packify
Status
Primary development is complete. Further development will be tracked in the issues. Historical changes can be found in the changelog.
Usage
Usage is simple: import the package and call the pack/unpack functions.
from packify import pack, unpack
from decimal import Decimal
data = {
123: 432.1,
"abc": "cba",
b"abc": b"cba",
"None": None,
"true": True,
"false": False,
'list': [
'123',
123,
b'123',
True,
],
'tuple': (
'123',
123,
b'123',
False,
),
'set': {
'123',
123,
b'123',
},
'Decimal': Decimal('123.321'),
}
packed = pack(data)
unpacked = unpack(packed)
assert type(packed) is bytes
assert unpacked == data
The following types are supported:
- int
- bool
- float
- Decimal
- str
- bytes
- bytearray
- NoneType
- list
- tuple
- set
- dict
Using with named tuples
If you want to use named tuples, you can do so by packing as a regular tuple and then unpacking it into the named tuple class.
from packify import pack, unpack
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
original = Point(1, 2)
packed = pack(tuple(original))
unpacked = Point(*unpack(packed))
assert unpacked == original
The recursive features of pack and unpack will not work with named tuples
nested within data structures. Using a Packable implementation is a better
approach if you need custom data types nested within data structures (see below).
Additionally, a simple duck-type interface/protocol, Packable, is included.
Any more complex data structure can be handled if it implements the Packable
interface. Packable is defined as follows:
@runtime_checkable
class Packable(Protocol):
def pack(self) -> bytes:
"""Packs the instance into bytes."""
...
@classmethod
def unpack(cls, data: bytes, /, *, inject: dict = {}) -> Packable:
"""Unpacks an instance from bytes. Must accept dependency
injection to unpack other Packable types.
"""
...
If a class that implements Packable is used, then it needs to be included in
the inject parameter for calls to unpack.
Example
from dataclasses import dataclass, field
from packify import pack, unpack
@dataclass
class Thing:
data: str = field()
amount: int = field()
fraction: float = field()
parts: list = field()
def __eq__(self, other) -> bool:
return type(self) is type(other) and self.pack() == other.pack()
def pack(self) -> bytes:
return pack((self.data, self.amount, self.fraction, self.parts))
@classmethod
def unpack(cls, data: bytes, /, *, inject: dict = {}):
return cls(*unpack(data, inject={**globals(), **inject}))
thing = Thing("hello world", 123, 420.69, ['a', b'b', 3])
packed = pack(thing)
unpacked = unpack(packed, inject={'Thing': Thing})
assert unpacked == thing
# alternately, the easier but less specific method is to copy globals
unpacked = unpack(packed, inject={**globals()})
assert unpacked == thing
As long as the class implements the Packable protocol, it can be included in
lists, sets, tuples, and dicts (assuming it is hashable for set or to be used as
a dict key), and it will just work.
The pack function will raise a UsageError if the data is not serializable,
and the unpack function will raise a UsageError if it is unable to find a
Packable class to unpack the relevant item.
For convenience/use in annotations, a SerializableType is exported which
includes the above type information.
Additional documentation can be found in dox.md, which was generated automagically by autodox.
CLI
The packify package includes a CLI for exporting the agent skill to various AI
coding environments:
# Print skill to stdout
packify skill
# Save skill to a specific directory
packify skill --output path/to/skills
# Install skill for specific AI tools
packify opencode # .opencode/skills/packify/SKILL.md
packify claude # .claude/skills/packify/SKILL.md
packify cursor # .cursor/skills/packify/SKILL.md
packify codex # .agents/skills/packify/SKILL.md
This makes the packify skill available to AI agents so they can understand and use the library effectively.
More Resources
Check out the Pycelium discord server. If you experience a problem, please discuss it on the Discord server. All suggestions for improvement are also welcome, and the best place for that is also Discord. If you experience a bug and do not use Discord, open an issue on Github.
Tests
Since it is a focused package, there are only 15 tests, and they consist of e2e
tests of both the pack and unpack functions, a few tests covering reported
bugs, and 2 fuzz tests to broaden the coverage of the test suite added after the
v0.3.0 refactor. To run the tests, clone the repository and use the following:
python tests/test_serialization.py
python tests/test_fuzzy.py
License
Copyright (c) 2026 Jonathan Voss (k98kurz)
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file packify-0.3.3.tar.gz.
File metadata
- Download URL: packify-0.3.3.tar.gz
- Upload date:
- Size: 9.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
49746701fde5d3552c88fb524508ec2be6a38f0dbb890933ae7893b4aac76a27
|
|
| MD5 |
7d8a404e9597cc362fbaa457ae08354f
|
|
| BLAKE2b-256 |
f526b8a82f871c9b55bb5a2294e69f541f5f2de5ffa5406ab75ef6478d7d927f
|
File details
Details for the file packify-0.3.3-py3-none-any.whl.
File metadata
- Download URL: packify-0.3.3-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cee79febbe493a5acffcbcf6ded9ed62765ad3bff1d7d62111ffeaecef8b6897
|
|
| MD5 |
97e428939e50876ac15400b313b5c266
|
|
| BLAKE2b-256 |
55bef6bee9715b331579d2cb09c1b11bcb6cd3da581a31ea788270baebd2f14d
|