Open-source implementation of the z/OS TERSE (AMATERSE / PACK / SPACK) compression format
Project description
TerseLib
A Python, implementation of the z/OS TERSE compression format (as produced by AMATERSE and the older TRSMAIN), written from scratch.
Compress files on Linux/macOS/Windows and unpack them with AMATERSE on the mainframe — or terse a data set on z/OS and decompress it anywhere.
- Both compression methods: PACK (LZW) and SPACK (LZMW) are supported
- Host (12-byte header) and native (4-byte header) containers
- Fixed (F/FB) and variable (V/VB) record formats, including RDW framing
- Text (EBCDIC ⇄ ASCII) and binary rendering, with selectable code pages
- Smart decompression: auto-detects text vs binary content and picks an output file extension by content sniffing (libmagic)
- Validated against the IBM
tersedecompresstest corpus: byte-identical output in both directions for every PACK/SPACK, FB/VB, text/binary combination (only exceptions: two corpus files that AMATERSE itself produced broken)
Why no off-the-shelf LZW library? TERSE's PACK is a nonstandard LZW: fixed 12-bit codes, a dictionary that starts full (pre-seeded with EBCDIC blanks) and least-recently-used slot recycling instead of a dictionary reset. SPACK is LZMW, which has no maintained Python implementation. Both codecs are therefore implemented here, straight from the spec. The
ebcdicpackage (extra code pages) andpython-magic(file-type detection) are used when installed.
Install
$ pip install terselib # from PyPI; add [full] for ebcdic + magic
$ pip install terselib[full]
Or from a checkout (this directory contains pyproject.toml):
$ pip install .
Command line
$ terse report.txt # -> report.txt.trs (SPACK, text, VB)
$ terse -b image.png # binary, lossless (FB LRECL 1)
$ terse -m pack --recfm f -l 80 x.txt # PACK, fixed 80-byte records
$ unterse DATA.TRS # auto: text/binary + extension sniffing
$ unterse -b DATA.TRS out.bin # force exact binary output
$ unterse -t -c cp037 DATA.TRS out.txt # text via a specific code page
$ unterse -i DATA.TRS # show header info only
terselib compress|decompress|info is an umbrella alias for the same
tools, also reachable as python -m terselib.
Moving files to/from z/OS
Transfer .trs files in binary (ftp> binary). On z/OS, allocate the
receiving data set as RECFM=FB LRECL=1024 (the file size is always a
multiple of 1024), then unpack with:
//UNPACK EXEC PGM=AMATERSE,PARM='UNPACK'
//SYSUT1 DD DISP=SHR,DSN=YOUR.TERSED.FILE
//SYSUT2 DD DSN=YOUR.OUTPUT,DISP=(NEW,CATLG),...
Library
import terselib
# compress / decompress bytes
blob = terselib.compress(b"HELLO\nWORLD\n", text=True) # SPACK, VB
result = terselib.decompress(blob) # auto-detect
assert result.data == b"HELLO\nWORLD\n" and result.text
# work with files; binary output gets a sniffed extension
terselib.compress_file("payload.bin", text=False, variable=False,
record_length=1)
path, result = terselib.decompress_file("payload.bin.trs")
# inspect a header without decompressing
print(terselib.read_header("DATA.TRS").describe())
# verbose logging (off by default)
terselib.enable_verbose_logging()
See the documentation (Sphinx / Read the Docs) for the full API reference.
Folder layout
.
├── pyproject.toml packaging metadata; run pip install from here
├── src/terselib/ the library + terse/unterse/terselib CLIs
├── tests/ stdlib unittest suite
├── scripts/ corpus_check.py -- validates against a reference
│ z/OS test corpus (see below)
└── docs/ Sphinx sources (readthedocs.io)
Development
$ python3 -m unittest discover -s tests # unit tests
$ python3 scripts/corpus_check.py PATH/TO/tersedecompress-testdata \
--skip-large --roundtrip # corpus validation
scripts/corpus_check.py needs a checkout of the tersedecompress
project's tersedecompress-testdata (not included in this repo) — real
AMATERSE-compressed files plus their z/OS-decompressed references, used to
validate this implementation byte-for-byte in both directions.
License
GPL-3.0-or-later, see LICENSE.
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 terselib-0.1.0.tar.gz.
File metadata
- Download URL: terselib-0.1.0.tar.gz
- Upload date:
- Size: 44.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9fa30970eb6427ce8b8200fbba9127911e592d8a17b45c15da2109ebcede7c4d
|
|
| MD5 |
0016e532cd59c7f93b1958e4cd7fedbe
|
|
| BLAKE2b-256 |
7f660d72dd6f6331b574e83ab2c277d0462e8e099e586a109d94079f85d2ec3f
|
Provenance
The following attestation bundles were made for terselib-0.1.0.tar.gz:
Publisher:
publish.yml on mainframed/terselib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
terselib-0.1.0.tar.gz -
Subject digest:
9fa30970eb6427ce8b8200fbba9127911e592d8a17b45c15da2109ebcede7c4d - Sigstore transparency entry: 2106706287
- Sigstore integration time:
-
Permalink:
mainframed/terselib@eb71fd2aeca0923867c93ed94638aa3b9e7d9c38 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mainframed
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@eb71fd2aeca0923867c93ed94638aa3b9e7d9c38 -
Trigger Event:
release
-
Statement type:
File details
Details for the file terselib-0.1.0-py3-none-any.whl.
File metadata
- Download URL: terselib-0.1.0-py3-none-any.whl
- Upload date:
- Size: 45.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5da219460663623a010a60541c47e824dafea3947ee36fb66296dceb14e7562
|
|
| MD5 |
2d6a5e11961e39110120e0ac6e4196a3
|
|
| BLAKE2b-256 |
d68b9f5be20569e77b6323f9a6dcc6d5bc9d8957f5d604925b5f1c3e8b48c503
|
Provenance
The following attestation bundles were made for terselib-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on mainframed/terselib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
terselib-0.1.0-py3-none-any.whl -
Subject digest:
f5da219460663623a010a60541c47e824dafea3947ee36fb66296dceb14e7562 - Sigstore transparency entry: 2106706375
- Sigstore integration time:
-
Permalink:
mainframed/terselib@eb71fd2aeca0923867c93ed94638aa3b9e7d9c38 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mainframed
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@eb71fd2aeca0923867c93ed94638aa3b9e7d9c38 -
Trigger Event:
release
-
Statement type: