Skip to main content

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: ipierre1/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 exceptionsPBIRSNotFound, 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/ipierre1/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

ssrs_powerbi_library-1.2.6.tar.gz (33.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ssrs_powerbi_library-1.2.6-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file ssrs_powerbi_library-1.2.6.tar.gz.

File metadata

  • Download URL: ssrs_powerbi_library-1.2.6.tar.gz
  • Upload date:
  • Size: 33.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ssrs_powerbi_library-1.2.6.tar.gz
Algorithm Hash digest
SHA256 c1ea715ef97964f93b7db518f267ff4e00d0b95138d0ac8a8a7d6926b1c580ce
MD5 e19ed5da82037da0add7039f5e4aa461
BLAKE2b-256 6b7e566ba5efa61c6cef577733e092db0aa6317bcb89e11ad2c60fd9fbaad0d8

See more details on using hashes here.

Provenance

The following attestation bundles were made for ssrs_powerbi_library-1.2.6.tar.gz:

Publisher: release.yml on ipierre1/ssrs-powerbi-library

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ssrs_powerbi_library-1.2.6-py3-none-any.whl.

File metadata

File hashes

Hashes for ssrs_powerbi_library-1.2.6-py3-none-any.whl
Algorithm Hash digest
SHA256 dbe1a99c5553897597624ec4abf1164eba1dee179df18565b49a4e90c5ae17f4
MD5 c91ea6345a25b968e29c2719b2b99881
BLAKE2b-256 970c40b0cf8ed4aca1997fc89dd9fb8409c2cd9e6450b40edefe0635f5e132b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for ssrs_powerbi_library-1.2.6-py3-none-any.whl:

Publisher: release.yml on ipierre1/ssrs-powerbi-library

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page