brynq-sdk-brynq 4.0.8__tar.gz → 4.0.10__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.

Potentially problematic release.


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

Files changed (28) hide show
  1. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/PKG-INFO +1 -1
  2. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/scenarios.py +13 -8
  3. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/schemas/scenarios.py +49 -34
  4. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq.egg-info/PKG-INFO +1 -1
  5. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/setup.py +1 -1
  6. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/__init__.py +0 -0
  7. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/brynq.py +0 -0
  8. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/credentials.py +0 -0
  9. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/customers.py +0 -0
  10. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/interfaces.py +0 -0
  11. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/mappings.py +0 -0
  12. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/organization_chart.py +0 -0
  13. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/roles.py +0 -0
  14. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/schemas/__init__.py +0 -0
  15. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/schemas/credentials.py +0 -0
  16. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/schemas/customers.py +0 -0
  17. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/schemas/interfaces.py +0 -0
  18. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/schemas/organization_chart.py +0 -0
  19. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/schemas/roles.py +0 -0
  20. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/schemas/users.py +0 -0
  21. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/source_systems.py +0 -0
  22. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq/users.py +0 -0
  23. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq.egg-info/SOURCES.txt +0 -0
  24. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq.egg-info/dependency_links.txt +0 -0
  25. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq.egg-info/not-zip-safe +0 -0
  26. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq.egg-info/requires.txt +0 -0
  27. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/brynq_sdk_brynq.egg-info/top_level.txt +0 -0
  28. {brynq_sdk_brynq-4.0.8 → brynq_sdk_brynq-4.0.10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq_sdk_brynq
3
- Version: 4.0.8
3
+ Version: 4.0.10
4
4
  Summary: BrynQ SDK for the BrynQ.com platform
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -244,14 +244,8 @@ class Scenarios():
244
244
  source_type = value.source['type']
245
245
  if source_type == 'FIXED':
246
246
  source_value = value.source['data']
247
- parts = value.target['data'][0].split('-')
248
- if len(parts) > 1:
249
- target_field = parts[-1] # Taking the last part is safest.
250
- df_with_fixed[target_field] = source_value
251
- else:
252
- warnings.warn(f"Target field of {parts} not found in dataframe due to unexpected format of target field (should be sdkmethod-field).")
253
- if target_field not in df_with_fixed.columns:
254
- warnings.warn(f"Target field {target_field} not found in dataframe.")
247
+ target_field = value.target['data'][0]['field']
248
+ df_with_fixed[target_field] = source_value
255
249
  except Exception as e:
256
250
  warnings.warn(f"Error adding fixed value to dataframe: {e}")
257
251
  continue
@@ -331,11 +325,17 @@ class Scenarios():
331
325
  # Handle different cases for source and target mapping
332
326
  if source_map_val and target_map_val and len(target_map_val) == 1:
333
327
  target_val = list(target_map_val.values())[0]
328
+ # Strip whitespace and newline characters from target value
329
+ target_val = target_val.strip()
334
330
 
335
331
  # Case 1: Single source field to single target field
336
332
  if len(source_map_val) == 1:
337
333
  source_val = list(source_map_val.values())[0]
338
334
 
335
+ # Strip whitespace and newline characters from both values
336
+ source_val = source_val.strip()
337
+ target_val = target_val.strip()
338
+
339
339
  # Clean the mapping values to handle different delimiters
340
340
  if (fix_source_val) and ('-' in source_val or ':' in source_val):
341
341
  source_val = source_val.replace('-', ':').split(':')[0]
@@ -361,6 +361,8 @@ class Scenarios():
361
361
  for field_alias in source_field_aliases:
362
362
  if field_alias in transformed_source_map:
363
363
  field_val = transformed_source_map[field_alias]
364
+ # Strip whitespace and newline characters
365
+ field_val = field_val.strip()
364
366
  # Clean the mapping values
365
367
  if (fix_source_val) and ('-' in field_val or ':' in field_val):
366
368
  field_val = field_val.replace('-', ':').split(':')[0]
@@ -370,6 +372,9 @@ class Scenarios():
370
372
  if len(source_values) == len(source_field_aliases):
371
373
  combined_source_val = '|'.join(source_values)
372
374
 
375
+ # Strip whitespace and newline characters from target value
376
+ target_val = target_val.strip()
377
+
373
378
  # Clean target value
374
379
  if (fix_target_val) and ('-' in target_val or ':' in target_val):
375
380
  target_val = target_val.replace('-', ':').split(':')[0]
@@ -50,14 +50,30 @@ class CustomSourceTarget(BaseModel):
50
50
  populate_by_name = True
51
51
 
52
52
 
53
+ class LibraryFieldDescriptor(BaseModel):
54
+ """Rich metadata describing a library field target."""
55
+ id: Optional[int] = None
56
+ uuid: Optional[str] = None
57
+ required: Optional[bool] = None
58
+ field: Optional[str] = None
59
+ field_label: Optional[Dict[str, str]] = Field(default=None, alias="fieldLabel")
60
+ app_id: Optional[int] = Field(default=None, alias="appId")
61
+ category: Optional[Dict[str, Any]] = None
62
+
63
+ class Config:
64
+ frozen = True
65
+ strict = True
66
+ populate_by_name = True
67
+
68
+
53
69
  class LibrarySourceTarget(BaseModel):
54
70
  type: Literal["LIBRARY"] = Field(
55
71
  "LIBRARY",
56
72
  description="Discriminator—fixed value for library look-ups"
57
73
  )
58
- data: List[str] = Field(
74
+ data: List[Union[str, LibraryFieldDescriptor]] = Field(
59
75
  ...,
60
- description="List of library field identifiers"
76
+ description="List of library field identifiers or metadata objects"
61
77
  )
62
78
 
63
79
  class Config:
@@ -128,8 +144,9 @@ class ScenarioDetail(BaseModel):
128
144
 
129
145
  source: SourceTarget = Field(..., description="Source definition")
130
146
  target: SourceTarget = Field(..., description="Target definition")
131
- mapping: ScenarioMappingConfiguration = Field(
132
- ..., description="Mapping/value-translation configuration"
147
+ mapping: Optional[ScenarioMappingConfiguration] = Field(
148
+ default=None,
149
+ description="Mapping/value-translation configuration (may be absent)"
133
150
  )
134
151
 
135
152
  class Config:
@@ -266,45 +283,43 @@ class ParsedScenario(BaseModel):
266
283
  props: Dict[str, FieldProperties] = {}
267
284
  source_to_value_maps: Dict[str, List[ScenarioMappingConfiguration]] = defaultdict(list)
268
285
 
269
- def _extract_name(path: dict, data_type: str = "LIBRARY") -> Optional[str]:
270
- """Extracts a name from a path object based on its data type."""
271
- # Process dictionary-based paths.
272
- if isinstance(path, dict):
273
- if data_type == "CUSTOM":
274
- return path.get("technical_name")
275
- if data_type == "LIBRARY":
276
- return path.get("data")
277
- else:
278
- return None
279
- # For data_type == "FIXED" or any other unhandled type, implicitly return None.
280
- elif isinstance(path, str): #string-based paths
281
- if data_type != "FIXED":
282
- return path.split("-")[-1]
283
- else:
284
- return None
285
- else:
286
- return None
286
+ def _extract_names_from_branch(branch: SourceTarget) -> Set[str]:
287
+ """Normalise source/target branch data into canonical field names."""
288
+ if isinstance(branch, CustomSourceTarget):
289
+ names = {item.technical_name for item in branch.data if item.technical_name}
290
+ if names:
291
+ return names
292
+ return {item.uuid for item in branch.data if getattr(item, "uuid", None)}
293
+ if isinstance(branch, LibrarySourceTarget):
294
+ names: Set[str] = set()
295
+ for entry in branch.data:
296
+ if isinstance(entry, str):
297
+ names.add(entry)
298
+ else:
299
+ if entry.field:
300
+ names.add(entry.field)
301
+ elif entry.uuid:
302
+ names.add(entry.uuid)
303
+ return names
304
+ if isinstance(branch, FixedSourceTarget):
305
+ return set()
306
+ return set()
287
307
 
288
308
  for detail in details:
289
- source_data = detail.get("source", {}).get("data", [])
290
- source_type = detail.get("source", {}).get("type", "LIBRARY")
291
- target_data = detail.get("target", {}).get("data", [])
292
- target_type = detail.get("target", {}).get("type", "LIBRARY")
309
+ detail_model = ScenarioDetail.model_validate(detail)
293
310
 
294
- source_names = {name for p in source_data for name in [ _extract_name(p, source_type) ] if name is not None}
295
- target_names = {name for p in target_data for name in [ _extract_name(p, target_type) ] if name is not None}
311
+ source_names = _extract_names_from_branch(detail_model.source)
312
+ target_names = _extract_names_from_branch(detail_model.target)
296
313
 
297
314
  for s_name in source_names:
298
315
  src_map[s_name].update(target_names)
299
316
  for t_name in target_names:
300
317
  tgt_map[t_name].update(source_names)
301
318
 
302
- mapping_config_data = detail.get("mapping")
303
- if mapping_config_data:
304
- mapping_config = ScenarioMappingConfiguration.model_validate(mapping_config_data)
305
- if mapping_config.values:
306
- key = '|'.join(source_names)
307
- source_to_value_maps[key].append(mapping_config)
319
+ mapping_config = detail_model.mapping
320
+ if mapping_config and mapping_config.values:
321
+ key = '|'.join(sorted(source_names)) if source_names else detail_model.id
322
+ source_to_value_maps[key].append(mapping_config)
308
323
 
309
324
  base_props = FieldProperties.model_validate(detail)
310
325
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq-sdk-brynq
3
- Version: 4.0.8
3
+ Version: 4.0.10
4
4
  Summary: BrynQ SDK for the BrynQ.com platform
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -2,7 +2,7 @@ from setuptools import find_namespace_packages, setup
2
2
 
3
3
  setup(
4
4
  name='brynq_sdk_brynq',
5
- version='4.0.8',
5
+ version='4.0.10',
6
6
  description='BrynQ SDK for the BrynQ.com platform',
7
7
  long_description='BrynQ SDK for the BrynQ.com platform',
8
8
  author='BrynQ',