msdev-kit 0.1.0__tar.gz → 0.1.2__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 → msdev_kit-0.1.2}/PKG-INFO +191 -56
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/README.md +190 -55
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/__init__.py +1 -1
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/pyproject.toml +1 -1
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/auth.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/__init__.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/admin.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/capacity.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/database.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/dataflow.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/dataset.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/kql.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/notebook.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/operations.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/pipeline.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/report.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/utilities.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/fabric/workspace.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/graph/__init__.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/graph/client.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/sharepoint/__init__.py +0 -0
- {msdev_kit-0.1.0 → msdev_kit-0.1.2}/msdev_kit/sharepoint/client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: msdev-kit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Microsoft developer toolkit: Fabric, MS Graph, and SharePoint
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Bernardo Rufino
|
|
@@ -32,21 +32,29 @@ Description-Content-Type: text/markdown
|
|
|
32
32
|
|
|
33
33
|
Microsoft developer toolkit for Python: Fabric/Power BI, MS Graph (Entra), and SharePoint.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
[](https://pypi.org/project/msdev-kit/)
|
|
36
|
+
[](https://pypi.org/project/msdev-kit/)
|
|
37
|
+
[](https://opensource.org/licenses/MIT)
|
|
38
|
+
|
|
39
|
+
## Table of Contents
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
[Installation](https://github.com/Bernardo-Rufino/msdev-kit#installation) · [Quick Start](https://github.com/Bernardo-Rufino/msdev-kit#quick-start) · [Authentication](https://github.com/Bernardo-Rufino/msdev-kit#authentication) · [Fabric & Power BI](https://github.com/Bernardo-Rufino/msdev-kit#fabric--power-bi) · [MS Graph (Entra)](https://github.com/Bernardo-Rufino/msdev-kit#ms-graph-entra) · [SharePoint](https://github.com/Bernardo-Rufino/msdev-kit#sharepoint) · [Limitations](https://github.com/Bernardo-Rufino/msdev-kit#limitations)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
38
46
|
|
|
39
47
|
```shell
|
|
40
48
|
pip install msdev-kit
|
|
41
49
|
```
|
|
42
50
|
|
|
43
|
-
|
|
51
|
+
Or install from GitHub:
|
|
44
52
|
|
|
45
53
|
```shell
|
|
46
54
|
pip install git+https://github.com/Bernardo-Rufino/msdev-kit.git
|
|
47
55
|
```
|
|
48
56
|
|
|
49
|
-
|
|
57
|
+
For local development:
|
|
50
58
|
|
|
51
59
|
```shell
|
|
52
60
|
git clone https://github.com/Bernardo-Rufino/msdev-kit.git
|
|
@@ -54,32 +62,64 @@ cd msdev-kit
|
|
|
54
62
|
pip install -e .
|
|
55
63
|
```
|
|
56
64
|
|
|
65
|
+
**Requirements:** Python >= 3.10, an Azure app registration with a client ID and client secret.
|
|
66
|
+
|
|
57
67
|
---
|
|
58
68
|
|
|
59
|
-
##
|
|
69
|
+
## Quick Start
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
```python
|
|
72
|
+
from msdev_kit import Auth
|
|
73
|
+
from msdev_kit.fabric import Workspace
|
|
74
|
+
from msdev_kit.graph import GraphClient
|
|
75
|
+
from msdev_kit.sharepoint import SharePointClient
|
|
63
76
|
|
|
64
|
-
|
|
77
|
+
# authenticate
|
|
78
|
+
auth = Auth(tenant_id="...", client_id="...", client_secret="...")
|
|
65
79
|
|
|
66
|
-
|
|
80
|
+
# fabric: list workspaces
|
|
81
|
+
ws = Workspace(auth.get_token('fabric'))
|
|
82
|
+
workspaces = ws.list_workspaces_for_user()
|
|
67
83
|
|
|
68
|
-
|
|
84
|
+
# graph: look up a user
|
|
85
|
+
graph = GraphClient(auth)
|
|
86
|
+
user_id = graph.get_user_id('user@company.com')
|
|
87
|
+
|
|
88
|
+
# sharepoint: download a file
|
|
89
|
+
sp = SharePointClient(auth, sp_hostname='company', sp_site_path='sites/DataTeam')
|
|
90
|
+
sp.download_file('/Reports/monthly.xlsx', local_dir='./downloads')
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Authentication
|
|
96
|
+
|
|
97
|
+
All classes use a shared `Auth` object. You can use different service principals for different services — instantiate one `Auth` per SPN:
|
|
69
98
|
|
|
70
99
|
```python
|
|
71
100
|
from msdev_kit import Auth
|
|
72
101
|
|
|
73
102
|
# service principal auth
|
|
74
|
-
|
|
103
|
+
fabric_auth = Auth(tenant_id="...", client_id="spn-a", client_secret="...")
|
|
104
|
+
graph_auth = Auth(tenant_id="...", client_id="spn-b", client_secret="...")
|
|
105
|
+
```
|
|
75
106
|
|
|
76
|
-
|
|
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
|
|
107
|
+
### Supported scopes
|
|
80
108
|
|
|
81
|
-
|
|
82
|
-
|
|
109
|
+
| Service | Scope | Usage |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `pbi` (default) | Power BI API | `auth.get_token()` or `auth.get_token('pbi')` |
|
|
112
|
+
| `fabric` | Fabric API | `auth.get_token('fabric')` |
|
|
113
|
+
| `graph` | MS Graph API | `auth.get_token('graph')` |
|
|
114
|
+
| `azure` | Azure Management API | `auth.get_token('azure')` |
|
|
115
|
+
|
|
116
|
+
### Interactive user auth
|
|
117
|
+
|
|
118
|
+
For scenarios requiring user context (e.g., RLS-enabled datasets):
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
token = auth.get_token_for_user('pbi') # opens browser for login
|
|
122
|
+
token = auth.get_token_for_user('fabric')
|
|
83
123
|
```
|
|
84
124
|
|
|
85
125
|
### Credentials
|
|
@@ -94,24 +134,34 @@ CLIENT_SECRET='<YOUR_CLIENT_SECRET>'
|
|
|
94
134
|
|
|
95
135
|
---
|
|
96
136
|
|
|
97
|
-
##
|
|
98
|
-
|
|
99
|
-
### `msdev_kit.fabric` — Fabric & Power BI
|
|
100
|
-
|
|
101
|
-
All existing Fabric/Power BI classes, accessed via the `fabric` sub-package:
|
|
137
|
+
## Fabric & Power BI
|
|
102
138
|
|
|
103
139
|
```python
|
|
104
|
-
from msdev_kit.fabric import Workspace, Dataset, Report, Dataflow, Pipeline
|
|
105
140
|
from msdev_kit import Auth
|
|
141
|
+
from msdev_kit.fabric import Workspace, Dataset, Report, Dataflow, Pipeline
|
|
106
142
|
|
|
107
143
|
auth = Auth(tenant_id, client_id, client_secret)
|
|
108
|
-
ws = Workspace(auth.get_token('fabric'))
|
|
109
144
|
```
|
|
110
145
|
|
|
111
|
-
|
|
146
|
+
Fabric classes take a token string — call `auth.get_token('fabric')` or `auth.get_token('pbi')` depending on the API.
|
|
147
|
+
|
|
148
|
+
- [Workspace](https://github.com/Bernardo-Rufino/msdev-kit#workspace) — workspaces, users, permissions
|
|
149
|
+
- [Dataset](https://github.com/Bernardo-Rufino/msdev-kit#dataset) — semantic models, DAX queries, permissions
|
|
150
|
+
- [Report](https://github.com/Bernardo-Rufino/msdev-kit#report) — metadata, definitions, visuals, measures
|
|
151
|
+
- [Dataflow](https://github.com/Bernardo-Rufino/msdev-kit#dataflow) — Gen1, Gen2, Gen2 CI/CD management
|
|
152
|
+
- [Pipeline](https://github.com/Bernardo-Rufino/msdev-kit#pipeline) — Data Pipeline management
|
|
153
|
+
- [Other modules](https://github.com/Bernardo-Rufino/msdev-kit#other-modules) — Capacity, Admin, KQL, Notebook, Database
|
|
154
|
+
|
|
155
|
+
### Workspace
|
|
112
156
|
|
|
113
157
|
Manage Power BI workspaces, users, and permissions.
|
|
114
158
|
|
|
159
|
+
```python
|
|
160
|
+
ws = Workspace(auth.get_token('pbi'))
|
|
161
|
+
workspaces = ws.list_workspaces_for_user()
|
|
162
|
+
ws.add_user('user@company.com', workspace_id, 'Member', 'User')
|
|
163
|
+
```
|
|
164
|
+
|
|
115
165
|
| Method | Description |
|
|
116
166
|
|---|---|
|
|
117
167
|
| `list_workspaces_for_user(...)` | List all workspaces the user has access to, with optional filters. |
|
|
@@ -123,16 +173,21 @@ Manage Power BI workspaces, users, and permissions.
|
|
|
123
173
|
| `remove_user(user_principal_name, workspace_id)` | Remove a user from a workspace. |
|
|
124
174
|
| `batch_update_user(user, workspaces_list)` | Batch update a user across multiple workspaces. |
|
|
125
175
|
|
|
126
|
-
|
|
176
|
+
### Dataset
|
|
127
177
|
|
|
128
178
|
Manage datasets (semantic models), permissions, and execute DAX queries.
|
|
129
179
|
|
|
180
|
+
```python
|
|
181
|
+
ds = Dataset(auth.get_token('pbi'))
|
|
182
|
+
result = ds.execute_query(workspace_id, dataset_id, "EVALUATE Sales")
|
|
183
|
+
```
|
|
184
|
+
|
|
130
185
|
| Method | Description |
|
|
131
186
|
|---|---|
|
|
132
187
|
| `list_datasets(workspace_id)` | List all datasets in a workspace. |
|
|
133
188
|
| `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
|
|
135
|
-
| `execute_query(workspace_id, dataset_id, query)` | Execute a DAX query
|
|
189
|
+
| `get_dataset_name(workspace_id, dataset_id)` | Resolve the display name of a dataset. Tries PBI API first, falls back to Fabric semantic models API. |
|
|
190
|
+
| `execute_query(workspace_id, dataset_id, query)` | Execute a DAX query. Runs a COUNTROWS pre-check to detect truncation. |
|
|
136
191
|
| `list_users(workspace_id, dataset_id)` | List users with access to a dataset. |
|
|
137
192
|
| `add_user(user_principal_name, workspace_id, dataset_id, access_right)` | Grant a user access to a dataset. |
|
|
138
193
|
| `update_user(user_principal_name, workspace_id, dataset_id, access_right)` | Update a user's access to a dataset. |
|
|
@@ -140,29 +195,46 @@ Manage datasets (semantic models), permissions, and execute DAX queries.
|
|
|
140
195
|
| `list_dataset_related_reports(workspace_id, dataset_id)` | List all reports linked to a dataset. |
|
|
141
196
|
| `export_dataset_related_reports(workspace_id, dataset_id)` | Export all reports linked to a dataset as `.pbix` files. |
|
|
142
197
|
|
|
143
|
-
|
|
198
|
+
### Report
|
|
144
199
|
|
|
145
200
|
Retrieve report metadata, definitions, visuals, and report-level measures.
|
|
146
201
|
|
|
202
|
+
```python
|
|
203
|
+
rpt = Report(auth.get_token('pbi'))
|
|
204
|
+
pages = rpt.list_report_pages(workspace_id, report_id)
|
|
205
|
+
```
|
|
206
|
+
|
|
147
207
|
| Method | Description |
|
|
148
208
|
|---|---|
|
|
149
209
|
| `list_reports(workspace_id)` | List all reports in a workspace. |
|
|
150
210
|
| `get_report_metadata(workspace_id, report_id)` | Get metadata for a specific report. |
|
|
151
211
|
| `get_report_name(workspace_id, report_id)` | Get a report's display name. |
|
|
152
212
|
| `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
|
|
213
|
+
| `get_report_json_pages_and_visuals(json_data, workspace_id, report_id)` | Parse a PBIR-Legacy report JSON and extract pages/visuals into a DataFrame. |
|
|
154
214
|
| `get_legacy_report_json(workspace_id, report_id, operations)` | Get and decode the full report definition for PBIR-Legacy reports. |
|
|
155
215
|
| `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.
|
|
157
|
-
| `rebind_report(workspace_id, report_id, new_dataset_id,
|
|
216
|
+
| `get_report_measures(workspace_id, report_id, operations)` | Extract report-level measures and generate a DAX Query View script. |
|
|
217
|
+
| `rebind_report(workspace_id, report_id, new_dataset_id, ...)` | Rebind a report to a new dataset and migrate Read access. |
|
|
158
218
|
|
|
159
|
-
|
|
219
|
+
### Dataflow
|
|
160
220
|
|
|
161
221
|
Manage Power BI and Fabric dataflows, including Gen1, Gen2, and Gen2 CI/CD.
|
|
162
222
|
|
|
223
|
+
```python
|
|
224
|
+
df = Dataflow(auth.get_token('fabric'))
|
|
225
|
+
|
|
226
|
+
# upgrade Gen1 to Gen2 CI/CD
|
|
227
|
+
result = df.upgrade_to_gen2_cicd(
|
|
228
|
+
workspace_id='<workspace_id>',
|
|
229
|
+
dataflow_id='<gen1_dataflow_id>',
|
|
230
|
+
display_name='my_dataflow_cicd',
|
|
231
|
+
source_type='gen1'
|
|
232
|
+
)
|
|
233
|
+
```
|
|
234
|
+
|
|
163
235
|
| Method | Description |
|
|
164
236
|
|---|---|
|
|
165
|
-
| `list_dataflows(workspace_id)` | List all dataflows
|
|
237
|
+
| `list_dataflows(workspace_id)` | List all dataflows (Gen1, Gen2, Gen2 CI/CD), merged and deduplicated. |
|
|
166
238
|
| `get_dataflow_details(workspace_id, dataflow_id)` | Get details of a specific dataflow. |
|
|
167
239
|
| `get_dataflow_name(workspace_id, dataflow_id)` | Resolve the display name of a dataflow. |
|
|
168
240
|
| `create_dataflow(workspace_id, dataflow_content)` | Create a new Power BI dataflow. |
|
|
@@ -171,39 +243,83 @@ Manage Power BI and Fabric dataflows, including Gen1, Gen2, and Gen2 CI/CD.
|
|
|
171
243
|
| `get_dataflow_gen2_definition(workspace_id, dataflow_id)` | Get the definition of a Dataflow Gen2 CI/CD item. |
|
|
172
244
|
| `create_dataflow_gen2_from_definition(workspace_id, display_name, definition)` | Create a Dataflow Gen2 CI/CD from a definition. |
|
|
173
245
|
| `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
|
|
175
|
-
| `change_data_destination(workspace_id, dataflow_id, destination_type, ...)` | Change
|
|
176
|
-
| `create_dataflow_with_new_destination(workspace_id, dataflow_id, ...)` | Create a new Gen2 CI/CD dataflow
|
|
246
|
+
| `get_data_destinations(workspace_id, dataflow_id)` | Get data destination details for each table in a dataflow. |
|
|
247
|
+
| `change_data_destination(workspace_id, dataflow_id, destination_type, ...)` | Change data destination (Lakehouse/Warehouse). Modes: `preview`, `replace`, `create`. |
|
|
248
|
+
| `create_dataflow_with_new_destination(workspace_id, dataflow_id, ...)` | Create a new Gen2 CI/CD dataflow with a different data destination. |
|
|
177
249
|
| `upgrade_to_gen2_cicd(...)` | Upgrade a Gen1 or Gen2 (standard) dataflow to Gen2 CI/CD. |
|
|
178
250
|
|
|
179
|
-
|
|
251
|
+
### Pipeline
|
|
180
252
|
|
|
181
253
|
Manage Fabric Data Pipelines.
|
|
182
254
|
|
|
255
|
+
```python
|
|
256
|
+
pipe = Pipeline(auth.get_token('fabric'))
|
|
257
|
+
activities = pipe.get_pipeline_activities(workspace_id, 'My Pipeline')
|
|
258
|
+
```
|
|
259
|
+
|
|
183
260
|
| Method | Description |
|
|
184
261
|
|---|---|
|
|
185
262
|
| `list_pipelines(workspace_id)` | List all Fabric Data Pipelines in a workspace. |
|
|
186
263
|
| `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
|
|
264
|
+
| `get_pipeline_definition(workspace_id, pipeline_id)` | Get the full definition of a pipeline. |
|
|
188
265
|
| `update_pipeline_definition(workspace_id, pipeline_id, definition)` | Update an existing pipeline definition. |
|
|
189
|
-
| `get_pipeline_activities(workspace_id, pipeline_id_or_name)` | Get
|
|
190
|
-
| `find_pipelines_by_dataflow(workspace_id, dataflow_id_or_name)` | Find
|
|
191
|
-
| `replace_dataflow_id_in_pipeline(workspace_id, pipeline_id,
|
|
266
|
+
| `get_pipeline_activities(workspace_id, pipeline_id_or_name)` | Get activities from a pipeline. Accepts ID or display name. |
|
|
267
|
+
| `find_pipelines_by_dataflow(workspace_id, dataflow_id_or_name)` | Find pipelines that reference a specific dataflow. |
|
|
268
|
+
| `replace_dataflow_id_in_pipeline(workspace_id, pipeline_id, old_id, new_id)` | Replace a dataflow ID in all RefreshDataflow activities. |
|
|
192
269
|
|
|
193
|
-
|
|
270
|
+
<details>
|
|
271
|
+
<summary><strong>Example: replacing a dataflow destination and updating pipelines</strong></summary>
|
|
194
272
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
273
|
+
When `change_data_destination(mode='replace')` is used on a standard Gen2 dataflow, the original is deleted and a new CI/CD dataflow is created with a new ID. Pipelines referencing the old ID must be updated:
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
from msdev_kit import Auth
|
|
277
|
+
from msdev_kit.fabric import Dataflow, Pipeline
|
|
278
|
+
|
|
279
|
+
auth = Auth(tenant_id, client_id, client_secret)
|
|
280
|
+
dataflow = Dataflow(auth.get_token('pbi'))
|
|
281
|
+
pipeline = Pipeline(auth.get_token('fabric'))
|
|
282
|
+
|
|
283
|
+
workspace_id = '<workspace_id>'
|
|
284
|
+
old_dataflow_id = '<dataflow_id>'
|
|
285
|
+
|
|
286
|
+
# 1. replace dataflow destination (creates new CI/CD, deletes original)
|
|
287
|
+
result = dataflow.change_data_destination(
|
|
288
|
+
workspace_id=workspace_id,
|
|
289
|
+
dataflow_id=old_dataflow_id,
|
|
290
|
+
destination_type='Warehouse',
|
|
291
|
+
destination_workspace_id=workspace_id,
|
|
292
|
+
destination_item_id='<warehouse_id>',
|
|
293
|
+
mode='replace'
|
|
294
|
+
)
|
|
295
|
+
new_dataflow_id = result['content']['id']
|
|
296
|
+
|
|
297
|
+
# 2. find pipelines referencing the old dataflow ID
|
|
298
|
+
matches = pipeline.find_pipelines_by_dataflow(workspace_id, old_dataflow_id)
|
|
299
|
+
|
|
300
|
+
# 3. update each pipeline to use the new ID
|
|
301
|
+
for m in matches['content']:
|
|
302
|
+
pipeline.replace_dataflow_id_in_pipeline(
|
|
303
|
+
workspace_id, m['pipeline_id'], old_dataflow_id, new_dataflow_id
|
|
304
|
+
)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
</details>
|
|
308
|
+
|
|
309
|
+
### Other modules
|
|
310
|
+
|
|
311
|
+
| Module | Class | Description |
|
|
312
|
+
|---|---|---|
|
|
313
|
+
| Capacity | `Capacity` | Monitor and manage Power BI and Fabric capacities. |
|
|
314
|
+
| Operations | `Operations` | Track long-running Fabric API operations. |
|
|
315
|
+
| Admin | `Admin` | Power BI Admin API operations. |
|
|
316
|
+
| KQL | `KQLDatabase` | Query Kusto (KQL) databases in Microsoft Fabric. |
|
|
317
|
+
| Notebook | `Notebook` | Manage Fabric notebooks (list, get metadata). |
|
|
318
|
+
| Database | `Database` | Query and write to SQL databases (Lakehouse, Warehouse) via ODBC. |
|
|
203
319
|
|
|
204
320
|
---
|
|
205
321
|
|
|
206
|
-
|
|
322
|
+
## MS Graph (Entra)
|
|
207
323
|
|
|
208
324
|
Manage Entra ID (Azure AD) users and groups via the MS Graph API.
|
|
209
325
|
|
|
@@ -214,8 +330,12 @@ from msdev_kit.graph import GraphClient
|
|
|
214
330
|
auth = Auth(tenant_id, client_id, client_secret)
|
|
215
331
|
graph = GraphClient(auth)
|
|
216
332
|
|
|
333
|
+
# look up a user and add them to a group
|
|
217
334
|
user_id = graph.get_user_id('user@company.com')
|
|
218
335
|
group_id = graph.get_group_id('Data Team')
|
|
336
|
+
graph.add_group_member(group_id, user_id)
|
|
337
|
+
|
|
338
|
+
# list all members of a group
|
|
219
339
|
members = graph.list_group_members(group_id)
|
|
220
340
|
```
|
|
221
341
|
|
|
@@ -229,7 +349,7 @@ members = graph.list_group_members(group_id)
|
|
|
229
349
|
|
|
230
350
|
---
|
|
231
351
|
|
|
232
|
-
|
|
352
|
+
## SharePoint
|
|
233
353
|
|
|
234
354
|
Manage SharePoint files and folders via MS Graph API (no ACS/Office365 dependency).
|
|
235
355
|
|
|
@@ -240,9 +360,15 @@ from msdev_kit.sharepoint import SharePointClient
|
|
|
240
360
|
auth = Auth(tenant_id, client_id, client_secret)
|
|
241
361
|
sp = SharePointClient(auth, sp_hostname='company', sp_site_path='sites/DataTeam')
|
|
242
362
|
|
|
363
|
+
# download a file
|
|
243
364
|
sp.download_file('/Reports/monthly.xlsx', local_dir='./downloads')
|
|
365
|
+
|
|
366
|
+
# upload a file (from path or bytes)
|
|
244
367
|
sp.upload_file('/Reports/updated.xlsx', source='./local/updated.xlsx')
|
|
245
|
-
sp.
|
|
368
|
+
sp.upload_file('/Reports/data.csv', source=csv_bytes, content_type='text/csv')
|
|
369
|
+
|
|
370
|
+
# create nested folders
|
|
371
|
+
sp.create_folder('/Reports/2026/Q1')
|
|
246
372
|
```
|
|
247
373
|
|
|
248
374
|
| Method | Description |
|
|
@@ -251,7 +377,16 @@ sp.create_folder('/Reports/2026')
|
|
|
251
377
|
| `upload_file(remote_path, source, content_type?)` | Upload/overwrite a file. `source` is a local file path (str) or raw bytes. |
|
|
252
378
|
| `create_folder(folder_path)` | Create a folder and all intermediate folders. |
|
|
253
379
|
|
|
254
|
-
Hostname and site path inputs are normalized automatically
|
|
380
|
+
Hostname and site path inputs are normalized automatically:
|
|
381
|
+
|
|
382
|
+
| Input | Normalized to |
|
|
383
|
+
|---|---|
|
|
384
|
+
| `company` | `company.sharepoint.com` |
|
|
385
|
+
| `company.sharepoint.com` | `company.sharepoint.com` |
|
|
386
|
+
| `https://company.sharepoint.com` | `company.sharepoint.com` |
|
|
387
|
+
| `DataTeam` | `sites/DataTeam` |
|
|
388
|
+
| `sites/DataTeam` | `sites/DataTeam` |
|
|
389
|
+
| `/sites/DataTeam` | `sites/DataTeam` |
|
|
255
390
|
|
|
256
391
|
---
|
|
257
392
|
|
|
@@ -2,21 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
Microsoft developer toolkit for Python: Fabric/Power BI, MS Graph (Entra), and SharePoint.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://pypi.org/project/msdev-kit/)
|
|
6
|
+
[](https://pypi.org/project/msdev-kit/)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
[Installation](https://github.com/Bernardo-Rufino/msdev-kit#installation) · [Quick Start](https://github.com/Bernardo-Rufino/msdev-kit#quick-start) · [Authentication](https://github.com/Bernardo-Rufino/msdev-kit#authentication) · [Fabric & Power BI](https://github.com/Bernardo-Rufino/msdev-kit#fabric--power-bi) · [MS Graph (Entra)](https://github.com/Bernardo-Rufino/msdev-kit#ms-graph-entra) · [SharePoint](https://github.com/Bernardo-Rufino/msdev-kit#sharepoint) · [Limitations](https://github.com/Bernardo-Rufino/msdev-kit#limitations)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
8
16
|
|
|
9
17
|
```shell
|
|
10
18
|
pip install msdev-kit
|
|
11
19
|
```
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
Or install from GitHub:
|
|
14
22
|
|
|
15
23
|
```shell
|
|
16
24
|
pip install git+https://github.com/Bernardo-Rufino/msdev-kit.git
|
|
17
25
|
```
|
|
18
26
|
|
|
19
|
-
|
|
27
|
+
For local development:
|
|
20
28
|
|
|
21
29
|
```shell
|
|
22
30
|
git clone https://github.com/Bernardo-Rufino/msdev-kit.git
|
|
@@ -24,32 +32,64 @@ cd msdev-kit
|
|
|
24
32
|
pip install -e .
|
|
25
33
|
```
|
|
26
34
|
|
|
35
|
+
**Requirements:** Python >= 3.10, an Azure app registration with a client ID and client secret.
|
|
36
|
+
|
|
27
37
|
---
|
|
28
38
|
|
|
29
|
-
##
|
|
39
|
+
## Quick Start
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
```python
|
|
42
|
+
from msdev_kit import Auth
|
|
43
|
+
from msdev_kit.fabric import Workspace
|
|
44
|
+
from msdev_kit.graph import GraphClient
|
|
45
|
+
from msdev_kit.sharepoint import SharePointClient
|
|
33
46
|
|
|
34
|
-
|
|
47
|
+
# authenticate
|
|
48
|
+
auth = Auth(tenant_id="...", client_id="...", client_secret="...")
|
|
35
49
|
|
|
36
|
-
|
|
50
|
+
# fabric: list workspaces
|
|
51
|
+
ws = Workspace(auth.get_token('fabric'))
|
|
52
|
+
workspaces = ws.list_workspaces_for_user()
|
|
37
53
|
|
|
38
|
-
|
|
54
|
+
# graph: look up a user
|
|
55
|
+
graph = GraphClient(auth)
|
|
56
|
+
user_id = graph.get_user_id('user@company.com')
|
|
57
|
+
|
|
58
|
+
# sharepoint: download a file
|
|
59
|
+
sp = SharePointClient(auth, sp_hostname='company', sp_site_path='sites/DataTeam')
|
|
60
|
+
sp.download_file('/Reports/monthly.xlsx', local_dir='./downloads')
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Authentication
|
|
66
|
+
|
|
67
|
+
All classes use a shared `Auth` object. You can use different service principals for different services — instantiate one `Auth` per SPN:
|
|
39
68
|
|
|
40
69
|
```python
|
|
41
70
|
from msdev_kit import Auth
|
|
42
71
|
|
|
43
72
|
# service principal auth
|
|
44
|
-
|
|
73
|
+
fabric_auth = Auth(tenant_id="...", client_id="spn-a", client_secret="...")
|
|
74
|
+
graph_auth = Auth(tenant_id="...", client_id="spn-b", client_secret="...")
|
|
75
|
+
```
|
|
45
76
|
|
|
46
|
-
|
|
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
|
|
77
|
+
### Supported scopes
|
|
50
78
|
|
|
51
|
-
|
|
52
|
-
|
|
79
|
+
| Service | Scope | Usage |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `pbi` (default) | Power BI API | `auth.get_token()` or `auth.get_token('pbi')` |
|
|
82
|
+
| `fabric` | Fabric API | `auth.get_token('fabric')` |
|
|
83
|
+
| `graph` | MS Graph API | `auth.get_token('graph')` |
|
|
84
|
+
| `azure` | Azure Management API | `auth.get_token('azure')` |
|
|
85
|
+
|
|
86
|
+
### Interactive user auth
|
|
87
|
+
|
|
88
|
+
For scenarios requiring user context (e.g., RLS-enabled datasets):
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
token = auth.get_token_for_user('pbi') # opens browser for login
|
|
92
|
+
token = auth.get_token_for_user('fabric')
|
|
53
93
|
```
|
|
54
94
|
|
|
55
95
|
### Credentials
|
|
@@ -64,24 +104,34 @@ CLIENT_SECRET='<YOUR_CLIENT_SECRET>'
|
|
|
64
104
|
|
|
65
105
|
---
|
|
66
106
|
|
|
67
|
-
##
|
|
68
|
-
|
|
69
|
-
### `msdev_kit.fabric` — Fabric & Power BI
|
|
70
|
-
|
|
71
|
-
All existing Fabric/Power BI classes, accessed via the `fabric` sub-package:
|
|
107
|
+
## Fabric & Power BI
|
|
72
108
|
|
|
73
109
|
```python
|
|
74
|
-
from msdev_kit.fabric import Workspace, Dataset, Report, Dataflow, Pipeline
|
|
75
110
|
from msdev_kit import Auth
|
|
111
|
+
from msdev_kit.fabric import Workspace, Dataset, Report, Dataflow, Pipeline
|
|
76
112
|
|
|
77
113
|
auth = Auth(tenant_id, client_id, client_secret)
|
|
78
|
-
ws = Workspace(auth.get_token('fabric'))
|
|
79
114
|
```
|
|
80
115
|
|
|
81
|
-
|
|
116
|
+
Fabric classes take a token string — call `auth.get_token('fabric')` or `auth.get_token('pbi')` depending on the API.
|
|
117
|
+
|
|
118
|
+
- [Workspace](https://github.com/Bernardo-Rufino/msdev-kit#workspace) — workspaces, users, permissions
|
|
119
|
+
- [Dataset](https://github.com/Bernardo-Rufino/msdev-kit#dataset) — semantic models, DAX queries, permissions
|
|
120
|
+
- [Report](https://github.com/Bernardo-Rufino/msdev-kit#report) — metadata, definitions, visuals, measures
|
|
121
|
+
- [Dataflow](https://github.com/Bernardo-Rufino/msdev-kit#dataflow) — Gen1, Gen2, Gen2 CI/CD management
|
|
122
|
+
- [Pipeline](https://github.com/Bernardo-Rufino/msdev-kit#pipeline) — Data Pipeline management
|
|
123
|
+
- [Other modules](https://github.com/Bernardo-Rufino/msdev-kit#other-modules) — Capacity, Admin, KQL, Notebook, Database
|
|
124
|
+
|
|
125
|
+
### Workspace
|
|
82
126
|
|
|
83
127
|
Manage Power BI workspaces, users, and permissions.
|
|
84
128
|
|
|
129
|
+
```python
|
|
130
|
+
ws = Workspace(auth.get_token('pbi'))
|
|
131
|
+
workspaces = ws.list_workspaces_for_user()
|
|
132
|
+
ws.add_user('user@company.com', workspace_id, 'Member', 'User')
|
|
133
|
+
```
|
|
134
|
+
|
|
85
135
|
| Method | Description |
|
|
86
136
|
|---|---|
|
|
87
137
|
| `list_workspaces_for_user(...)` | List all workspaces the user has access to, with optional filters. |
|
|
@@ -93,16 +143,21 @@ Manage Power BI workspaces, users, and permissions.
|
|
|
93
143
|
| `remove_user(user_principal_name, workspace_id)` | Remove a user from a workspace. |
|
|
94
144
|
| `batch_update_user(user, workspaces_list)` | Batch update a user across multiple workspaces. |
|
|
95
145
|
|
|
96
|
-
|
|
146
|
+
### Dataset
|
|
97
147
|
|
|
98
148
|
Manage datasets (semantic models), permissions, and execute DAX queries.
|
|
99
149
|
|
|
150
|
+
```python
|
|
151
|
+
ds = Dataset(auth.get_token('pbi'))
|
|
152
|
+
result = ds.execute_query(workspace_id, dataset_id, "EVALUATE Sales")
|
|
153
|
+
```
|
|
154
|
+
|
|
100
155
|
| Method | Description |
|
|
101
156
|
|---|---|
|
|
102
157
|
| `list_datasets(workspace_id)` | List all datasets in a workspace. |
|
|
103
158
|
| `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
|
|
105
|
-
| `execute_query(workspace_id, dataset_id, query)` | Execute a DAX query
|
|
159
|
+
| `get_dataset_name(workspace_id, dataset_id)` | Resolve the display name of a dataset. Tries PBI API first, falls back to Fabric semantic models API. |
|
|
160
|
+
| `execute_query(workspace_id, dataset_id, query)` | Execute a DAX query. Runs a COUNTROWS pre-check to detect truncation. |
|
|
106
161
|
| `list_users(workspace_id, dataset_id)` | List users with access to a dataset. |
|
|
107
162
|
| `add_user(user_principal_name, workspace_id, dataset_id, access_right)` | Grant a user access to a dataset. |
|
|
108
163
|
| `update_user(user_principal_name, workspace_id, dataset_id, access_right)` | Update a user's access to a dataset. |
|
|
@@ -110,29 +165,46 @@ Manage datasets (semantic models), permissions, and execute DAX queries.
|
|
|
110
165
|
| `list_dataset_related_reports(workspace_id, dataset_id)` | List all reports linked to a dataset. |
|
|
111
166
|
| `export_dataset_related_reports(workspace_id, dataset_id)` | Export all reports linked to a dataset as `.pbix` files. |
|
|
112
167
|
|
|
113
|
-
|
|
168
|
+
### Report
|
|
114
169
|
|
|
115
170
|
Retrieve report metadata, definitions, visuals, and report-level measures.
|
|
116
171
|
|
|
172
|
+
```python
|
|
173
|
+
rpt = Report(auth.get_token('pbi'))
|
|
174
|
+
pages = rpt.list_report_pages(workspace_id, report_id)
|
|
175
|
+
```
|
|
176
|
+
|
|
117
177
|
| Method | Description |
|
|
118
178
|
|---|---|
|
|
119
179
|
| `list_reports(workspace_id)` | List all reports in a workspace. |
|
|
120
180
|
| `get_report_metadata(workspace_id, report_id)` | Get metadata for a specific report. |
|
|
121
181
|
| `get_report_name(workspace_id, report_id)` | Get a report's display name. |
|
|
122
182
|
| `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
|
|
183
|
+
| `get_report_json_pages_and_visuals(json_data, workspace_id, report_id)` | Parse a PBIR-Legacy report JSON and extract pages/visuals into a DataFrame. |
|
|
124
184
|
| `get_legacy_report_json(workspace_id, report_id, operations)` | Get and decode the full report definition for PBIR-Legacy reports. |
|
|
125
185
|
| `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.
|
|
127
|
-
| `rebind_report(workspace_id, report_id, new_dataset_id,
|
|
186
|
+
| `get_report_measures(workspace_id, report_id, operations)` | Extract report-level measures and generate a DAX Query View script. |
|
|
187
|
+
| `rebind_report(workspace_id, report_id, new_dataset_id, ...)` | Rebind a report to a new dataset and migrate Read access. |
|
|
128
188
|
|
|
129
|
-
|
|
189
|
+
### Dataflow
|
|
130
190
|
|
|
131
191
|
Manage Power BI and Fabric dataflows, including Gen1, Gen2, and Gen2 CI/CD.
|
|
132
192
|
|
|
193
|
+
```python
|
|
194
|
+
df = Dataflow(auth.get_token('fabric'))
|
|
195
|
+
|
|
196
|
+
# upgrade Gen1 to Gen2 CI/CD
|
|
197
|
+
result = df.upgrade_to_gen2_cicd(
|
|
198
|
+
workspace_id='<workspace_id>',
|
|
199
|
+
dataflow_id='<gen1_dataflow_id>',
|
|
200
|
+
display_name='my_dataflow_cicd',
|
|
201
|
+
source_type='gen1'
|
|
202
|
+
)
|
|
203
|
+
```
|
|
204
|
+
|
|
133
205
|
| Method | Description |
|
|
134
206
|
|---|---|
|
|
135
|
-
| `list_dataflows(workspace_id)` | List all dataflows
|
|
207
|
+
| `list_dataflows(workspace_id)` | List all dataflows (Gen1, Gen2, Gen2 CI/CD), merged and deduplicated. |
|
|
136
208
|
| `get_dataflow_details(workspace_id, dataflow_id)` | Get details of a specific dataflow. |
|
|
137
209
|
| `get_dataflow_name(workspace_id, dataflow_id)` | Resolve the display name of a dataflow. |
|
|
138
210
|
| `create_dataflow(workspace_id, dataflow_content)` | Create a new Power BI dataflow. |
|
|
@@ -141,39 +213,83 @@ Manage Power BI and Fabric dataflows, including Gen1, Gen2, and Gen2 CI/CD.
|
|
|
141
213
|
| `get_dataflow_gen2_definition(workspace_id, dataflow_id)` | Get the definition of a Dataflow Gen2 CI/CD item. |
|
|
142
214
|
| `create_dataflow_gen2_from_definition(workspace_id, display_name, definition)` | Create a Dataflow Gen2 CI/CD from a definition. |
|
|
143
215
|
| `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
|
|
145
|
-
| `change_data_destination(workspace_id, dataflow_id, destination_type, ...)` | Change
|
|
146
|
-
| `create_dataflow_with_new_destination(workspace_id, dataflow_id, ...)` | Create a new Gen2 CI/CD dataflow
|
|
216
|
+
| `get_data_destinations(workspace_id, dataflow_id)` | Get data destination details for each table in a dataflow. |
|
|
217
|
+
| `change_data_destination(workspace_id, dataflow_id, destination_type, ...)` | Change data destination (Lakehouse/Warehouse). Modes: `preview`, `replace`, `create`. |
|
|
218
|
+
| `create_dataflow_with_new_destination(workspace_id, dataflow_id, ...)` | Create a new Gen2 CI/CD dataflow with a different data destination. |
|
|
147
219
|
| `upgrade_to_gen2_cicd(...)` | Upgrade a Gen1 or Gen2 (standard) dataflow to Gen2 CI/CD. |
|
|
148
220
|
|
|
149
|
-
|
|
221
|
+
### Pipeline
|
|
150
222
|
|
|
151
223
|
Manage Fabric Data Pipelines.
|
|
152
224
|
|
|
225
|
+
```python
|
|
226
|
+
pipe = Pipeline(auth.get_token('fabric'))
|
|
227
|
+
activities = pipe.get_pipeline_activities(workspace_id, 'My Pipeline')
|
|
228
|
+
```
|
|
229
|
+
|
|
153
230
|
| Method | Description |
|
|
154
231
|
|---|---|
|
|
155
232
|
| `list_pipelines(workspace_id)` | List all Fabric Data Pipelines in a workspace. |
|
|
156
233
|
| `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
|
|
234
|
+
| `get_pipeline_definition(workspace_id, pipeline_id)` | Get the full definition of a pipeline. |
|
|
158
235
|
| `update_pipeline_definition(workspace_id, pipeline_id, definition)` | Update an existing pipeline definition. |
|
|
159
|
-
| `get_pipeline_activities(workspace_id, pipeline_id_or_name)` | Get
|
|
160
|
-
| `find_pipelines_by_dataflow(workspace_id, dataflow_id_or_name)` | Find
|
|
161
|
-
| `replace_dataflow_id_in_pipeline(workspace_id, pipeline_id,
|
|
236
|
+
| `get_pipeline_activities(workspace_id, pipeline_id_or_name)` | Get activities from a pipeline. Accepts ID or display name. |
|
|
237
|
+
| `find_pipelines_by_dataflow(workspace_id, dataflow_id_or_name)` | Find pipelines that reference a specific dataflow. |
|
|
238
|
+
| `replace_dataflow_id_in_pipeline(workspace_id, pipeline_id, old_id, new_id)` | Replace a dataflow ID in all RefreshDataflow activities. |
|
|
162
239
|
|
|
163
|
-
|
|
240
|
+
<details>
|
|
241
|
+
<summary><strong>Example: replacing a dataflow destination and updating pipelines</strong></summary>
|
|
164
242
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
243
|
+
When `change_data_destination(mode='replace')` is used on a standard Gen2 dataflow, the original is deleted and a new CI/CD dataflow is created with a new ID. Pipelines referencing the old ID must be updated:
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
from msdev_kit import Auth
|
|
247
|
+
from msdev_kit.fabric import Dataflow, Pipeline
|
|
248
|
+
|
|
249
|
+
auth = Auth(tenant_id, client_id, client_secret)
|
|
250
|
+
dataflow = Dataflow(auth.get_token('pbi'))
|
|
251
|
+
pipeline = Pipeline(auth.get_token('fabric'))
|
|
252
|
+
|
|
253
|
+
workspace_id = '<workspace_id>'
|
|
254
|
+
old_dataflow_id = '<dataflow_id>'
|
|
255
|
+
|
|
256
|
+
# 1. replace dataflow destination (creates new CI/CD, deletes original)
|
|
257
|
+
result = dataflow.change_data_destination(
|
|
258
|
+
workspace_id=workspace_id,
|
|
259
|
+
dataflow_id=old_dataflow_id,
|
|
260
|
+
destination_type='Warehouse',
|
|
261
|
+
destination_workspace_id=workspace_id,
|
|
262
|
+
destination_item_id='<warehouse_id>',
|
|
263
|
+
mode='replace'
|
|
264
|
+
)
|
|
265
|
+
new_dataflow_id = result['content']['id']
|
|
266
|
+
|
|
267
|
+
# 2. find pipelines referencing the old dataflow ID
|
|
268
|
+
matches = pipeline.find_pipelines_by_dataflow(workspace_id, old_dataflow_id)
|
|
269
|
+
|
|
270
|
+
# 3. update each pipeline to use the new ID
|
|
271
|
+
for m in matches['content']:
|
|
272
|
+
pipeline.replace_dataflow_id_in_pipeline(
|
|
273
|
+
workspace_id, m['pipeline_id'], old_dataflow_id, new_dataflow_id
|
|
274
|
+
)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
</details>
|
|
278
|
+
|
|
279
|
+
### Other modules
|
|
280
|
+
|
|
281
|
+
| Module | Class | Description |
|
|
282
|
+
|---|---|---|
|
|
283
|
+
| Capacity | `Capacity` | Monitor and manage Power BI and Fabric capacities. |
|
|
284
|
+
| Operations | `Operations` | Track long-running Fabric API operations. |
|
|
285
|
+
| Admin | `Admin` | Power BI Admin API operations. |
|
|
286
|
+
| KQL | `KQLDatabase` | Query Kusto (KQL) databases in Microsoft Fabric. |
|
|
287
|
+
| Notebook | `Notebook` | Manage Fabric notebooks (list, get metadata). |
|
|
288
|
+
| Database | `Database` | Query and write to SQL databases (Lakehouse, Warehouse) via ODBC. |
|
|
173
289
|
|
|
174
290
|
---
|
|
175
291
|
|
|
176
|
-
|
|
292
|
+
## MS Graph (Entra)
|
|
177
293
|
|
|
178
294
|
Manage Entra ID (Azure AD) users and groups via the MS Graph API.
|
|
179
295
|
|
|
@@ -184,8 +300,12 @@ from msdev_kit.graph import GraphClient
|
|
|
184
300
|
auth = Auth(tenant_id, client_id, client_secret)
|
|
185
301
|
graph = GraphClient(auth)
|
|
186
302
|
|
|
303
|
+
# look up a user and add them to a group
|
|
187
304
|
user_id = graph.get_user_id('user@company.com')
|
|
188
305
|
group_id = graph.get_group_id('Data Team')
|
|
306
|
+
graph.add_group_member(group_id, user_id)
|
|
307
|
+
|
|
308
|
+
# list all members of a group
|
|
189
309
|
members = graph.list_group_members(group_id)
|
|
190
310
|
```
|
|
191
311
|
|
|
@@ -199,7 +319,7 @@ members = graph.list_group_members(group_id)
|
|
|
199
319
|
|
|
200
320
|
---
|
|
201
321
|
|
|
202
|
-
|
|
322
|
+
## SharePoint
|
|
203
323
|
|
|
204
324
|
Manage SharePoint files and folders via MS Graph API (no ACS/Office365 dependency).
|
|
205
325
|
|
|
@@ -210,9 +330,15 @@ from msdev_kit.sharepoint import SharePointClient
|
|
|
210
330
|
auth = Auth(tenant_id, client_id, client_secret)
|
|
211
331
|
sp = SharePointClient(auth, sp_hostname='company', sp_site_path='sites/DataTeam')
|
|
212
332
|
|
|
333
|
+
# download a file
|
|
213
334
|
sp.download_file('/Reports/monthly.xlsx', local_dir='./downloads')
|
|
335
|
+
|
|
336
|
+
# upload a file (from path or bytes)
|
|
214
337
|
sp.upload_file('/Reports/updated.xlsx', source='./local/updated.xlsx')
|
|
215
|
-
sp.
|
|
338
|
+
sp.upload_file('/Reports/data.csv', source=csv_bytes, content_type='text/csv')
|
|
339
|
+
|
|
340
|
+
# create nested folders
|
|
341
|
+
sp.create_folder('/Reports/2026/Q1')
|
|
216
342
|
```
|
|
217
343
|
|
|
218
344
|
| Method | Description |
|
|
@@ -221,7 +347,16 @@ sp.create_folder('/Reports/2026')
|
|
|
221
347
|
| `upload_file(remote_path, source, content_type?)` | Upload/overwrite a file. `source` is a local file path (str) or raw bytes. |
|
|
222
348
|
| `create_folder(folder_path)` | Create a folder and all intermediate folders. |
|
|
223
349
|
|
|
224
|
-
Hostname and site path inputs are normalized automatically
|
|
350
|
+
Hostname and site path inputs are normalized automatically:
|
|
351
|
+
|
|
352
|
+
| Input | Normalized to |
|
|
353
|
+
|---|---|
|
|
354
|
+
| `company` | `company.sharepoint.com` |
|
|
355
|
+
| `company.sharepoint.com` | `company.sharepoint.com` |
|
|
356
|
+
| `https://company.sharepoint.com` | `company.sharepoint.com` |
|
|
357
|
+
| `DataTeam` | `sites/DataTeam` |
|
|
358
|
+
| `sites/DataTeam` | `sites/DataTeam` |
|
|
359
|
+
| `/sites/DataTeam` | `sites/DataTeam` |
|
|
225
360
|
|
|
226
361
|
---
|
|
227
362
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|