SSRS Library
Project description
ssrs-powerbi-library
A Python library for automating Power BI Report Server (PBIRS) and SQL Server Reporting Services (SSRS) via the REST API v2.0. Designed to replace PowerShell ReportingServicesTools in CI/CD pipelines.
Repository: atlas-bi/ssrs-powerbi-library
Features
- Easy API — connect once, get resource handle objects, call methods on them
- NTLM authentication — native Windows/domain credentials via
requests-ntlm - Power BI reports — upload, delete, data sources, data model parameters, cache refresh plans, security
- Paginated (SSRS) reports — upload, delete, data sources, report parameters, cache refresh plans, security
- Folder management — create, list, delete, security policies
- Schedule helpers — build daily / weekly / monthly schedules with a fluent API
- Row-level security — manage RLS role assignments on Power BI reports
- Typed exceptions —
PBIRSNotFound,PBIRSConflict,PBIRSAuthError - CI/CD ready — works in GitLab, GitHub Actions, Azure Pipelines, etc.
Installation
pip install ssrs-powerbi-library
Or from source:
git clone https://github.com/atlas-bi/ssrs-powerbi-library.git
cd ssrs-powerbi-library
pip install -e .
Requirements: Python 3.8+, network access to PBIRS, NTLM-capable credentials.
Quick start
from ssrs_library import PBIRSClient
client = PBIRSClient(
base_url="http://pbirs.corp.local/reports",
username="svc_deploy",
password="secret",
domain="CORP",
)
client.test_connection() # raises PBIRSAuthError / PBIRSError on failure
# Upload a .pbix
report = client.upload_powerbi_report(
folder_path="/Sales",
file_path="/ci/artifacts/Revenue.pbix",
name="Revenue",
overwrite=True,
)
print(report) # <PowerBIReport name='Revenue' path='/Sales/Revenue'>
API reference
PBIRSClient
PBIRSClient(base_url, username, password, domain="", verify_ssl=True, timeout=30)
| Method | Returns | Description |
|---|---|---|
test_connection() |
bool |
Verify credentials & connectivity |
get_folder(path) |
Folder |
Fetch a folder by catalog path |
create_folder(path, description="") |
Folder |
Create folder (and intermediate folders) |
list_folders(parent_path=None) |
List[Folder] |
List sub-folders |
get_powerbi_report(path) |
PowerBIReport |
Fetch a .pbix report |
list_powerbi_reports(folder_path=None) |
List[PowerBIReport] |
List .pbix reports |
upload_powerbi_report(folder_path, file_path, name, overwrite=False) |
PowerBIReport |
Upload .pbix (auto-selects multipart for files >25 MB) |
get_paginated_report(path) |
PaginatedReport |
Fetch a .rdl report |
list_paginated_reports(folder_path=None) |
List[PaginatedReport] |
List .rdl reports |
upload_paginated_report(folder_path, file_path, name, overwrite=False) |
PaginatedReport |
Upload .rdl |
PowerBIReport
Obtained from client.get_powerbi_report(path) or client.upload_powerbi_report(...).
Properties
| Property | Type | Description |
|---|---|---|
id |
str |
Catalog GUID |
name |
str |
Display name |
path |
str |
Full catalog path |
description |
str |
Description (empty string if absent) |
has_data_sources |
bool |
Whether the report has bound data sources |
Lifecycle
report.delete()
Data sources
sources = report.get_datasources() # List[DataSource]
report.set_datasources([ds1, ds2]) # full replace
Data model parameters
params = report.get_data_model_parameters()
report.set_data_model_parameters([
{"Name": "Environment", "Value": "Production"},
{"Name": "MaxRows", "Value": "10000"},
])
Cache refresh plans
plans = report.get_cache_refresh_plans() # List[CacheRefreshPlan]
plan = report.create_cache_refresh_plan(
description="Nightly refresh",
schedule=Schedule.daily(hour=2),
)
Catalog security (who can view/edit the report)
policies = report.get_policies()
# {"InheritParentSecurity": False, "Policies": [...]}
report.set_policies(policies) # full overwrite
report.add_user("CORP\\alice", ["Browser"])
report.add_user("CORP\\admins", ["Content Manager"])
report.remove_user("CORP\\alice")
Built-in role names: "Browser", "Content Manager", "Publisher", "Report Builder".
Row-level security (data model RLS)
roles = report.get_data_model_roles() # model role definitions
assignments = report.get_data_model_role_assignments()
report.set_data_model_role_assignments([
{"GroupUserName": "CORP\\alice", "Roles": ["Region_West"]},
{"GroupUserName": "CORP\\bob", "Roles": ["Region_East"]},
])
# Convenience helpers (read-modify-write):
report.add_rls_user("CORP\\alice", ["Region_West", "Region_North"])
report.remove_rls_user("CORP\\alice")
PaginatedReport
Obtained from client.get_paginated_report(path) or client.upload_paginated_report(...).
Same properties as PowerBIReport. Additional methods:
| Method | Description |
|---|---|
delete() |
Delete from catalog |
get_datasources() / set_datasources(datasources) |
Manage data sources |
get_parameters() / set_parameters(params) |
Read / update report parameter definitions |
get_cache_refresh_plans() |
List cache refresh plans |
create_cache_refresh_plan(description, schedule, event_type) |
Create a cache refresh plan |
get_policies() / set_policies(policy_data) |
Read / replace catalog security policies |
add_user(username, roles) |
Grant catalog access (read-modify-write) |
remove_user(username) |
Revoke catalog access (read-modify-write) |
Folder
Obtained from client.get_folder(path) or client.create_folder(path).
| Method | Description |
|---|---|
list_items() |
Raw catalog items (all types) |
list_powerbi_reports() |
List[PowerBIReport] in this folder |
list_paginated_reports() |
List[PaginatedReport] in this folder |
list_folders() |
Sub-folders |
delete() |
Delete folder and all contents |
get_policies() / set_policies(policy_data) |
Read / replace security policies |
add_user(username, roles) |
Grant access (read-modify-write) |
remove_user(username) |
Revoke access (read-modify-write) |
DataSource
from ssrs_library import DataSource
# SQL, integrated auth (default)
ds = DataSource("SalesDB", "Server=sql01;Database=Sales;")
# Stored credentials
ds = DataSource(
name="SalesDB",
connection_string="Server=sql01;Database=Sales;",
credential_retrieval="Store",
username="svc_report",
password="secret",
windows_credentials=False,
)
report.set_datasources([ds])
| Parameter | Default | Description |
|---|---|---|
name |
— | Data source name |
connection_string |
— | ADO.NET connection string |
data_source_type |
"SQL" |
Provider type (e.g. "Oracle", "OLEDB") |
enabled |
True |
Whether the data source is active |
id |
None |
GUID (set when reading from server) |
description |
None |
Optional description |
credential_retrieval |
"None" |
"None", "Integrated", or "Store" |
username |
None |
Username for "Store" retrieval |
password |
None |
Password for "Store" retrieval |
windows_credentials |
True |
Use Windows auth for stored creds |
Schedule
Helper for building cache-refresh plan schedules.
from ssrs_library import Schedule
# Daily at 02:00 (default)
Schedule.daily()
# Daily at 06:30
Schedule.daily(hour=6, minute=30)
# Every 3 days at 04:00
Schedule.daily(hour=4, interval=3)
# Every Monday and Friday at 08:30
Schedule.weekly(["Monday", "Friday"], hour=8, minute=30)
# Every two weeks on Wednesday
Schedule.weekly(["Wednesday"], interval=2)
# 1st of every month at 03:00 (default)
Schedule.monthly()
# 15th of January and July at 01:00
Schedule.monthly(day=15, months=["January", "July"], hour=1)
Pass a Schedule instance (or a raw {"Definition": {...}} dict) to
create_cache_refresh_plan() or plan.update().
CacheRefreshPlan
Obtained from report.get_cache_refresh_plans() or report.create_cache_refresh_plan(...).
| Method | Description |
|---|---|
execute() |
Trigger an immediate refresh |
update(description=None, schedule=None) |
Modify description and/or schedule |
delete() |
Delete this plan |
plan.update(
description="Updated nightly refresh",
schedule=Schedule.daily(hour=3),
)
plan.execute()
plan.delete()
Exceptions
from ssrs_library import PBIRSError, PBIRSNotFound, PBIRSConflict, PBIRSAuthError
| Exception | Raised when |
|---|---|
PBIRSAuthError |
HTTP 401 or 403 |
PBIRSNotFound |
HTTP 404 |
PBIRSConflict |
HTTP 409 (item already exists) |
PBIRSError |
Any other HTTP error |
Configuration patterns
Direct (script / notebook)
from ssrs_library import PBIRSClient
client = PBIRSClient(
base_url="http://pbirs.corp.local/reports",
username="alice",
password="secret",
domain="CORP",
)
Environment variables (CI/CD)
import os
from ssrs_library import PBIRSClient
client = PBIRSClient(
base_url=os.environ["PBIRS_URL"],
username=os.environ["PBIRS_USER"],
password=os.environ["PBIRS_PASSWORD"],
domain=os.environ.get("PBIRS_DOMAIN", ""),
)
.env file (local development)
from dotenv import load_dotenv
import os
from ssrs_library import PBIRSClient
load_dotenv()
client = PBIRSClient(
base_url=os.environ["PBIRS_URL"],
username=os.environ["PBIRS_USER"],
password=os.environ["PBIRS_PASSWORD"],
domain=os.environ.get("PBIRS_DOMAIN", ""),
)
CI/CD deploy example
from ssrs_library import PBIRSClient, DataSource, Schedule, PBIRSConflict
import os
client = PBIRSClient(
base_url=os.environ["PBIRS_URL"],
username=os.environ["PBIRS_USER"],
password=os.environ["PBIRS_PASSWORD"],
domain=os.environ.get("PBIRS_DOMAIN", ""),
)
# Ensure folder exists
try:
folder = client.create_folder("/Sales")
except PBIRSConflict:
folder = client.get_folder("/Sales")
# Deploy report
report = client.upload_powerbi_report(
folder_path="/Sales",
file_path="artifacts/Revenue.pbix",
name="Revenue",
overwrite=True,
)
# Point at production database
report.set_datasources([
DataSource(
"SalesDB",
f"Server={os.environ['DB_HOST']};Database=Sales;",
credential_retrieval="Store",
username=os.environ["DB_USER"],
password=os.environ["DB_PASSWORD"],
windows_credentials=False,
)
])
# Schedule nightly refresh at 02:00
for plan in report.get_cache_refresh_plans():
plan.delete()
report.create_cache_refresh_plan(
description="Nightly",
schedule=Schedule.daily(hour=2),
)
# Grant read access
report.add_user("CORP\\Sales Team", ["Browser"])
Testing
pip install pytest
pytest tests/ -v
All tests use unittest.mock — no live server required.
License
MIT License
Project details
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 ssrs_powerbi_library-1.2.1.tar.gz.
File metadata
- Download URL: ssrs_powerbi_library-1.2.1.tar.gz
- Upload date:
- Size: 32.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b313084421c0d2a3d885e1e0acc129087a84ccd5e495da041be22bddf6579d6
|
|
| MD5 |
0db72924a1c97166239c32352cf56939
|
|
| BLAKE2b-256 |
6ed81da3fbc8d4781abddfeda84be21f5d12cd79e3d5b32a82b8e5d66e707308
|
Provenance
The following attestation bundles were made for ssrs_powerbi_library-1.2.1.tar.gz:
Publisher:
release.yml on ipierre1/ssrs-powerbi-library
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ssrs_powerbi_library-1.2.1.tar.gz -
Subject digest:
1b313084421c0d2a3d885e1e0acc129087a84ccd5e495da041be22bddf6579d6 - Sigstore transparency entry: 1243259955
- Sigstore integration time:
-
Permalink:
ipierre1/ssrs-powerbi-library@f2fc07f28cd18e1a435926967ee3baeda71cfff8 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ipierre1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f2fc07f28cd18e1a435926967ee3baeda71cfff8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ssrs_powerbi_library-1.2.1-py3-none-any.whl.
File metadata
- Download URL: ssrs_powerbi_library-1.2.1-py3-none-any.whl
- Upload date:
- Size: 22.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f63aefd6acac4cecc3c7bc049cd2a87cba12ac4846991335400356f7ef8b9118
|
|
| MD5 |
5bcde10609de2e71e8b813a8a8d515fa
|
|
| BLAKE2b-256 |
076b28e23b9c216975746fa1c9dbacce1fad05c87fd0cb0508bb209b81182943
|
Provenance
The following attestation bundles were made for ssrs_powerbi_library-1.2.1-py3-none-any.whl:
Publisher:
release.yml on ipierre1/ssrs-powerbi-library
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ssrs_powerbi_library-1.2.1-py3-none-any.whl -
Subject digest:
f63aefd6acac4cecc3c7bc049cd2a87cba12ac4846991335400356f7ef8b9118 - Sigstore transparency entry: 1243259959
- Sigstore integration time:
-
Permalink:
ipierre1/ssrs-powerbi-library@f2fc07f28cd18e1a435926967ee3baeda71cfff8 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ipierre1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f2fc07f28cd18e1a435926967ee3baeda71cfff8 -
Trigger Event:
push
-
Statement type: