msdev-kit 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- msdev_kit-0.1.0/PKG-INFO +269 -0
- msdev_kit-0.1.0/README.md +238 -0
- msdev_kit-0.1.0/msdev_kit/__init__.py +3 -0
- msdev_kit-0.1.0/msdev_kit/auth.py +35 -0
- msdev_kit-0.1.0/msdev_kit/fabric/__init__.py +11 -0
- msdev_kit-0.1.0/msdev_kit/fabric/admin.py +42 -0
- msdev_kit-0.1.0/msdev_kit/fabric/capacity.py +186 -0
- msdev_kit-0.1.0/msdev_kit/fabric/database.py +94 -0
- msdev_kit-0.1.0/msdev_kit/fabric/dataflow.py +1801 -0
- msdev_kit-0.1.0/msdev_kit/fabric/dataset.py +617 -0
- msdev_kit-0.1.0/msdev_kit/fabric/kql.py +66 -0
- msdev_kit-0.1.0/msdev_kit/fabric/notebook.py +88 -0
- msdev_kit-0.1.0/msdev_kit/fabric/operations.py +108 -0
- msdev_kit-0.1.0/msdev_kit/fabric/pipeline.py +505 -0
- msdev_kit-0.1.0/msdev_kit/fabric/report.py +1012 -0
- msdev_kit-0.1.0/msdev_kit/fabric/utilities.py +12 -0
- msdev_kit-0.1.0/msdev_kit/fabric/workspace.py +516 -0
- msdev_kit-0.1.0/msdev_kit/graph/__init__.py +1 -0
- msdev_kit-0.1.0/msdev_kit/graph/client.py +91 -0
- msdev_kit-0.1.0/msdev_kit/sharepoint/__init__.py +1 -0
- msdev_kit-0.1.0/msdev_kit/sharepoint/client.py +105 -0
- msdev_kit-0.1.0/pyproject.toml +41 -0
msdev_kit-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: msdev-kit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Microsoft developer toolkit: Fabric, MS Graph, and SharePoint
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Bernardo Rufino
|
|
7
|
+
Author-email: contact@bernardorufino.com
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Requires-Dist: azure-identity (>=1.24.0,<2)
|
|
17
|
+
Requires-Dist: azure-kusto-data (>=6.0.1,<7.0.0)
|
|
18
|
+
Requires-Dist: cryptography (>=46.0.6,<47.0.0)
|
|
19
|
+
Requires-Dist: numpy (==2.1.3)
|
|
20
|
+
Requires-Dist: openpyxl (==3.1.5)
|
|
21
|
+
Requires-Dist: pandas (==2.2.3)
|
|
22
|
+
Requires-Dist: pyodbc (==5.2.0)
|
|
23
|
+
Requires-Dist: python-dotenv (==1.0.1)
|
|
24
|
+
Requires-Dist: pyyaml (>=6.0.3,<7.0.0)
|
|
25
|
+
Requires-Dist: requests (>=2.33.0)
|
|
26
|
+
Requires-Dist: sqlalchemy (==2.0.44)
|
|
27
|
+
Project-URL: Homepage, https://github.com/Bernardo-Rufino/msdev-kit
|
|
28
|
+
Project-URL: Repository, https://github.com/Bernardo-Rufino/msdev-kit
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# msdev-kit
|
|
32
|
+
|
|
33
|
+
Microsoft developer toolkit for Python: Fabric/Power BI, MS Graph (Entra), and SharePoint.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
### Install from PyPI (recommended)
|
|
38
|
+
|
|
39
|
+
```shell
|
|
40
|
+
pip install msdev-kit
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Install from GitHub
|
|
44
|
+
|
|
45
|
+
```shell
|
|
46
|
+
pip install git+https://github.com/Bernardo-Rufino/msdev-kit.git
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Install for local development
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
git clone https://github.com/Bernardo-Rufino/msdev-kit.git
|
|
53
|
+
cd msdev-kit
|
|
54
|
+
pip install -e .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Prerequisites
|
|
60
|
+
|
|
61
|
+
- Python >= 3.10
|
|
62
|
+
- An Azure app registration with a client ID and client secret
|
|
63
|
+
|
|
64
|
+
## Getting Started
|
|
65
|
+
|
|
66
|
+
### Authentication
|
|
67
|
+
|
|
68
|
+
All classes use a shared `Auth` object. You can use different service principals for different services:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from msdev_kit import Auth
|
|
72
|
+
|
|
73
|
+
# service principal auth
|
|
74
|
+
auth = Auth(tenant_id="...", client_id="...", client_secret="...")
|
|
75
|
+
|
|
76
|
+
token = auth.get_token() # Power BI API (default)
|
|
77
|
+
token = auth.get_token('fabric') # Fabric API
|
|
78
|
+
token = auth.get_token('graph') # MS Graph API
|
|
79
|
+
token = auth.get_token('azure') # Azure Management API
|
|
80
|
+
|
|
81
|
+
# interactive user auth
|
|
82
|
+
token = auth.get_token_for_user('pbi')
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Credentials
|
|
86
|
+
|
|
87
|
+
Set up credentials via environment variables or a `.env` file:
|
|
88
|
+
|
|
89
|
+
```shell
|
|
90
|
+
TENANT_ID='<YOUR_TENANT_ID>'
|
|
91
|
+
CLIENT_ID='<YOUR_CLIENT_ID>'
|
|
92
|
+
CLIENT_SECRET='<YOUR_CLIENT_SECRET>'
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Sub-packages
|
|
98
|
+
|
|
99
|
+
### `msdev_kit.fabric` — Fabric & Power BI
|
|
100
|
+
|
|
101
|
+
All existing Fabric/Power BI classes, accessed via the `fabric` sub-package:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from msdev_kit.fabric import Workspace, Dataset, Report, Dataflow, Pipeline
|
|
105
|
+
from msdev_kit import Auth
|
|
106
|
+
|
|
107
|
+
auth = Auth(tenant_id, client_id, client_secret)
|
|
108
|
+
ws = Workspace(auth.get_token('fabric'))
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Workspace
|
|
112
|
+
|
|
113
|
+
Manage Power BI workspaces, users, and permissions.
|
|
114
|
+
|
|
115
|
+
| Method | Description |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `list_workspaces_for_user(...)` | List all workspaces the user has access to, with optional filters. |
|
|
118
|
+
| `get_workspace_details(workspace_id)` | Get details for a specific workspace. |
|
|
119
|
+
| `list_users(workspace_id)` | List all users in a workspace. |
|
|
120
|
+
| `list_reports(workspace_id)` | List all reports in a workspace. |
|
|
121
|
+
| `add_user(user_principal_name, workspace_id, access_right, user_type)` | Add a user or service principal to a workspace. |
|
|
122
|
+
| `update_user(user_principal_name, workspace_id, access_right)` | Update a user's role on a workspace. |
|
|
123
|
+
| `remove_user(user_principal_name, workspace_id)` | Remove a user from a workspace. |
|
|
124
|
+
| `batch_update_user(user, workspaces_list)` | Batch update a user across multiple workspaces. |
|
|
125
|
+
|
|
126
|
+
#### Dataset
|
|
127
|
+
|
|
128
|
+
Manage datasets (semantic models), permissions, and execute DAX queries.
|
|
129
|
+
|
|
130
|
+
| Method | Description |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `list_datasets(workspace_id)` | List all datasets in a workspace. |
|
|
133
|
+
| `get_dataset_details(workspace_id, dataset_id)` | Get details of a specific dataset. |
|
|
134
|
+
| `get_dataset_name(workspace_id, dataset_id)` | Resolve the display name of a dataset. Tries the PBI API first, falls back to the Fabric semantic models API. |
|
|
135
|
+
| `execute_query(workspace_id, dataset_id, query)` | Execute a DAX query against a dataset. Runs a COUNTROWS pre-check to detect if API row/value limits would truncate the result and returns truncation metadata. |
|
|
136
|
+
| `list_users(workspace_id, dataset_id)` | List users with access to a dataset. |
|
|
137
|
+
| `add_user(user_principal_name, workspace_id, dataset_id, access_right)` | Grant a user access to a dataset. |
|
|
138
|
+
| `update_user(user_principal_name, workspace_id, dataset_id, access_right)` | Update a user's access to a dataset. |
|
|
139
|
+
| `remove_user(user_principal_name, workspace_id, dataset_id)` | Remove a user's access to a dataset. |
|
|
140
|
+
| `list_dataset_related_reports(workspace_id, dataset_id)` | List all reports linked to a dataset. |
|
|
141
|
+
| `export_dataset_related_reports(workspace_id, dataset_id)` | Export all reports linked to a dataset as `.pbix` files. |
|
|
142
|
+
|
|
143
|
+
#### Report
|
|
144
|
+
|
|
145
|
+
Retrieve report metadata, definitions, visuals, and report-level measures.
|
|
146
|
+
|
|
147
|
+
| Method | Description |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `list_reports(workspace_id)` | List all reports in a workspace. |
|
|
150
|
+
| `get_report_metadata(workspace_id, report_id)` | Get metadata for a specific report. |
|
|
151
|
+
| `get_report_name(workspace_id, report_id)` | Get a report's display name. |
|
|
152
|
+
| `list_report_pages(workspace_id, report_id)` | List all pages in a report. |
|
|
153
|
+
| `get_report_json_pages_and_visuals(json_data, workspace_id, report_id)` | Parse a PBIR-Legacy report JSON and extract pages and visual details into a DataFrame. |
|
|
154
|
+
| `get_legacy_report_json(workspace_id, report_id, operations)` | Get and decode the full report definition for PBIR-Legacy reports. |
|
|
155
|
+
| `export_report(workspace_id, report_id, ...)` | Export a report as a `.pbix` file. |
|
|
156
|
+
| `get_report_measures(workspace_id, report_id, operations)` | Extract report-level measures and generate a DAX Query View script. Supports both PBIR and PBIR-Legacy formats. |
|
|
157
|
+
| `rebind_report(workspace_id, report_id, new_dataset_id, new_dataset_workspace_id, admin, dataset)` | Rebind a report to a new dataset/semantic model and migrate Read access to the new dataset. |
|
|
158
|
+
|
|
159
|
+
#### Dataflow
|
|
160
|
+
|
|
161
|
+
Manage Power BI and Fabric dataflows, including Gen1, Gen2, and Gen2 CI/CD.
|
|
162
|
+
|
|
163
|
+
| Method | Description |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `list_dataflows(workspace_id)` | List all dataflows in a workspace (Gen1, Gen2 standard, and Gen2 CI/CD). Results are merged and deduplicated with a `source` column. |
|
|
166
|
+
| `get_dataflow_details(workspace_id, dataflow_id)` | Get details of a specific dataflow. |
|
|
167
|
+
| `get_dataflow_name(workspace_id, dataflow_id)` | Resolve the display name of a dataflow. |
|
|
168
|
+
| `create_dataflow(workspace_id, dataflow_content)` | Create a new Power BI dataflow. |
|
|
169
|
+
| `delete_dataflow(workspace_id, dataflow_id, type='pbi')` | Delete a dataflow. Use `type='fabric'` for Fabric API. |
|
|
170
|
+
| `export_dataflow_json(workspace_id, dataflow_id, dataflow_name)` | Export a dataflow definition as JSON. |
|
|
171
|
+
| `get_dataflow_gen2_definition(workspace_id, dataflow_id)` | Get the definition of a Dataflow Gen2 CI/CD item. |
|
|
172
|
+
| `create_dataflow_gen2_from_definition(workspace_id, display_name, definition)` | Create a Dataflow Gen2 CI/CD from a definition. |
|
|
173
|
+
| `update_dataflow_gen2_from_definition(workspace_id, dataflow_id, display_name, definition)` | Update an existing Dataflow Gen2 CI/CD definition. |
|
|
174
|
+
| `get_data_destinations(workspace_id, dataflow_id)` | Get the data destination details for each table in a dataflow. |
|
|
175
|
+
| `change_data_destination(workspace_id, dataflow_id, destination_type, ...)` | Change a dataflow's data destination (Lakehouse/Warehouse). Supports `preview`, `replace`, and `create` modes. |
|
|
176
|
+
| `create_dataflow_with_new_destination(workspace_id, dataflow_id, ...)` | Create a new Gen2 CI/CD dataflow from an existing one with a different data destination. |
|
|
177
|
+
| `upgrade_to_gen2_cicd(...)` | Upgrade a Gen1 or Gen2 (standard) dataflow to Gen2 CI/CD. |
|
|
178
|
+
|
|
179
|
+
#### Pipeline
|
|
180
|
+
|
|
181
|
+
Manage Fabric Data Pipelines.
|
|
182
|
+
|
|
183
|
+
| Method | Description |
|
|
184
|
+
|---|---|
|
|
185
|
+
| `list_pipelines(workspace_id)` | List all Fabric Data Pipelines in a workspace. |
|
|
186
|
+
| `get_pipeline(workspace_id, pipeline_id)` | Get the metadata of a specific pipeline. |
|
|
187
|
+
| `get_pipeline_definition(workspace_id, pipeline_id)` | Get the full definition of a Fabric Data Pipeline. |
|
|
188
|
+
| `update_pipeline_definition(workspace_id, pipeline_id, definition)` | Update an existing pipeline definition. |
|
|
189
|
+
| `get_pipeline_activities(workspace_id, pipeline_id_or_name)` | Get the list of activities from a pipeline. |
|
|
190
|
+
| `find_pipelines_by_dataflow(workspace_id, dataflow_id_or_name)` | Find all pipelines in a workspace that reference a specific dataflow. |
|
|
191
|
+
| `replace_dataflow_id_in_pipeline(workspace_id, pipeline_id, old_dataflow_id, new_dataflow_id)` | Replace a dataflow ID in all RefreshDataflow activities of a pipeline. |
|
|
192
|
+
|
|
193
|
+
#### Other modules
|
|
194
|
+
|
|
195
|
+
| Module | Description |
|
|
196
|
+
|---|---|
|
|
197
|
+
| `Capacity` | Monitor and manage Power BI and Fabric capacities. |
|
|
198
|
+
| `Operations` | Track long-running Fabric API operations. |
|
|
199
|
+
| `Admin` | Power BI Admin API operations. |
|
|
200
|
+
| `KQLDatabase` | Query Kusto (KQL) databases in Microsoft Fabric. |
|
|
201
|
+
| `Notebook` | Manage Fabric notebooks. |
|
|
202
|
+
| `Database` | Query and write to SQL databases (Lakehouse, Warehouse) via ODBC. |
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### `msdev_kit.graph` — MS Graph (Entra)
|
|
207
|
+
|
|
208
|
+
Manage Entra ID (Azure AD) users and groups via the MS Graph API.
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from msdev_kit import Auth
|
|
212
|
+
from msdev_kit.graph import GraphClient
|
|
213
|
+
|
|
214
|
+
auth = Auth(tenant_id, client_id, client_secret)
|
|
215
|
+
graph = GraphClient(auth)
|
|
216
|
+
|
|
217
|
+
user_id = graph.get_user_id('user@company.com')
|
|
218
|
+
group_id = graph.get_group_id('Data Team')
|
|
219
|
+
members = graph.list_group_members(group_id)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
| Method | Description |
|
|
223
|
+
|---|---|
|
|
224
|
+
| `get_user_id(email)` | Resolve user object ID by UPN/email, with mail fallback. |
|
|
225
|
+
| `get_group_id(group_name)` | Resolve Entra group object ID by display name. |
|
|
226
|
+
| `list_group_members(group_id)` | Paginated member list (id, displayName, mail, UPN). |
|
|
227
|
+
| `add_group_member(group_id, user_id)` | Add user to group. Silently ignores already-member errors. |
|
|
228
|
+
| `remove_group_member(group_id, user_id)` | Remove user from group. Silently ignores 404/403. |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
### `msdev_kit.sharepoint` — SharePoint
|
|
233
|
+
|
|
234
|
+
Manage SharePoint files and folders via MS Graph API (no ACS/Office365 dependency).
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from msdev_kit import Auth
|
|
238
|
+
from msdev_kit.sharepoint import SharePointClient
|
|
239
|
+
|
|
240
|
+
auth = Auth(tenant_id, client_id, client_secret)
|
|
241
|
+
sp = SharePointClient(auth, sp_hostname='company', sp_site_path='sites/DataTeam')
|
|
242
|
+
|
|
243
|
+
sp.download_file('/Reports/monthly.xlsx', local_dir='./downloads')
|
|
244
|
+
sp.upload_file('/Reports/updated.xlsx', source='./local/updated.xlsx')
|
|
245
|
+
sp.create_folder('/Reports/2026')
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
| Method | Description |
|
|
249
|
+
|---|---|
|
|
250
|
+
| `download_file(file_path, local_dir)` | Download a file from the default document library. Returns local file path. |
|
|
251
|
+
| `upload_file(remote_path, source, content_type?)` | Upload/overwrite a file. `source` is a local file path (str) or raw bytes. |
|
|
252
|
+
| `create_folder(folder_path)` | Create a folder and all intermediate folders. |
|
|
253
|
+
|
|
254
|
+
Hostname and site path inputs are normalized automatically — accepts short names (`company`), FQDNs (`company.sharepoint.com`), or full URLs (`https://company.sharepoint.com`).
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Limitations
|
|
259
|
+
|
|
260
|
+
- The Power BI REST API has a **200 requests per hour** rate limit.
|
|
261
|
+
- Not all users can be updated via the API. See Microsoft docs: [Dataset permissions](https://learn.microsoft.com/en-us/power-bi/developer/embedded/datasets-permissions#get-and-update-dataset-permissions-with-apis).
|
|
262
|
+
- **Dataset query limits** (executeQueries API):
|
|
263
|
+
- Max **100,000 rows** or **1,000,000 values** (rows x columns) per query, whichever is hit first.
|
|
264
|
+
- Max **15 MB** of data per query.
|
|
265
|
+
- **120 query requests per minute** per user.
|
|
266
|
+
- Only **DAX** queries are supported (no MDX, INFO functions, or DMV).
|
|
267
|
+
- Datasets hosted in Azure Analysis Services or with a live connection to on-premises AAS are not supported.
|
|
268
|
+
- Service Principals are not supported for datasets with RLS or SSO enabled.
|
|
269
|
+
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# msdev-kit
|
|
2
|
+
|
|
3
|
+
Microsoft developer toolkit for Python: Fabric/Power BI, MS Graph (Entra), and SharePoint.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Install from PyPI (recommended)
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
pip install msdev-kit
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Install from GitHub
|
|
14
|
+
|
|
15
|
+
```shell
|
|
16
|
+
pip install git+https://github.com/Bernardo-Rufino/msdev-kit.git
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Install for local development
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
git clone https://github.com/Bernardo-Rufino/msdev-kit.git
|
|
23
|
+
cd msdev-kit
|
|
24
|
+
pip install -e .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Prerequisites
|
|
30
|
+
|
|
31
|
+
- Python >= 3.10
|
|
32
|
+
- An Azure app registration with a client ID and client secret
|
|
33
|
+
|
|
34
|
+
## Getting Started
|
|
35
|
+
|
|
36
|
+
### Authentication
|
|
37
|
+
|
|
38
|
+
All classes use a shared `Auth` object. You can use different service principals for different services:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from msdev_kit import Auth
|
|
42
|
+
|
|
43
|
+
# service principal auth
|
|
44
|
+
auth = Auth(tenant_id="...", client_id="...", client_secret="...")
|
|
45
|
+
|
|
46
|
+
token = auth.get_token() # Power BI API (default)
|
|
47
|
+
token = auth.get_token('fabric') # Fabric API
|
|
48
|
+
token = auth.get_token('graph') # MS Graph API
|
|
49
|
+
token = auth.get_token('azure') # Azure Management API
|
|
50
|
+
|
|
51
|
+
# interactive user auth
|
|
52
|
+
token = auth.get_token_for_user('pbi')
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Credentials
|
|
56
|
+
|
|
57
|
+
Set up credentials via environment variables or a `.env` file:
|
|
58
|
+
|
|
59
|
+
```shell
|
|
60
|
+
TENANT_ID='<YOUR_TENANT_ID>'
|
|
61
|
+
CLIENT_ID='<YOUR_CLIENT_ID>'
|
|
62
|
+
CLIENT_SECRET='<YOUR_CLIENT_SECRET>'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Sub-packages
|
|
68
|
+
|
|
69
|
+
### `msdev_kit.fabric` — Fabric & Power BI
|
|
70
|
+
|
|
71
|
+
All existing Fabric/Power BI classes, accessed via the `fabric` sub-package:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from msdev_kit.fabric import Workspace, Dataset, Report, Dataflow, Pipeline
|
|
75
|
+
from msdev_kit import Auth
|
|
76
|
+
|
|
77
|
+
auth = Auth(tenant_id, client_id, client_secret)
|
|
78
|
+
ws = Workspace(auth.get_token('fabric'))
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Workspace
|
|
82
|
+
|
|
83
|
+
Manage Power BI workspaces, users, and permissions.
|
|
84
|
+
|
|
85
|
+
| Method | Description |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `list_workspaces_for_user(...)` | List all workspaces the user has access to, with optional filters. |
|
|
88
|
+
| `get_workspace_details(workspace_id)` | Get details for a specific workspace. |
|
|
89
|
+
| `list_users(workspace_id)` | List all users in a workspace. |
|
|
90
|
+
| `list_reports(workspace_id)` | List all reports in a workspace. |
|
|
91
|
+
| `add_user(user_principal_name, workspace_id, access_right, user_type)` | Add a user or service principal to a workspace. |
|
|
92
|
+
| `update_user(user_principal_name, workspace_id, access_right)` | Update a user's role on a workspace. |
|
|
93
|
+
| `remove_user(user_principal_name, workspace_id)` | Remove a user from a workspace. |
|
|
94
|
+
| `batch_update_user(user, workspaces_list)` | Batch update a user across multiple workspaces. |
|
|
95
|
+
|
|
96
|
+
#### Dataset
|
|
97
|
+
|
|
98
|
+
Manage datasets (semantic models), permissions, and execute DAX queries.
|
|
99
|
+
|
|
100
|
+
| Method | Description |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `list_datasets(workspace_id)` | List all datasets in a workspace. |
|
|
103
|
+
| `get_dataset_details(workspace_id, dataset_id)` | Get details of a specific dataset. |
|
|
104
|
+
| `get_dataset_name(workspace_id, dataset_id)` | Resolve the display name of a dataset. Tries the PBI API first, falls back to the Fabric semantic models API. |
|
|
105
|
+
| `execute_query(workspace_id, dataset_id, query)` | Execute a DAX query against a dataset. Runs a COUNTROWS pre-check to detect if API row/value limits would truncate the result and returns truncation metadata. |
|
|
106
|
+
| `list_users(workspace_id, dataset_id)` | List users with access to a dataset. |
|
|
107
|
+
| `add_user(user_principal_name, workspace_id, dataset_id, access_right)` | Grant a user access to a dataset. |
|
|
108
|
+
| `update_user(user_principal_name, workspace_id, dataset_id, access_right)` | Update a user's access to a dataset. |
|
|
109
|
+
| `remove_user(user_principal_name, workspace_id, dataset_id)` | Remove a user's access to a dataset. |
|
|
110
|
+
| `list_dataset_related_reports(workspace_id, dataset_id)` | List all reports linked to a dataset. |
|
|
111
|
+
| `export_dataset_related_reports(workspace_id, dataset_id)` | Export all reports linked to a dataset as `.pbix` files. |
|
|
112
|
+
|
|
113
|
+
#### Report
|
|
114
|
+
|
|
115
|
+
Retrieve report metadata, definitions, visuals, and report-level measures.
|
|
116
|
+
|
|
117
|
+
| Method | Description |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `list_reports(workspace_id)` | List all reports in a workspace. |
|
|
120
|
+
| `get_report_metadata(workspace_id, report_id)` | Get metadata for a specific report. |
|
|
121
|
+
| `get_report_name(workspace_id, report_id)` | Get a report's display name. |
|
|
122
|
+
| `list_report_pages(workspace_id, report_id)` | List all pages in a report. |
|
|
123
|
+
| `get_report_json_pages_and_visuals(json_data, workspace_id, report_id)` | Parse a PBIR-Legacy report JSON and extract pages and visual details into a DataFrame. |
|
|
124
|
+
| `get_legacy_report_json(workspace_id, report_id, operations)` | Get and decode the full report definition for PBIR-Legacy reports. |
|
|
125
|
+
| `export_report(workspace_id, report_id, ...)` | Export a report as a `.pbix` file. |
|
|
126
|
+
| `get_report_measures(workspace_id, report_id, operations)` | Extract report-level measures and generate a DAX Query View script. Supports both PBIR and PBIR-Legacy formats. |
|
|
127
|
+
| `rebind_report(workspace_id, report_id, new_dataset_id, new_dataset_workspace_id, admin, dataset)` | Rebind a report to a new dataset/semantic model and migrate Read access to the new dataset. |
|
|
128
|
+
|
|
129
|
+
#### Dataflow
|
|
130
|
+
|
|
131
|
+
Manage Power BI and Fabric dataflows, including Gen1, Gen2, and Gen2 CI/CD.
|
|
132
|
+
|
|
133
|
+
| Method | Description |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `list_dataflows(workspace_id)` | List all dataflows in a workspace (Gen1, Gen2 standard, and Gen2 CI/CD). Results are merged and deduplicated with a `source` column. |
|
|
136
|
+
| `get_dataflow_details(workspace_id, dataflow_id)` | Get details of a specific dataflow. |
|
|
137
|
+
| `get_dataflow_name(workspace_id, dataflow_id)` | Resolve the display name of a dataflow. |
|
|
138
|
+
| `create_dataflow(workspace_id, dataflow_content)` | Create a new Power BI dataflow. |
|
|
139
|
+
| `delete_dataflow(workspace_id, dataflow_id, type='pbi')` | Delete a dataflow. Use `type='fabric'` for Fabric API. |
|
|
140
|
+
| `export_dataflow_json(workspace_id, dataflow_id, dataflow_name)` | Export a dataflow definition as JSON. |
|
|
141
|
+
| `get_dataflow_gen2_definition(workspace_id, dataflow_id)` | Get the definition of a Dataflow Gen2 CI/CD item. |
|
|
142
|
+
| `create_dataflow_gen2_from_definition(workspace_id, display_name, definition)` | Create a Dataflow Gen2 CI/CD from a definition. |
|
|
143
|
+
| `update_dataflow_gen2_from_definition(workspace_id, dataflow_id, display_name, definition)` | Update an existing Dataflow Gen2 CI/CD definition. |
|
|
144
|
+
| `get_data_destinations(workspace_id, dataflow_id)` | Get the data destination details for each table in a dataflow. |
|
|
145
|
+
| `change_data_destination(workspace_id, dataflow_id, destination_type, ...)` | Change a dataflow's data destination (Lakehouse/Warehouse). Supports `preview`, `replace`, and `create` modes. |
|
|
146
|
+
| `create_dataflow_with_new_destination(workspace_id, dataflow_id, ...)` | Create a new Gen2 CI/CD dataflow from an existing one with a different data destination. |
|
|
147
|
+
| `upgrade_to_gen2_cicd(...)` | Upgrade a Gen1 or Gen2 (standard) dataflow to Gen2 CI/CD. |
|
|
148
|
+
|
|
149
|
+
#### Pipeline
|
|
150
|
+
|
|
151
|
+
Manage Fabric Data Pipelines.
|
|
152
|
+
|
|
153
|
+
| Method | Description |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `list_pipelines(workspace_id)` | List all Fabric Data Pipelines in a workspace. |
|
|
156
|
+
| `get_pipeline(workspace_id, pipeline_id)` | Get the metadata of a specific pipeline. |
|
|
157
|
+
| `get_pipeline_definition(workspace_id, pipeline_id)` | Get the full definition of a Fabric Data Pipeline. |
|
|
158
|
+
| `update_pipeline_definition(workspace_id, pipeline_id, definition)` | Update an existing pipeline definition. |
|
|
159
|
+
| `get_pipeline_activities(workspace_id, pipeline_id_or_name)` | Get the list of activities from a pipeline. |
|
|
160
|
+
| `find_pipelines_by_dataflow(workspace_id, dataflow_id_or_name)` | Find all pipelines in a workspace that reference a specific dataflow. |
|
|
161
|
+
| `replace_dataflow_id_in_pipeline(workspace_id, pipeline_id, old_dataflow_id, new_dataflow_id)` | Replace a dataflow ID in all RefreshDataflow activities of a pipeline. |
|
|
162
|
+
|
|
163
|
+
#### Other modules
|
|
164
|
+
|
|
165
|
+
| Module | Description |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `Capacity` | Monitor and manage Power BI and Fabric capacities. |
|
|
168
|
+
| `Operations` | Track long-running Fabric API operations. |
|
|
169
|
+
| `Admin` | Power BI Admin API operations. |
|
|
170
|
+
| `KQLDatabase` | Query Kusto (KQL) databases in Microsoft Fabric. |
|
|
171
|
+
| `Notebook` | Manage Fabric notebooks. |
|
|
172
|
+
| `Database` | Query and write to SQL databases (Lakehouse, Warehouse) via ODBC. |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### `msdev_kit.graph` — MS Graph (Entra)
|
|
177
|
+
|
|
178
|
+
Manage Entra ID (Azure AD) users and groups via the MS Graph API.
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from msdev_kit import Auth
|
|
182
|
+
from msdev_kit.graph import GraphClient
|
|
183
|
+
|
|
184
|
+
auth = Auth(tenant_id, client_id, client_secret)
|
|
185
|
+
graph = GraphClient(auth)
|
|
186
|
+
|
|
187
|
+
user_id = graph.get_user_id('user@company.com')
|
|
188
|
+
group_id = graph.get_group_id('Data Team')
|
|
189
|
+
members = graph.list_group_members(group_id)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
| Method | Description |
|
|
193
|
+
|---|---|
|
|
194
|
+
| `get_user_id(email)` | Resolve user object ID by UPN/email, with mail fallback. |
|
|
195
|
+
| `get_group_id(group_name)` | Resolve Entra group object ID by display name. |
|
|
196
|
+
| `list_group_members(group_id)` | Paginated member list (id, displayName, mail, UPN). |
|
|
197
|
+
| `add_group_member(group_id, user_id)` | Add user to group. Silently ignores already-member errors. |
|
|
198
|
+
| `remove_group_member(group_id, user_id)` | Remove user from group. Silently ignores 404/403. |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
### `msdev_kit.sharepoint` — SharePoint
|
|
203
|
+
|
|
204
|
+
Manage SharePoint files and folders via MS Graph API (no ACS/Office365 dependency).
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from msdev_kit import Auth
|
|
208
|
+
from msdev_kit.sharepoint import SharePointClient
|
|
209
|
+
|
|
210
|
+
auth = Auth(tenant_id, client_id, client_secret)
|
|
211
|
+
sp = SharePointClient(auth, sp_hostname='company', sp_site_path='sites/DataTeam')
|
|
212
|
+
|
|
213
|
+
sp.download_file('/Reports/monthly.xlsx', local_dir='./downloads')
|
|
214
|
+
sp.upload_file('/Reports/updated.xlsx', source='./local/updated.xlsx')
|
|
215
|
+
sp.create_folder('/Reports/2026')
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
| Method | Description |
|
|
219
|
+
|---|---|
|
|
220
|
+
| `download_file(file_path, local_dir)` | Download a file from the default document library. Returns local file path. |
|
|
221
|
+
| `upload_file(remote_path, source, content_type?)` | Upload/overwrite a file. `source` is a local file path (str) or raw bytes. |
|
|
222
|
+
| `create_folder(folder_path)` | Create a folder and all intermediate folders. |
|
|
223
|
+
|
|
224
|
+
Hostname and site path inputs are normalized automatically — accepts short names (`company`), FQDNs (`company.sharepoint.com`), or full URLs (`https://company.sharepoint.com`).
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Limitations
|
|
229
|
+
|
|
230
|
+
- The Power BI REST API has a **200 requests per hour** rate limit.
|
|
231
|
+
- Not all users can be updated via the API. See Microsoft docs: [Dataset permissions](https://learn.microsoft.com/en-us/power-bi/developer/embedded/datasets-permissions#get-and-update-dataset-permissions-with-apis).
|
|
232
|
+
- **Dataset query limits** (executeQueries API):
|
|
233
|
+
- Max **100,000 rows** or **1,000,000 values** (rows x columns) per query, whichever is hit first.
|
|
234
|
+
- Max **15 MB** of data per query.
|
|
235
|
+
- **120 query requests per minute** per user.
|
|
236
|
+
- Only **DAX** queries are supported (no MDX, INFO functions, or DMV).
|
|
237
|
+
- Datasets hosted in Azure Analysis Services or with a live connection to on-premises AAS are not supported.
|
|
238
|
+
- Service Principals are not supported for datasets with RLS or SSO enabled.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from azure.identity import ClientSecretCredential, InteractiveBrowserCredential, TokenCachePersistenceOptions
|
|
2
|
+
|
|
3
|
+
_SCOPES = {
|
|
4
|
+
'pbi': 'https://analysis.windows.net/powerbi/api/.default',
|
|
5
|
+
'fabric': 'https://api.fabric.microsoft.com/.default',
|
|
6
|
+
'azure': 'https://management.azure.com/.default',
|
|
7
|
+
'graph': 'https://graph.microsoft.com/.default',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Auth:
|
|
12
|
+
|
|
13
|
+
def __init__(self, tenant_id: str, client_id: str, client_secret: str):
|
|
14
|
+
self.tenant_id = tenant_id
|
|
15
|
+
self.client_id = client_id
|
|
16
|
+
self.client_secret = client_secret
|
|
17
|
+
self._credential = ClientSecretCredential(
|
|
18
|
+
authority='https://login.microsoftonline.com/',
|
|
19
|
+
tenant_id=tenant_id,
|
|
20
|
+
client_id=client_id,
|
|
21
|
+
client_secret=client_secret,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def get_token(self, service: str = 'pbi') -> str:
|
|
25
|
+
scope = _SCOPES.get(service)
|
|
26
|
+
if not scope:
|
|
27
|
+
raise ValueError(f"Invalid service specified. Choose one of: {', '.join(_SCOPES)}")
|
|
28
|
+
return self._credential.get_token(scope).token
|
|
29
|
+
|
|
30
|
+
def get_token_for_user(self, service: str = 'pbi') -> str:
|
|
31
|
+
scope = _SCOPES.get(service)
|
|
32
|
+
if not scope:
|
|
33
|
+
raise ValueError(f"Invalid service specified. Choose one of: {', '.join(_SCOPES)}")
|
|
34
|
+
auth = InteractiveBrowserCredential(cache_persistence_options=TokenCachePersistenceOptions())
|
|
35
|
+
return auth.get_token(scope).token
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .workspace import Workspace
|
|
2
|
+
from .dataset import Dataset
|
|
3
|
+
from .report import Report
|
|
4
|
+
from .dataflow import Dataflow
|
|
5
|
+
from .capacity import Capacity
|
|
6
|
+
from .admin import Admin
|
|
7
|
+
from .operations import Operations
|
|
8
|
+
from .kql import KQLDatabase
|
|
9
|
+
from .database import Database
|
|
10
|
+
from .pipeline import Pipeline
|
|
11
|
+
from .notebook import Notebook
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import json
|
|
3
|
+
from typing import Dict
|
|
4
|
+
|
|
5
|
+
class Admin:
|
|
6
|
+
|
|
7
|
+
def __init__(self, token: str):
|
|
8
|
+
"""
|
|
9
|
+
Initialize variables for Power BI Admin API interactions.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
token (str): The bearer token for authorization.
|
|
13
|
+
"""
|
|
14
|
+
self.main_url = 'https://api.powerbi.com/v1.0/myorg/admin'
|
|
15
|
+
self.token = token
|
|
16
|
+
self.headers = {'Authorization': f'Bearer {self.token}'}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_report_users_as_admin(self, report_id: str) -> Dict:
|
|
20
|
+
"""
|
|
21
|
+
Retrieves a list of users with access to a specific report as an administrator.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
report_id (str): The ID of the report to get users for.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Dict: A dictionary containing the status message and content (list of users).
|
|
28
|
+
"""
|
|
29
|
+
request_url = f'{self.main_url}/reports/{report_id}/users'
|
|
30
|
+
|
|
31
|
+
r = requests.get(url=request_url, headers=self.headers)
|
|
32
|
+
|
|
33
|
+
status = r.status_code
|
|
34
|
+
response = json.loads(r.content)
|
|
35
|
+
|
|
36
|
+
if status == 200:
|
|
37
|
+
return {'message': 'Success', 'content': response.get('value', [])}
|
|
38
|
+
else:
|
|
39
|
+
error_message = response.get('error', {}).get('message', 'Unknown error')
|
|
40
|
+
return {'message': {'error': error_message, 'status_code': status}, 'content': ''}
|
|
41
|
+
|
|
42
|
+
|