Skip to main content

saransh-workflows

Python parsers for Indian financial statement PDFs — CAMS Consolidated Account Statement, CDSL CAS, and NSDL e-CAS. Each parser extracts text from the PDF using pypdf and returns a fully structured JSON object.


Installation

From PyPI (once published)

pip install saransh-workflows

From source (development)

git clone https://github.com/sagarchandagarwal/saransh-workflows.git
cd saransh-workflows
pip install -e .

CLI Usage

After installation three commands are available on your PATH:

# CAMS parser
parse-cams path/to/cams_statement.pdf
parse-cams path/to/cams_statement.pdf --pretty -o output.json
parse-cams path/to/cams_statement.pdf --password your_pdf_password --pretty

# CDSL parser
parse-cdsl path/to/cdsl_cas.pdf
parse-cdsl path/to/cdsl_cas.pdf --pretty -o output.json
parse-cdsl path/to/cdsl_cas.pdf --password your_pdf_password --pretty

# NSDL parser
parse-nsdl path/to/nsdl_ecas.pdf
parse-nsdl path/to/nsdl_ecas.pdf --pretty -o output.json
parse-nsdl path/to/nsdl_ecas.pdf --password your_pdf_password --pretty

All three commands accept the same flags:

Flag Description
input_pdf Path to the source PDF (required)
-o / --output Output JSON path (default: same name as PDF with .json suffix)
--pretty Pretty-print JSON with 2-space indentation
--password Password for encrypted/password-protected PDF files

Python API

from pathlib import Path
from saransh_workflows import parse_cams_pdf, parse_cdsl_pdf, parse_nsdl_pdf

cams_data  = parse_cams_pdf(Path("cams_statement.pdf"))
cdsl_data  = parse_cdsl_pdf(Path("cdsl_cas.pdf"))
nsdl_data  = parse_nsdl_pdf(Path("nsdl_ecas.pdf"))

# Encrypted PDFs
nsdl_encrypted = parse_nsdl_pdf(Path("nsdl_ecas.pdf"), password="your_pdf_password")

All three functions return a plain dict that can be serialised with json.dumps.


Output JSON Schemas

CAMS

{
  "source_file": str,
  "statement_period": {"from": str, "to": str} | null,
  "investor": {
    "email": str | null,
    "name": str | null,
    "address": [str],
    "phone_res": str | null,
    "mobile": str | null
  },
  "portfolio_summary": [
    {"fund_house": str, "cost_value_inr": float, "market_value_inr": float}
  ],
  "folios": [
    {
      "fund_house": str,
      "folio_no": str | null,
      "pan": str | null,
      "kyc": str | null,
      "holder_name": str | null,
      "scheme_code": str | null,
      "scheme_name": str | null,
      "isin": str | null,
      "registrar": str | null,
      "nominees": [str],
      "opening_unit_balance": float | null,
      "transactions": [
        {
          "date": str,
          "transaction": str,
          "amount_inr": float | null,
          "units": float | null,
          "price_inr": float | null,
          "unit_balance": float | null,
          "charges": [{"date": str, "amount_inr": float}]
        }
      ],
      "closing_unit_balance": float | null,
      "nav": {"date": str, "value_inr": float} | null,
      "total_cost_value_inr": float | null,
      "market_value": {"date": str, "value_inr": float} | null,
      "notes": [str]
    }
  ],
  "warnings": [str]
}

CDSL

{
  "source_file": str,
  "cas_id": str | null,
  "statement_period": {"from": str, "to": str} | null,
  "investor": {"name": str, "pan": str, "address": [str]},
  "summary": {
    "accounts": [...],
    "total_portfolio_value_inr": float | null,
    "grand_total_inr": float | null,
    "monthly_portfolio_valuation": [...],
    "asset_allocation": [...]
  },
  "cdsl_accounts": [
    {
      "bo_id": str,
      "dp_name": str,
      "transactions": [...],
      "holdings": [...],
      "holding_sections": [...],
      "no_transaction": bool,
      "nil_holding": bool,
      "portfolio_values": [float]
    }
  ],
  "nsdl_accounts": [...],
  "mutual_fund_folios": [
    {
      "amc_name": str,
      "scheme_name": str,
      "scheme_code": str,
      "folio_no": str | null,
      "isin": str | null,
      "opening_balance": float | null,
      "closing_balance": float | null,
      "transactions": [...]
    }
  ]
}

NSDL

{
  "source_file": str,
  "nsdl_id": str | null,
  "statement_period": {"from": str, "to": str} | null,
  "investor": {
    "name": str | null,
    "pan": str | null,
    "address": [str],
    "portfolio_value_inr": float | null
  },
  "summary": {
    "accounts": [...],
    "total_inr": float | null,
    "grand_total_inr": float | null,
    "portfolio_trend": [
      {
        "month": str,
        "portfolio_value_inr": float | null,
        "change_inr": float | null,
        "change_percent": float | null,
        "remark": str | null
      }
    ],
    "asset_composition": [
      {"asset_class": str, "value_inr": float, "percent": float}
    ]
  },
  "holdings": {
    "account": {...},
    "securities": [
      {
        "isin": str,
        "security": str,
        "current_balance": float,
        "free_balance": float,
        "value_inr": float,
        ...
      }
    ]
  },
  "transactions": {
    "account": {...},
    "isin_sections": [
      {
        "isin": str,
        "security": str,
        "opening_balance": float | null,
        "closing_balance": float | null,
        "transactions": [...]
      }
    ]
  }
}

Project Structure

saransh-workflows/
├── saransh_workflows/        # Installable Python package
│   ├── __init__.py           # Public API re-exports
│   ├── cams.py               # CAMS parser
│   ├── cdsl.py               # CDSL parser
│   └── nsdl.py               # NSDL parser
├── cams-parser/
│   ├── parse_cams_pdf.py     # Standalone script (standalone usage)
│   └── requirements.txt
├── cdsl-parser/
│   ├── parse_cdsl_pdf.py     # Standalone script
│   └── requirements.txt
├── nsdl-parser/
│   ├── parse_nsdl_pdf.py     # Standalone script
│   └── requirements.txt
├── pyproject.toml            # Package metadata & build config
├── README.md
└── AGENTS.md                 # Development log & change history

Publishing to PyPI

pip install build twine
python -m build
twine upload dist/*

Requirements

  • Python ≥ 3.11
  • pypdf ≥ 6.0.0
  • cryptography ≥ 3.1 (required for AES-encrypted PDFs)

License

MIT

Metadata

Release files for saransh-workflows 0.1.0

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

Source distribution (sdist)

Source distribution for saransh-workflows 0.1.0
File Size Uploaded Provenance
saransh_workflows-0.1.0.tar.gz 25.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for saransh-workflows 0.1.0
File Interpreter ABI Platform
saransh_workflows-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.5 kB

Release files / saransh_workflows-0.1.0.tar.gz

Download URL saransh_workflows-0.1.0.tar.gz
Size 25.6 kB
Tags Source
SHA-256 checksum
How to use checksums
72dcfedc3f991f0934658f8485690502f9982245fee65f9bcf5e093a5b4a1790
BLAKE2b-256 checksum
How to use checksums
5af4fb86a0baefbc8e87eff11d5e3973740a6a32add5435ec226fb9bc454e6eb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Release files / saransh_workflows-0.1.0-py3-none-any.whl

Download URL saransh_workflows-0.1.0-py3-none-any.whl
Size 18.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
840633e9cf29157ce56be4f1aa6029353699bbf974db2c00467a4907e0d227d8
BLAKE2b-256 checksum
How to use checksums
5294c4aa878e7ea875165c9a1e06a30a5248ad2292bf68f7774915a4b501289a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Security for saransh-workflows 0.1.0

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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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