brynq-sdk-brynq 4.2.6.dev0__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.

Potentially problematic release.


This version of brynq-sdk-brynq might be problematic. Click here for more details.

@@ -0,0 +1,234 @@
1
+ from typing import Dict, List, Any, Optional
2
+ from .credentials import Credentials
3
+ from .mappings import Mappings
4
+ from .scenarios import Scenarios
5
+ from .schemas.interfaces import Interface, InterfaceDetail, InterfaceConfig, Schedule, Scope, DevSettings
6
+ from brynq_sdk_functions import Functions
7
+
8
+ class Interfaces:
9
+ """
10
+ Handles all interface-related operations for BrynQ SDK.
11
+ """
12
+ def __init__(self, brynq_instance):
13
+ """
14
+ Initialize Interfaces manager.
15
+
16
+ Args:
17
+ brynq_instance: The parent BrynQ instance
18
+ """
19
+ self._brynq = brynq_instance
20
+ self.credentials = Credentials(brynq_instance)
21
+ self.mappings = Mappings(brynq_instance)
22
+ self.scenarios = Scenarios(brynq_instance)
23
+
24
+ def get_all(self) -> List[Dict[str, Any]]:
25
+ """Get all interfaces this token has access to.
26
+
27
+ Returns:
28
+ List[Dict[str, Any]]: List of interfaces with their details including:
29
+ - id (int): Interface ID
30
+ - name (str): Interface name
31
+ - description (str): Interface description
32
+ - sourceSystems (List[int]): List of source system IDs
33
+ - targetSystems (List[int]): List of target system IDs
34
+ - taskSchedule (Dict): Task schedule details including status, timing, etc.
35
+
36
+ Raises:
37
+ ValueError: If the response data is invalid
38
+ requests.exceptions.RequestException: If the API request fails
39
+ """
40
+ response = self._brynq.brynq_session.get(
41
+ f"{self._brynq.url}interfaces",
42
+ timeout=self._brynq.timeout
43
+ )
44
+ response.raise_for_status()
45
+
46
+ try:
47
+ interfaces_data = response.json()
48
+ valid_data, _ = Functions.validate_pydantic_data(interfaces_data, schema=Interface)
49
+ return valid_data
50
+ except ValueError as e:
51
+ raise ValueError(f"Invalid interface data received from API: {str(e)}")
52
+
53
+ def get(self) -> Dict[str, Any]:
54
+ """Get a specific interface by its ID.
55
+ Returns:
56
+ Dict[str, Any]: Interface details including:
57
+ - name (str): Interface name
58
+ - type (str): Interface type (e.g., 'ADVANCED')
59
+ - apps (Dict): Application configuration with:
60
+ - source (str): Source application name
61
+ - target (str): Target application name
62
+
63
+ Raises:
64
+ ValueError: If interface_id is not a positive integer or if the response data is invalid
65
+ requests.exceptions.RequestException: If the API request fails
66
+ """
67
+ # Basic validation
68
+
69
+ response = self._brynq.brynq_session.get(
70
+ f"{self._brynq.url}interfaces/{self._brynq.data_interface_id}",
71
+ timeout=self._brynq.timeout
72
+ )
73
+ response.raise_for_status()
74
+
75
+ try:
76
+ interface_data = response.json()
77
+ valid_data, _ = Functions.validate_pydantic_data(interface_data, schema=InterfaceDetail)
78
+ return valid_data[0]
79
+ except ValueError as e:
80
+ raise ValueError(f"Invalid interface data received from API: {str(e)}")
81
+
82
+ def get_config(self) -> Dict[str, Any]:
83
+ """Get the base configuration of an interface.
84
+
85
+ Args:
86
+ interface_id (int): The ID of the interface
87
+
88
+ Returns:
89
+ Dict[str, Any]: Interface configuration including:
90
+ - mapping (List): List of mapping configurations
91
+ - variables (Dict): Configuration variables
92
+
93
+ Raises:
94
+ ValueError: If interface_id is not a positive integer or if the response data is invalid
95
+ requests.exceptions.RequestException: If the API request fails
96
+ """
97
+ # Basic validation
98
+
99
+ response = self._brynq.brynq_session.get(
100
+ f"{self._brynq.url}interfaces/{self._brynq.data_interface_id}/config",
101
+ timeout=self._brynq.timeout
102
+ )
103
+ response.raise_for_status()
104
+
105
+ try:
106
+ config_data = response.json()
107
+ valid_data, _ = Functions.validate_pydantic_data(config_data, schema=InterfaceConfig)
108
+ return valid_data[0]
109
+ except ValueError as e:
110
+ raise ValueError(f"Invalid interface configuration data: {str(e)}")
111
+
112
+ def flush_config(self) -> Dict[str, Any]:
113
+ """
114
+ Flushes the interface config to revert to a fresh state.
115
+
116
+ Returns:
117
+ Dict[str, Any]: Response from the flush operation
118
+
119
+ Raises:
120
+ requests.exceptions.RequestException: If the API request fails
121
+ """
122
+ response = self._brynq.brynq_session.get(
123
+ url=f'{self._brynq.url}interfaces/{self._brynq.data_interface_id}/config/flush',
124
+ timeout=self._brynq.timeout
125
+ )
126
+ response.raise_for_status()
127
+ return response
128
+
129
+ def get_schedule(self) -> Dict[str, Any]:
130
+ """Get the schedule configuration of an interface.
131
+
132
+ Returns:
133
+ Dict[str, Any]: Schedule configuration including:
134
+ - id (int): The schedule ID
135
+ - triggerType (str): Type of trigger (e.g., 'MANUAL')
136
+ - triggerPattern (str): Pattern for the trigger
137
+ - timezone (str): Timezone setting
138
+ - nextReload (str, optional): Next scheduled reload time
139
+ - frequency (Dict): Object containing day, hour, month, minute
140
+ - startAfterPrecedingTask (bool, optional): Whether to start after preceding task
141
+ - lastReload (str): Last reload time
142
+ - lastErrorMessage (str): Last error message
143
+
144
+ Raises:
145
+ ValueError: If interface_id is not a positive integer or if the response data is invalid
146
+ requests.exceptions.RequestException: If the API request fails
147
+ """
148
+ response = self._brynq.brynq_session.get(
149
+ f"{self._brynq.url}interfaces/{self._brynq.data_interface_id}/config/schedule",
150
+ timeout=self._brynq.timeout
151
+ )
152
+ response.raise_for_status()
153
+
154
+ try:
155
+ schedule_data = response.json()
156
+ valid_data, _ = Functions.validate_pydantic_data(schedule_data, schema=Schedule)
157
+ return valid_data[0]
158
+ except ValueError as e:
159
+ raise ValueError(f"Invalid schedule configuration data: {str(e)}")
160
+
161
+
162
+ def get_scope(self) -> Dict[str, Any]:
163
+ """Get live and draft scopes from interface by id.
164
+
165
+ Returns:
166
+ Dict[str, Any]: Scope configuration including:
167
+ - live (Dict, optional): Live scope configuration
168
+ - draft (Dict, optional): Draft scope configuration
169
+
170
+ Raises:
171
+ ValueError: If interface_id is not a positive integer or if the response data is invalid
172
+ requests.exceptions.RequestException: If the API request fails
173
+ """
174
+ response = self._brynq.brynq_session.get(
175
+ f"{self._brynq.url}interfaces/{self._brynq.data_interface_id}/scope",
176
+ timeout=self._brynq.timeout
177
+ )
178
+ response.raise_for_status()
179
+
180
+ try:
181
+ scope_data = response.json()
182
+ valid_data, _ = Functions.validate_pydantic_data(scope_data, schema=Scope)
183
+ return valid_data[0]
184
+ except ValueError as e:
185
+ raise ValueError(f"Invalid scope data: {str(e)}")
186
+
187
+ def get_dev_settings(self) -> List[dict[str,Any]]:
188
+ """Get the dev-settings of an interface
189
+
190
+ Returns:
191
+ Dict[str, Any]: A dictionary containing the dev settings:
192
+ - dockerImage (str): Docker image name
193
+ - sftpMapping (List[dict]): SFTP mapping configuration
194
+ - runfilePath (str): Path to the runfile
195
+ - stopIsAllowed (bool): Whether stopping is allowed
196
+
197
+ Raises:
198
+ requests.exceptions.RequestException: If the API request fails
199
+ requests.exceptions.HTTPError: If dev settings not found (404)
200
+ ValueError: If interface_id is not a positive integer
201
+ """
202
+
203
+ response = self._brynq.brynq_session.get(
204
+ url=f"{self._brynq.url}interfaces/{self._brynq.data_interface_id}/config/dev-settings",
205
+ timeout=self._brynq.timeout
206
+ )
207
+ response.raise_for_status()
208
+
209
+ valid_data, _ = Functions.validate_pydantic_data(response.json(), schema=DevSettings)
210
+ return valid_data
211
+
212
+ def get_variables(self, variable_name: str = None):
213
+ """
214
+ Get a value from the task_variables table corresponding with the given name. If temp value is filled, it will
215
+ (run_instant = 1), then the temp_value will be returned. This is to give the possibility for users in the frontend to run
216
+ a task once manual with other values then normal without overwriting the normal values.
217
+ :param variable_name: the name of the variable
218
+ :return: the value of the given variable.
219
+ """
220
+
221
+ variables = self.get_config().get("variables")
222
+
223
+ if not variables:
224
+ raise Exception(f"There are no valid variables in interface '{self._brynq.data_interface_id}'")
225
+
226
+ if variable_name:
227
+ variable = variables.get(variable_name)
228
+ if not variable:
229
+ raise Exception(f"The variable '{variable_name}' does not exist in interface '{self._brynq.data_interface_id}'")
230
+ self.flush_config()
231
+ return variable
232
+ else:
233
+ self.flush_config()
234
+ return variables
@@ -0,0 +1,107 @@
1
+ import requests
2
+ import pandas as pd
3
+ from typing import Optional, Union, Literal, Any, Tuple, List, Dict
4
+ import warnings
5
+ from .schemas.interfaces import MappingItem
6
+ from brynq_sdk_functions import Functions
7
+
8
+ class MappingNotFoundError(Exception):
9
+ """Raised when a requested mapping is not found"""
10
+ pass
11
+
12
+ class Mappings:
13
+ """
14
+ Handles all mapping-related operations for BrynQ SDK.
15
+ """
16
+ def __init__(self, brynq_instance):
17
+ """
18
+ Initialize Mappings manager.
19
+
20
+ Args:
21
+ brynq_instance: The parent BrynQ instance
22
+ """
23
+ self._brynq = brynq_instance
24
+
25
+ def _get_mappings(self) -> List[Dict[str, Any]]:
26
+ """Get all mappings for an interface.
27
+
28
+ Args:
29
+ interface_id (int): The ID of the interface
30
+
31
+ Returns:
32
+ List[Dict[str, Any]]: List of mapping configurations
33
+
34
+ Raises:
35
+ ValueError: If interface_id is not a positive integer or if the response data is invalid
36
+ requests.exceptions.RequestException: If the API request fails
37
+ """
38
+ response = self._brynq.brynq_session.get(
39
+ f"{self._brynq.url}interfaces/{self._brynq.data_interface_id}/config/mapping",
40
+ timeout=self._brynq.timeout
41
+ )
42
+ response.raise_for_status()
43
+
44
+ try:
45
+ mappings_data = response.json()
46
+ valid_data, _ = Functions.validate_pydantic_data(mappings_data, schema=MappingItem)
47
+ return valid_data
48
+ except ValueError as e:
49
+ raise ValueError(f"Invalid mappings data: {str(e)}")
50
+
51
+ def _to_dataframe(self, mapping_data: dict, prefix: bool = False) -> pd.DataFrame:
52
+ """Convert mapping values to DataFrame format"""
53
+ rows = []
54
+ for value in mapping_data['values']:
55
+ row = {}
56
+ for key, val in value['input'].items():
57
+ row[f'input.{key}' if prefix else key] = val
58
+ for key, val in value['output'].items():
59
+ row[f'output.{key}' if prefix else key] = val
60
+ rows.append(row)
61
+ return pd.DataFrame(rows)
62
+
63
+ def _to_dict(self, mapping_data: dict) -> dict:
64
+ """Convert mapping values to dictionary format"""
65
+ mappings = {}
66
+ for value in mapping_data['values']:
67
+ input_key = ','.join(value['input'].values())
68
+ output_value = ','.join(value['output'].values()) if len(value['output']) > 1 else next(iter(value['output'].values()))
69
+ mappings[input_key] = output_value
70
+ return mappings
71
+
72
+ def get(self, mapping: Optional[str] = None, as_df: bool = False, prefix: bool = False) -> dict:
73
+ """Get the mapping from BrynQ.
74
+
75
+ Args:
76
+ interface_id (int): The id of the task in BrynQ
77
+ mapping (str): The name of the mapping
78
+ as_df (bool, optional): If True, returns mappings as pandas DataFrame. If False, returns mappings as dictionary. Defaults to False.
79
+ prefix (bool, optional): Only used when as_df is True. If True, prefixes column names with 'input.' and 'output.'. Defaults to False.
80
+
81
+ Returns:
82
+ dict: Dictionary with keys:
83
+ - 'default_value': The default value for the mapping
84
+ - 'mappings': Either a DataFrame (if as_df=True) or a dictionary (if as_df=False)
85
+
86
+ Raises:
87
+ MappingNotFoundError: If mapping is not found
88
+ ValueError: If mapping data is invalid
89
+ """
90
+ mappings = self._get_mappings()
91
+ if mapping is None:
92
+ if as_df:
93
+ mapping_data = [{'default_value': item['default_value'], 'mappings': self._to_dataframe(item, prefix)} for item in mappings]
94
+ else:
95
+ mapping_data = [{'default_value': item['default_value'], 'mappings': self._to_dict(item)} for item in mappings]
96
+
97
+ return mapping_data
98
+ else:
99
+ mapping_data = next((item for item in mappings if item['name'] == mapping), None)
100
+
101
+ if not mapping_data:
102
+ raise MappingNotFoundError(f"Mapping named '{mapping}' not found")
103
+
104
+ return {
105
+ 'default_value': mapping_data['default_value'],
106
+ 'mappings': self._to_dataframe(mapping_data, prefix) if as_df else self._to_dict(mapping_data)
107
+ }
@@ -0,0 +1,251 @@
1
+ import requests
2
+ from typing import Dict, List, Any, Literal, Union, Optional
3
+ from .schemas.organization_chart import (
4
+ OrganizationChartNode,
5
+ OrganizationLayerCreate,
6
+ OrganizationLayerGet,
7
+ OrganizationLayerUpdate,
8
+ OrganizationNode,
9
+ OrganizationNodeCreate, OrganizationNodeUpdate
10
+ )
11
+ from brynq_sdk_functions import Functions
12
+
13
+
14
+ class OrganizationChart:
15
+ """
16
+ Handles all organization chart related operations for BrynQ SDK.
17
+ """
18
+ def __init__(self, brynq_instance):
19
+ """
20
+ Initialize OrganizationChart manager.
21
+
22
+ Args:
23
+ brynq_instance: The parent BrynQ instance
24
+ """
25
+ self._brynq = brynq_instance
26
+
27
+ def get(self, layout: Literal["nested", "flat"] = "nested") -> List[Dict[str, Any]]:
28
+ """Get all organization charts.
29
+
30
+ Args:
31
+ layout (str): Layout format, either "nested" or "flat"
32
+
33
+ Returns:
34
+ Dict[str, Any]: Organization charts data including:
35
+ - id (int): Node ID
36
+ - name (str): Node name
37
+ - dropIndex (int): Drop index for ordering
38
+ - parent_id (int, optional): Parent node ID, null for root nodes
39
+ - source_system_entities (List[str]): List of source system entities
40
+
41
+ Raises:
42
+ requests.exceptions.RequestException: If the API request fails
43
+ ValueError: If layout is not "nested" or "flat" or if the response data is invalid
44
+ """
45
+ if layout not in ["nested", "flat"]:
46
+ raise ValueError('layout must be either "nested" or "flat"')
47
+
48
+ response = self._brynq.brynq_session.get(
49
+ f"{self._brynq.url}organization-chart",
50
+ params={"layout": layout},
51
+ timeout=self._brynq.timeout
52
+ )
53
+ response.raise_for_status()
54
+
55
+ try:
56
+ chart_data = response.json()
57
+ valid_data, _ = Functions.validate_pydantic_data(chart_data, schema=OrganizationChartNode)
58
+ return valid_data
59
+ except ValueError as e:
60
+ raise ValueError(f"Invalid organization chart data: {str(e)}")
61
+
62
+ def get_layers(self) -> List[Dict[str, Any]]:
63
+ """Get all organization layers.
64
+
65
+ Returns:
66
+ Dict[str, Any]: Organization chart layers data including:
67
+ - id (int): Layer ID
68
+ - name (str): Layer name
69
+ - level (int): Layer level in hierarchy
70
+
71
+ Raises:
72
+ requests.exceptions.RequestException: If the API request fails
73
+ ValueError: If the response data is invalid
74
+ """
75
+ response = self._brynq.brynq_session.get(
76
+ f"{self._brynq.url}organization-chart/layers",
77
+ timeout=self._brynq.timeout
78
+ )
79
+ response.raise_for_status()
80
+
81
+ try:
82
+ layers_data = response.json()
83
+ valid_data, _ = Functions.validate_pydantic_data(layers_data, schema=OrganizationLayerGet)
84
+ return valid_data
85
+ except ValueError as e:
86
+ raise ValueError(f"Invalid organization layer data: {str(e)}")
87
+
88
+ def create_layer(self, data:Dict[str,Any]) -> Dict[str, Any]:
89
+ """Create a new organization layer.
90
+
91
+ Args:
92
+ data (Dict[str,Any]): Data to create a new layer for
93
+ {
94
+ name (str): Layer name
95
+ level (int): Layer level in hierarchy
96
+ }
97
+ Returns:
98
+ Dict[str, Any]: Response from the API
99
+
100
+ Raises:
101
+ requests.exceptions.RequestException: If the API request fails
102
+ ValueError: If the input data is invalid
103
+ """
104
+ valid_data, _ = Functions.validate_pydantic_data(data, schema=OrganizationLayerCreate)
105
+
106
+ response = self._brynq.brynq_session.post(
107
+ f"{self._brynq.url}organization-chart/layers",
108
+ json=valid_data[0],
109
+ timeout=self._brynq.timeout
110
+ )
111
+ response.raise_for_status()
112
+ return response
113
+
114
+ def update_layer(self, data:dict[str, Any]) -> Dict[str, Any]:
115
+ """Update an existing organization layer.
116
+
117
+ Args:
118
+ data(dict[]): Organization layer data
119
+ {
120
+ layer_id (int): ID of the layer to update
121
+ name (str): New layer name
122
+ level (int): New layer level in hierarchy
123
+ }
124
+ Returns:
125
+ Dict[str, Any]: Response from the API
126
+
127
+ Raises:
128
+ requests.exceptions.RequestException: If the API request fails
129
+ ValueError: If the input data is invalid
130
+ """
131
+ valid_data, _ = Functions.validate_pydantic_data(data, schema=OrganizationLayerUpdate)
132
+
133
+ response = self._brynq.brynq_session.put(
134
+ f"{self._brynq.url}organization-chart/layers/{data['id']}",
135
+ json=valid_data[0],
136
+ timeout=self._brynq.timeout
137
+ )
138
+ response.raise_for_status()
139
+ return response
140
+
141
+ def delete_layer(self, layer_id: int) -> None:
142
+ """Delete a layer and its underlying layers.
143
+
144
+ Args:
145
+ layer_id (int): ID of the layer to delete
146
+
147
+ Raises:
148
+ requests.exceptions.RequestException: If the API request fails
149
+ ValueError: If layer_id is not an integer
150
+ """
151
+ if not isinstance(layer_id, int):
152
+ raise ValueError("layer_id must be an integer")
153
+
154
+ response = self._brynq.brynq_session.delete(
155
+ f"{self._brynq.url}organization-chart/layers/{layer_id}",
156
+ timeout=self._brynq.timeout
157
+ )
158
+ response.raise_for_status()
159
+ return response
160
+
161
+ def get_nodes(self) -> List[Dict[str, Any]]:
162
+ """Get all organization chart nodes.
163
+
164
+ Returns:
165
+ Dict[str, Any]: Organization chart nodes data including:
166
+ - id (int): Node ID
167
+ - name (str): Node name
168
+ - parentId (int, optional): Parent node ID
169
+
170
+ Raises:
171
+ requests.exceptions.RequestException: If the API request fails
172
+ ValueError: If the response data is invalid
173
+ """
174
+ response = self._brynq.brynq_session.get(
175
+ url=f'{self._brynq.url}organization-chart/nodes',
176
+ timeout=self._brynq.timeout
177
+ )
178
+ response.raise_for_status()
179
+ valid_data, _ = Functions.validate_pydantic_data(response.json(), schema=OrganizationNode)
180
+ return valid_data
181
+
182
+ def create_nodes(self, data:dict) -> Dict[str, Any]:
183
+ """Create an organization chart node.
184
+
185
+ Args:
186
+ data (dict): Node data
187
+ {
188
+ name (str): Name of the node
189
+ position (int, optional): Position among siblings
190
+ parent_id (int, optional): ID of the parent node
191
+ }
192
+ Returns:
193
+ Dict[str, Any]: Response from the API
194
+
195
+ Raises:
196
+ requests.exceptions.RequestException: If the API request fails
197
+ ValueError: If the input data is invalid
198
+ """
199
+
200
+ valid_data, _ = Functions.validate_pydantic_data(data, schema=OrganizationNodeCreate)
201
+
202
+ response = self._brynq.brynq_session.post(
203
+ f"{self._brynq.url}organization-chart/nodes",
204
+ json=valid_data[0],
205
+ timeout=self._brynq.timeout
206
+ )
207
+ response.raise_for_status()
208
+ return response
209
+
210
+ def update_node(self, data: dict) -> dict:
211
+ """Update an organization chart node.
212
+
213
+ Args:
214
+ data (dict): Dictionary containing fields to update (e.g. name, position, parentId)
215
+
216
+ Returns:
217
+ dict: Updated node details returned from API
218
+
219
+ Raises:
220
+ ValueError: If node_id is not a positive integer
221
+ requests.exceptions.RequestException: If the API request fails
222
+ """
223
+ valid_data, _ = Functions.validate_pydantic_data(data, schema=OrganizationNodeUpdate)
224
+
225
+ response = self._brynq.brynq_session.put(
226
+ f"{self._brynq.url}organization-chart/nodes/{data['id']}",
227
+ json=valid_data[0],
228
+ timeout=self._brynq.timeout
229
+ )
230
+ response.raise_for_status()
231
+ return response
232
+
233
+ def delete_node(self, node_id: int) -> None:
234
+ """Delete a node and its underlying nodes.
235
+
236
+ Args:
237
+ node_id (int): ID of the layer to delete
238
+
239
+ Raises:
240
+ requests.exceptions.RequestException: If the API request fails
241
+ ValueError: If layer_id is not an integer
242
+ """
243
+ if not isinstance(node_id, int):
244
+ raise ValueError("node_id must be an integer")
245
+
246
+ response = self._brynq.brynq_session.delete(
247
+ f"{self._brynq.url}organization-chart/nodes/{node_id}",
248
+ timeout=self._brynq.timeout
249
+ )
250
+ response.raise_for_status()
251
+ return response