msdev-kit 0.1.0__py3-none-any.whl
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/__init__.py +3 -0
- msdev_kit/auth.py +35 -0
- msdev_kit/fabric/__init__.py +11 -0
- msdev_kit/fabric/admin.py +42 -0
- msdev_kit/fabric/capacity.py +186 -0
- msdev_kit/fabric/database.py +94 -0
- msdev_kit/fabric/dataflow.py +1801 -0
- msdev_kit/fabric/dataset.py +617 -0
- msdev_kit/fabric/kql.py +66 -0
- msdev_kit/fabric/notebook.py +88 -0
- msdev_kit/fabric/operations.py +108 -0
- msdev_kit/fabric/pipeline.py +505 -0
- msdev_kit/fabric/report.py +1012 -0
- msdev_kit/fabric/utilities.py +12 -0
- msdev_kit/fabric/workspace.py +516 -0
- msdev_kit/graph/__init__.py +1 -0
- msdev_kit/graph/client.py +91 -0
- msdev_kit/sharepoint/__init__.py +1 -0
- msdev_kit/sharepoint/client.py +105 -0
- msdev_kit-0.1.0.dist-info/METADATA +269 -0
- msdev_kit-0.1.0.dist-info/RECORD +22 -0
- msdev_kit-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import requests
|
|
3
|
+
from typing import Dict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Notebook:
|
|
7
|
+
|
|
8
|
+
def __init__(self, token: str):
|
|
9
|
+
"""
|
|
10
|
+
Initialize variables.
|
|
11
|
+
"""
|
|
12
|
+
self.fabric_api_base_url = 'https://api.fabric.microsoft.com'
|
|
13
|
+
self.token = token
|
|
14
|
+
self.headers = {'Authorization': f'Bearer {self.token}'}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _request_with_retry(self, method: str, url: str, max_retries: int = 3, **kwargs) -> requests.Response:
|
|
18
|
+
"""
|
|
19
|
+
Makes an HTTP request with automatic retry on 429 (Too Many Requests).
|
|
20
|
+
Respects the Retry-After header when present.
|
|
21
|
+
"""
|
|
22
|
+
for attempt in range(max_retries + 1):
|
|
23
|
+
response = requests.request(method, url, **kwargs)
|
|
24
|
+
if response.status_code != 429:
|
|
25
|
+
return response
|
|
26
|
+
|
|
27
|
+
retry_after = int(response.headers.get('Retry-After', 5))
|
|
28
|
+
print(f" Rate limited (429). Retrying in {retry_after}s... (attempt {attempt + 1}/{max_retries})")
|
|
29
|
+
time.sleep(retry_after)
|
|
30
|
+
|
|
31
|
+
return response
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def list_notebooks(self, workspace_id: str) -> Dict:
|
|
35
|
+
"""
|
|
36
|
+
Lists all notebooks in a workspace.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
workspace_id (str): The ID of the workspace.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Dict: 'message' and 'content' (list of notebook dicts with id, displayName, description).
|
|
43
|
+
"""
|
|
44
|
+
if workspace_id == '':
|
|
45
|
+
return {'message': 'Missing workspace id, please check.', 'content': ''}
|
|
46
|
+
|
|
47
|
+
api_url = f'{self.fabric_api_base_url}/v1/workspaces/{workspace_id}/notebooks'
|
|
48
|
+
notebooks = []
|
|
49
|
+
|
|
50
|
+
while api_url:
|
|
51
|
+
response = self._request_with_retry('GET', api_url, headers=self.headers)
|
|
52
|
+
if response.status_code != 200:
|
|
53
|
+
error_data = response.json() if response.headers.get('content-type', '').startswith('application/json') else {}
|
|
54
|
+
error_message = error_data.get('message', error_data.get('error', {}).get('message', response.text))
|
|
55
|
+
return {'message': {'error': error_message, 'status_code': response.status_code}}
|
|
56
|
+
|
|
57
|
+
data = response.json()
|
|
58
|
+
notebooks.extend(data.get('value', []))
|
|
59
|
+
api_url = data.get('continuationUri', None)
|
|
60
|
+
|
|
61
|
+
return {'message': 'Success', 'content': notebooks}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def get_notebook(self, workspace_id: str, notebook_id: str) -> Dict:
|
|
65
|
+
"""
|
|
66
|
+
Gets the metadata of a specific notebook.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
workspace_id (str): The ID of the workspace.
|
|
70
|
+
notebook_id (str): The ID of the notebook.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Dict: 'message' and 'content' (notebook dict with id, displayName, description, etc.).
|
|
74
|
+
"""
|
|
75
|
+
if workspace_id == '':
|
|
76
|
+
return {'message': 'Missing workspace id, please check.', 'content': ''}
|
|
77
|
+
if notebook_id == '':
|
|
78
|
+
return {'message': 'Missing notebook id, please check.', 'content': ''}
|
|
79
|
+
|
|
80
|
+
api_url = f'{self.fabric_api_base_url}/v1/workspaces/{workspace_id}/notebooks/{notebook_id}'
|
|
81
|
+
response = self._request_with_retry('GET', api_url, headers=self.headers)
|
|
82
|
+
|
|
83
|
+
if response.status_code == 200:
|
|
84
|
+
return {'message': 'Success', 'content': response.json()}
|
|
85
|
+
else:
|
|
86
|
+
error_data = response.json() if response.headers.get('content-type', '').startswith('application/json') else {}
|
|
87
|
+
error_message = error_data.get('message', error_data.get('error', {}).get('message', response.text))
|
|
88
|
+
return {'message': {'error': error_message, 'status_code': response.status_code}}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import requests
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from .utilities import create_directory
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Operations:
|
|
8
|
+
|
|
9
|
+
def __init__(self, token: str):
|
|
10
|
+
"""
|
|
11
|
+
Initialize variables.
|
|
12
|
+
"""
|
|
13
|
+
self.main_url = 'https://api.fabric.microsoft.com/v1'
|
|
14
|
+
self.token = token
|
|
15
|
+
self.headers = {'Authorization': f'Bearer {self.token}'}
|
|
16
|
+
self.data_dir = './data/operations'
|
|
17
|
+
|
|
18
|
+
create_directory(self.data_dir)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_operation_state(
|
|
22
|
+
self,
|
|
23
|
+
operation_id: str = '') -> str:
|
|
24
|
+
"""
|
|
25
|
+
Get the operation state for a long running operation.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
operation_id (str, optional): operation id to check state.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Dict: message and operation state.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
DEFAULT_STATE = 'unknown'
|
|
35
|
+
|
|
36
|
+
# Main URL
|
|
37
|
+
request_url = f'{self.main_url}/operations/{operation_id}'
|
|
38
|
+
|
|
39
|
+
# If operation ID was not informed, return error message...
|
|
40
|
+
if operation_id == '':
|
|
41
|
+
return {'message': 'Missing operation id, please check.', 'operation_state': DEFAULT_STATE}
|
|
42
|
+
|
|
43
|
+
# If workspace ID was informed...
|
|
44
|
+
else:
|
|
45
|
+
|
|
46
|
+
# Make the request
|
|
47
|
+
r = requests.get(url=request_url, headers=self.headers)
|
|
48
|
+
|
|
49
|
+
# Get HTTP status and content
|
|
50
|
+
status = r.status_code
|
|
51
|
+
response = json.loads(r.content)
|
|
52
|
+
|
|
53
|
+
# If success...
|
|
54
|
+
if status == 200:
|
|
55
|
+
# Get the state
|
|
56
|
+
operation_state = response.get('status', DEFAULT_STATE)
|
|
57
|
+
|
|
58
|
+
return {'message': 'Success', 'operation_state': operation_state}
|
|
59
|
+
|
|
60
|
+
else:
|
|
61
|
+
# If any error happens, return message.
|
|
62
|
+
response = json.loads(r.content)
|
|
63
|
+
error_message = response['error']['message']
|
|
64
|
+
|
|
65
|
+
return {'message': {'error': error_message}, 'operation_state': DEFAULT_STATE}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_operation_result(
|
|
69
|
+
self,
|
|
70
|
+
operation_id: str = '') -> Dict:
|
|
71
|
+
"""
|
|
72
|
+
Get the operation result for a long running operation.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
operation_id (str, optional): operation id to get result from.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Dict: json with it's contents.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
# Main URL
|
|
82
|
+
request_url = f'{self.main_url}/operations/{operation_id}/result'
|
|
83
|
+
|
|
84
|
+
# If operation ID was not informed, return error message...
|
|
85
|
+
if operation_id == '':
|
|
86
|
+
return {'message': 'Missing operation id, please check.', 'content': ''}
|
|
87
|
+
|
|
88
|
+
# If workspace ID was informed...
|
|
89
|
+
else:
|
|
90
|
+
|
|
91
|
+
# Make the request
|
|
92
|
+
r = requests.get(url=request_url, headers=self.headers)
|
|
93
|
+
|
|
94
|
+
# Get HTTP status and content
|
|
95
|
+
status = r.status_code
|
|
96
|
+
response = json.loads(r.content)
|
|
97
|
+
|
|
98
|
+
# If success...
|
|
99
|
+
if status == 200:
|
|
100
|
+
|
|
101
|
+
return {'message': 'Success', 'content': response}
|
|
102
|
+
|
|
103
|
+
else:
|
|
104
|
+
# If any error happens, return message.
|
|
105
|
+
response = json.loads(r.content)
|
|
106
|
+
error_message = response['error']['message']
|
|
107
|
+
|
|
108
|
+
return {'message': {'error': error_message}, 'content': ''}
|