Metadata-Version: 2.4
Name: powerbi-tmdl-tools
Version: 1.0.5
Summary: Convert Power BI/Tabular TMDL and PBIP semantic models to JSON and generate Mermaid ERDs.
Author-email: kohsah <kohsakohsa@proton.me>
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/kohsah/tmdl2json
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: png-python
Requires-Dist: mermaid-cli; extra == "png-python"
Dynamic: license-file

# TMDL to JSON Converter

A Python3 utility to convert Tabular Model Definition Language (TMDL) files into JSON format. This tool parses the indentation-based TMDL syntax and outputs a structured JSON representation, making it easier to process or analyze Power BI/Analysis Services semantic models programmatically.

For contributor and tooling conventions, see [AGENTS.md](AGENTS.md). For a detailed breakdown of supported features and extraction capabilities, see [docs/TECHNICAL_SPEC.md](docs/TECHNICAL_SPEC.md).

## Features

- **TMDL Parsing**: Handles root objects (`table`, `database`, `model`) and nested elements like columns, partitions, measures, annotations, and relationships.
- **Relationship Enrichment**: Derives `fromTable`/`fromColumnName` and `toTable`/`toColumnName` from `fromColumn`/`toColumn`.
- **Multi-line Support**: Normalizes multi-line blocks (e.g., partition `source` M scripts, measure expressions) by stripping common indentation.
- **Partition Source Enrichment**: Extracts `{[Schema="...",Item="..."]}` references and attempts base64 decode/decompression for `Binary.FromText(..., BinaryEncoding.Base64)`.
- **Batch Processing**: Converts a single file or an entire directory of `.tmdl` files.
- **PBIP Parsing**: Parses PBIP inputs (report root folder, `.pbip` file path, or semantic model folder) and aggregates model definition files into one JSON document.
- **ERD Generation**: Produces Mermaid ER diagrams from JSON output, with PNG export via:
  - remote `mermaid.ink` (default)
  - local Mermaid CLI (`mmdc`)
  - Python `mermaid-cli` library

## Project Structure

```
.
├── AGENTS.md
├── README.md
├── config_loader.py
├── erd_generator.py
├── pbip_definition.json
├── pbip_parser.py
├── requirements.txt
├── tmdl_parser.py
├── test_erd_generator.py
├── test_pbip_parser.py
├── test_tmdl_parser.py
└── docs/
    └── TECHNICAL_SPEC.md
```

## Usage

Run commands from the `code` directory using the in-repo virtual environment Python (`../env/Scripts/python` on Windows, or `../env/python` if you use a shim).

## Install (PyPI)

Install from PyPI:

```bash
python -m pip install powerbi-tmdl-tools
```

Optional (enable `--png-mode python` for ERD PNG rendering):

```bash
python -m pip install "powerbi-tmdl-tools[png-python]"
```

After installation, the following console commands are available:
- `tmdl-to-json`
- `pbip-to-json`
- `tmdl-erd`

### 1. Convert a single TMDL file

**Print to console:**
```bash
../env/Scripts/python tmdl_parser.py tmdl/DimCountry.tmdl
```

**Save to a specific JSON file:**
```bash
../env/Scripts/python tmdl_parser.py tmdl/DimCountry.tmdl -o output.json
```

### 2. Convert a directory of `.tmdl` files

Convert all `.tmdl` files in a directory and save them to an output folder:

```bash
../env/Scripts/python tmdl_parser.py tmdl -o json_output
```
*Note: If `json_output` does not exist, it will be created.*

### 3. Parse a PBIP folder

Parse a `.pbip` folder and write the aggregated model JSON:

```bash
../env/Scripts/python pbip_parser.py path\to\Report.pbip --output model.json
```

`tmdl_parser.py` can also accept:
- a PBIP report root folder containing a single `.pbip` file (it resolves `.pbip -> .Report/definition.pbir -> .SemanticModel/definition`)
- a `.pbip` file path directly

### 4. Help

View all available options:

```bash
../env/Scripts/python tmdl_parser.py --help
```

## Testing

Unit tests are provided to verify parser functionality. Run them from the `code` directory:

```bash
../env/Scripts/python -m unittest
```

## ERD Generation

The `erd_generator.py` utility generates Entity Relationship Diagrams (ERD) from the JSON output produced by `tmdl_parser.py` or `pbip_parser.py`.

### Features

- **Mermaid Syntax**: Generates standard Mermaid ERD diagrams compatible with GitHub, Notion, and other tools.
- **Smart Filtering**: Automatically excludes system tables (`DateTableTemplate`, `LocalDateTable`) to focus on your business logic.
- **Clean Output**: Trims DAX formulas from column names for better readability.
- **PNG Export**: Can export diagrams directly to PNG images using the mermaid.ink API (requires internet access).
  - Default: remote `mermaid.ink`
  - Offline: local `mmdc` (Mermaid CLI) or Python `mermaid-cli` (see options below)

### Usage

**1. Generate Mermaid Markdown:**

```bash
../env/Scripts/python erd_generator.py input.json --output diagram.md
```

**2. Generate PNG Image:**

```bash
../env/Scripts/python erd_generator.py input.json --png-output diagram.png
```

**3. Generate both Markdown and PNG:**

```bash
../env/Scripts/python erd_generator.py input.json --output diagram.md --png-output diagram.png
```

### Options

- `input_file`: Path to the JSON input file (output from `tmdl_parser.py`).
- `--output`, `-o`: Path to output Mermaid file (e.g. `output.md`). If ending in `.md`, wraps content in a mermaid code block.
- `--png-output`: Path to output PNG file.
- `--png-mode`: PNG rendering mode:
  - `remote` (default): uses `mermaid.ink` (requires internet access)
  - `local`: uses Mermaid CLI (`mmdc`) (offline; requires `mmdc` installed)
  - `python`: uses Python `mermaid-cli` (offline; install via `requirements.txt`)
- `--mmdc-path`: Path to `mmdc` executable (for `--png-mode local`)
- `MMDC_PATH`: Environment variable alternative to `--mmdc-path` (for `--png-mode local`)
