Skip to main content

python-copybook

PyPI Python License

A Python library for parsing fixed-format COBOL copybook files into structured, traversable data models.

Overview

python-copybook reads .cpy and .cbl copybook files and produces a clean hierarchy of parsed COBOL data fields. It handles multi-line statements, continuation lines, inline comments, REDEFINES, OCCURS, RENAMES, and all standard data definition clauses.

The library is structured as a five-stage pipeline:

File → CobolLine → CobolStatement → CobolField → CobolNode tree → rendered output

Each stage is independent and produces typed objects, so you can stop at any layer depending on what you need.

Current Scope

This library currently supports flat, self-contained copybooks only.

  • Fixed-format 80-column COBOL records
  • No COPY statement resolution — copybooks with imports are not yet supported
  • Offset, length, and position calculation is in progress
  • Buffer and memory view generation (mapping a raw data record to named fields) is planned

Installation

pip install python-copybook

Requirements

Python 3.12+

Quick Start

from copybook.parser import read_copybook, read_statements, parse_fields
from copybook.tree import build_tree, build_flat_tree
from copybook.render import render_copybook, render_flat_copybook

# Stage 1 — read physical lines
lines = read_copybook("CLAIMREC.cpy")

# Stage 2 — assemble logical statements
statements = read_statements(lines)

# Stage 3 — parse fields from statements
fields = parse_fields(statements)

# Stage 4 — build hierarchy tree
tree = build_tree(fields)

# Stage 5 — render output
print(render_copybook(tree))

Pipeline Stages

Stage 1 — read_copybook(path) → list[CobolLine]

Reads the file and slices each physical line into its fixed-format column regions. Lines are stored raw — no interpretation occurs at this stage.

Columns 1–6   — Sequence number
Column  7     — Indicator  (* = comment, - = continuation, space = normal)
Columns 8–72  — Area  (actual COBOL content)
Columns 73–80 — Identification (free-form comment)

Stage 2 — read_statements(lines) → list[CobolStatement]

Joins physical lines into complete logical declarations. In fixed-format COBOL, a declaration ends with a period and may span multiple lines. This stage handles:

  • Full-line comments (* or / indicator)
  • Continuation lines (- indicator)
  • Inline comments (*> syntax, COBOL 2002+)

Stage 3 — parse_fields(statements) → list[CobolField]

Extracts every COBOL clause from each statement using independent regex searches. Clause order in the source does not matter.

Clauses parsed: PIC/PICTURE, REDEFINES, RENAMES, RENAMES THRU, USAGE, OCCURS, DEPENDING ON, INDEXED BY, VALUE/VALUES ARE, SIGN SEPARATE, SYNCHRONIZED

Stage 4 — build_tree(fields) → list[CobolNode]

Assigns parent-child relationships using level numbers. Returns root-level nodes; all others are reachable via .children.

Two tree views are available:

Function Contents
build_tree(fields) Full hierarchy — mirrors source exactly
build_flat_tree(fields) Elementary fields only — no groups, no 88s, no REDEFINES

Stage 5 — Rendering

Function Output
render_copybook(tree) Full copybook, original level numbers preserved
render_flat_copybook(nodes, record_name) All fields remapped to level 05 under one 01 record

render_copybook accepts an indent_size parameter (default 4) to control visual depth:

render_copybook(tree, indent_size=0)   # flat — all fields at Area B
render_copybook(tree, indent_size=4)   # default — 4 spaces per depth level

Data Models

CobolLine

One physical line from the file. Never mutated after creation.

line.line_number      # int — 1-based
line.indicator        # str — single char, space = normal
line.area             # str — raw columns 8–72
line.is_comment       # bool — indicator is * or /
line.is_continuation  # bool — indicator is -
line.raw_line         # str — reconstructed 80-char record

CobolStatement

One complete logical declaration, potentially spanning multiple lines.

stmt.area             # str — full joined text e.g. '15 Field PIC X(10).'
stmt.source_lines     # list[CobolLine] — contributing physical lines
stmt.reserved_words   # list[str] — COBOL keywords found in this statement
stmt.copybook         # str — source file path

CobolField

One parsed data field with all clauses extracted.

field.level           # int  — level number
field.name            # str  — uppercased field name
field.picture         # str | None  — e.g. '9(07)', 'X(15)', 'S9(7)V99'
field.redefines       # str | None  — target field name
field.usage           # str | None  — e.g. 'COMP-3', 'BINARY', 'DISPLAY'
field.occurs          # int | None  — fixed array size
field.occurs_max      # int | None  — upper bound for variable arrays
field.depending_on    # str | None  — field holding current array size
field.indexed_by      # str | None  — index name for OCCURS tables
field.value           # str | None  — VALUE clause content
field.sign_separate   # bool — SIGN LEADING/TRAILING SEPARATE present
field.synchronized    # bool — SYNC/SYNCHRONIZED present

# Derived properties
field.is_filler         # name == 'FILLER'
field.is_condition      # level == 88
field.is_group          # no PIC clause
field.is_redefine       # has REDEFINES clause
field.is_array          # has OCCURS clause
field.is_variable_array # has DEPENDING ON clause
field.is_numeric        # PIC contains 9
field.is_signed         # PIC starts with S

CobolNode

A node in the field hierarchy tree. Wraps a CobolField with parent/child references.

node.cobol_field      # CobolField
node.parent           # CobolNode | None
node.children         # list[CobolNode]
node.level            # shortcut to cobol_field.level
node.name             # shortcut to cobol_field.name
node.to_dict()        # JSON string — parent serialized as name string to avoid circular refs

Examples

Parse and print a copybook tree

from copybook.parser import read_copybook, read_statements, parse_fields
from copybook.tree import build_tree
from copybook.render import render_copybook

lines      = read_copybook("CLAIMREC.cpy")
statements = read_statements(lines)
fields     = parse_fields(statements)
tree       = build_tree(fields)

print(render_copybook(tree, indent_size=4))
       01  Claim-Record.
           12 Insured-Details.
               15 Insured-Policy-No        PIC 9(07).
               15 Insured-Last-Name        PIC X(15).
           12 Policy-Details.
               15 Policy-Type              PIC 9.
                   88 Private              VALUE 1.
                   88 Medicare             VALUE 2.

Generate a flat copybook (no groups, no REDEFINES)

from copybook.tree import build_flat_tree
from copybook.render import render_flat_copybook

flat = build_flat_tree(fields)
print(render_flat_copybook(flat, "FLAT-CLAIMREC"))
       01  FLAT-CLAIMREC.
           05 Insured-Policy-No        PIC 9(07).
           05 Insured-Last-Name        PIC X(15).
           05 Insured-First-Name       PIC X(10).
           05 Policy-Type              PIC 9.
           05 Policy-Benefit-Date-Num  PIC 9(08).
           05 Policy-Amount            PIC S9(7)V99.

Inspect a field

for field in fields:
    if field.is_numeric:
        print(f"{field.name}: PIC {field.picture}")

Serialize a tree node to JSON

tree = build_tree(fields)
print(tree[0].to_dict())

Project Structure

copybook/
    models.py          — CobolLine, CobolStatement, CobolField, CobolNode
    patterns.py        — regex patterns, layout constants, reserved words
    parser.py          — read_copybook, read_statements, parse_fields
    tree.py            — build_tree, build_flat_tree
    render.py          — render_copybook, render_flat_copybook
    reserved_words.txt — COBOL reserved word list

Supported COBOL Features

Feature Supported
Fixed-format 80-column records ✅
Full-line comments (*, / indicator) ✅
Continuation lines (- indicator) ✅
Inline comments (*>) ✅
Multi-line statements ✅
PIC / PICTURE clause ✅
REDEFINES ✅
OCCURS n TIMES ✅
OCCURS n TO m TIMES DEPENDING ON ✅
INDEXED BY ✅
VALUE / VALUES ARE ✅
USAGE / COMP / COMP-3 / BINARY etc. ✅
SIGN LEADING/TRAILING SEPARATE ✅
SYNCHRONIZED / SYNC ✅
RENAMES / RENAMES THRU ✅
Level 66, 77, 88 ✅
:tag: style replacement tokens ✅
Free-format COBOL ❌

Roadmap

  • PIC clause byte length calculator (DISPLAY, COMP-3, BINARY, etc.)
  • Field offset and position computation
  • REDEFINES-aware offset handling (overlapping storage)
  • OCCURS multiplier in offset calculation
  • Raw record buffer slicing by field name
  • Multiple memory view strategies (full tree, flat, storage-only)
  • COPY statement resolution across multiple copybook files

License

GPL-3.0 — see LICENSE for details.

Metadata

Release files for python-copybook 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for python-copybook 0.1.2
File Size Uploaded Provenance
python_copybook-0.1.2.tar.gz 36.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for python-copybook 0.1.2
File Interpreter ABI Platform
python_copybook-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 74.9 kB

Release files / python_copybook-0.1.2.tar.gz

Download URL python_copybook-0.1.2.tar.gz
Size 36.6 kB
Tags Source
SHA-256 checksum
How to use checksums
286fed7da99a55a97102b2fe4347dfb7bd67c6a2b30c7b6cb41318ca05353f99
BLAKE2b-256 checksum
How to use checksums
20a0359eb2f75103fdb938bf7fb371d3322d0b5172217e5002e903f966ee5450
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.2 CPython/3.12.10 Darwin/25.1.0

Release files / python_copybook-0.1.2-py3-none-any.whl

Download URL python_copybook-0.1.2-py3-none-any.whl
Size 38.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aa11cb2f409cd28620c8e9e6a310828d36668a29a029e0d019cc6ecde9728b3f
BLAKE2b-256 checksum
How to use checksums
e1bebfd34ea6aa657e6f734ac8f711e7ca1ebf4c5245190f5b31c2d3a53d360a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.2 CPython/3.12.10 Darwin/25.1.0

Security for python-copybook 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page