Compile a Power BI Project (.pbip) folder into a .pbix file — pure Python, no Power BI Desktop or Windows required.
Project description
pbip-compiler
Compile a Power BI Project (.pbip) folder into a single .pbix file —
in pure Python. No Power BI Desktop, no external CLI tools, no Windows required.
It parses the project's semantic model (TMDL / model.bim) and PBIR report,
builds a real VertiPaq DataModel (via pbix-mcp),
preserves each table's Power Query (M) so the report stays refreshable, and
assembles the final .pbix ZIP.
Features
- 📦
.pbip→.pbixentirely in Python - 🧮 Builds a real VertiPaq DataModel (tables, columns, measures, relationships)
- 🔁 Preserves partition M expressions → Refresh in Power BI loads the data
- 🌐 Handles live-connection reports (bound to a published semantic model)
- 🪶 Falls back to a thin / report-only
.pbixwhen there is no local model
Installation
# with uv (recommended)
uv add pbip-compiler
# or with pip
pip install pbip-compiler
Requires Python ≥ 3.11.
Quick start (CLI)
pbip-compiler --pbip ./MyProject --output ./MyReport.pbix
Using pbip_compiler as a module
1. Compile a .pbip folder to a .pbix file
from pbip_compiler import PbipCompiler
compiler = PbipCompiler("./MyProject") # path to the .pbip folder
output = compiler.compile("./MyReport.pbix") # returns the resolved Path
print(f"Compiled → {output}")
2. Compile to bytes (no file written)
Useful when serving the result over HTTP, uploading it, or writing it yourself.
from pbip_compiler import PbipCompiler
compiler = PbipCompiler("./MyProject")
pbix_bytes: bytes = compiler.compile_to_bytes()
# e.g. write it yourself, stream it, upload it...
with open("MyReport.pbix", "wb") as f:
f.write(pbix_bytes)
3. Handle errors
from pathlib import Path
from pbip_compiler import PbipCompiler
try:
result: Path = PbipCompiler("./MyProject").compile("./out.pbix")
print(f"✅ Success → {result}")
except FileNotFoundError as exc:
# e.g. no *.Report folder inside the project
print(f"❌ Project layout problem: {exc}")
except Exception as exc:
print(f"❌ Compilation failed: {exc}")
4. Build a .pbix from a semantic model defined in code
You don't have to start from a .pbip folder. You can describe a model with the
data classes and build the DataModel directly.
from pbip_compiler import Column, Measure, Relationship, SemanticModel, Table
from pbip_compiler.datamodel import PbixMcpDataModelBuilder
model = SemanticModel(
tables=[
Table(
name="Sales",
columns=[
Column(name="OrderId", data_type="Int64"),
Column(name="ProductId", data_type="Int64"),
Column(name="Amount", data_type="Decimal"),
],
measures=[
Measure(name="Total Sales", expression="SUM(Sales[Amount])"),
],
# Power Query (M) source — preserved so Refresh loads the data
m_expression='let Source = Csv.Document(File.Contents("sales.csv")) in Source',
),
Table(
name="Product",
columns=[
Column(name="ProductId", data_type="Int64"),
Column(name="Name", data_type="String"),
],
),
],
relationships=[
Relationship(
from_table="Sales", from_column="ProductId",
to_table="Product", to_column="ProductId",
),
],
)
datamodel_bytes: bytes = PbixMcpDataModelBuilder().build(model)
Public API
| Object | Description |
|---|---|
PbipCompiler(pbip_path) |
Orchestrates a .pbip → .pbix compilation. |
PbipCompiler.compile(output) |
Compile and write the .pbix; returns the Path. |
PbipCompiler.compile_to_bytes() |
Compile and return the .pbix as bytes. |
SemanticModel |
A model: tables + relationships. |
Table |
name, columns, measures, is_hidden, m_expression. |
Column |
name, data_type, source_column. |
Measure |
name, expression (DAX). |
Relationship |
from_table/from_column → to_table/to_column. |
How it works
.pbip folder
├── *.Report/ → PBIR report ─┐
└── *.SemanticModel/ → TMDL / .bim ─┤
▼
SemanticModelLoader + ReportLayoutLoader
▼
PbixMcpDataModelBuilder (VertiPaq DataModel, M preserved)
▼
PbixAssembler → MyReport.pbix
- Live connection — if the report binds to a published semantic model, no local DataModel is built; the report + a Connections part are embedded.
- No / empty semantic model — a thin (report-only)
.pbixis produced.
License
MIT © 2026 Maxim Bacar
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 pbip_compiler-0.2.0.tar.gz.
File metadata
- Download URL: pbip_compiler-0.2.0.tar.gz
- Upload date:
- Size: 79.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33642368e8d096819ad06b7f3ff8aa8d3fc089d30c62ab21ca7859419826abfc
|
|
| MD5 |
3a53659960078e3faa07755015962f02
|
|
| BLAKE2b-256 |
ea184afcc8df18632d8cbc22f3129000b3550d7ede5c87504c810a34c9cea09a
|
Provenance
The following attestation bundles were made for pbip_compiler-0.2.0.tar.gz:
Publisher:
release.yml on MaximBacar/pbip-compiler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pbip_compiler-0.2.0.tar.gz -
Subject digest:
33642368e8d096819ad06b7f3ff8aa8d3fc089d30c62ab21ca7859419826abfc - Sigstore transparency entry: 1945012399
- Sigstore integration time:
-
Permalink:
MaximBacar/pbip-compiler@7f40966584156773143143ab0f119f46732e366b -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/MaximBacar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7f40966584156773143143ab0f119f46732e366b -
Trigger Event:
push
-
Statement type:
File details
Details for the file pbip_compiler-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pbip_compiler-0.2.0-py3-none-any.whl
- Upload date:
- Size: 29.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 |
6f27c298f4f9efab6fa142d5744a3dcebcead3d614974f1dfbf95772aa48e59c
|
|
| MD5 |
a251a34cead9cca2be29c74c7a1ea1c7
|
|
| BLAKE2b-256 |
9c3ab1fb646d0448e9d6ddd81068e17c7678fe8dd35e6ef81be5dedd9037c16d
|
Provenance
The following attestation bundles were made for pbip_compiler-0.2.0-py3-none-any.whl:
Publisher:
release.yml on MaximBacar/pbip-compiler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pbip_compiler-0.2.0-py3-none-any.whl -
Subject digest:
6f27c298f4f9efab6fa142d5744a3dcebcead3d614974f1dfbf95772aa48e59c - Sigstore transparency entry: 1945012545
- Sigstore integration time:
-
Permalink:
MaximBacar/pbip-compiler@7f40966584156773143143ab0f119f46732e366b -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/MaximBacar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7f40966584156773143143ab0f119f46732e366b -
Trigger Event:
push
-
Statement type: