Contributing
Thank you for your interest in contributing to Permafrost!
Environment setup
git clone https://github.com/caua-ferreira/permafrost-framework
cd permafrost-framework
pip install -e '.[dev]'
Running tests
# Full suite
pytest tests/ -v
# Specific test files
pytest tests/test_freeze_thaw.py -v
pytest tests/test_catalog.py -v
pytest tests/test_cluster.py -v
# With coverage
pytest tests/ --cov=src/permafrost --cov-report=html
Project structure
src/permafrost/
__init__.py # Public API exports
codec.py # freeze(), thaw(), audit(), predictors
catalog.py # PermafrostCatalog (DuckDB)
chunk_mode.py # freeze_stream(), freeze_file(), peek()
cli.py # CLI (typer + rich)
cluster.py # Master, Worker, Client
schema_detector.py # SchemaDetector, DataType
storage.py # Cloud storage adapters
crypto.py # AES-256-GCM encryption, KMS providers
context.py # PermafrostContext — unified high-level API
How to add a new codec
- Pick the next available
codec_idincodec.py - Implement
_compress_bytes()and_decompress_bytes()for the new codec - Add the constant
CODEC_MYCODEC = 0x0N - Export the constant in
__init__.py - Add to the name map in
audit() - Write tests in
tests/test_freeze_thaw.py
How to add a new StorageAdapter
- Create a class inheriting from
StorageAdapterinstorage.py - Implement all abstract methods (
upload,download,exists, etc.) - Add to the
storage_from_uri()factory with the new URI scheme - Export in
__init__.py - Add optional dependency in
pyproject.toml
PR process
- Fork + descriptive branch (
feat/zpaq-codec,fix/timestamp-encoding) - Code + tests (no regression on the existing test suite)
pytest tests/ -vmust pass completely- PR with description of what and why
SDK Stability & Versioning Policy
Permafrost follows Semantic Versioning 2.0.0.
What counts as the public API
Everything exported from permafrost.__all__ is public API:
freeze(),thaw(),audit(),freeze_to(),thaw_from(),audit_remote()freeze_file(),freeze_stream(),peek()PermafrostContext,PermafrostCatalogLocalAdapter,S3Adapter,GCSAdapter,AzureAdapterPermafrostMaster,PermafrostWorker,PermafrostClient- All constants:
CODEC_*,QUANT_*,PRED_*,MAGIC,EOF_MAGIC SchemaDetector,DataType,FieldKindKeyProvider,LocalKeyProvider,AWSKMSProvider,GCPKMSProviderSchemaEvolutionError,apply_schema_evolution,schema_diffCODEC_AUTO,DataProfile,auto_select,profile_dataframeAuthError,RBACManager,ClusterUser,generate_token,validate_token
Names prefixed with _ are internal and may change at any time.
Version policy
| Change type | Version bump | Example |
|---|---|---|
| New public function, parameter, or constant | MINOR (0.x) | Adding freeze_async() |
| Breaking change to existing public API | MAJOR (x.0.0) | Renaming thaw() parameter |
| Bug fix that doesn't break callers | PATCH (0.0.x) | Fixing encoding edge case |
| Deprecation added (not removed) | MINOR | Adding DeprecationWarning |
| Deprecated symbol removed | MAJOR | Removing deprecated function |
Deprecation process
Before removing or changing a public symbol:
- Add a
DeprecationWarningin the current MINOR release:
import warnings
def old_name(*args, **kwargs):
warnings.warn(
"old_name() is deprecated since 0.8.0 and will be removed in 1.0.0. "
"Use new_name() instead.",
DeprecationWarning,
stacklevel=2,
)
return new_name(*args, **kwargs)
- Document in changelog under a
### Deprecatedheading. - Keep the alias for at least one MINOR version before removal.
- Removal happens in the next MAJOR release only.
.permafrost file format compatibility
- Format version is independent of SDK version.
- Files written by v1.x are always readable by implementations supporting v1.y (y ≥ x).
- Breaking format changes require incrementing
VERSION_MAJOR(byte 4 of file). - The reference implementation in
codec.pyis the canonical source of truth.
Code of Conduct
This project follows the Contributor Covenant. Be respectful, constructive, and inclusive.