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

Potentially problematic release.


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

Files changed (29) hide show
  1. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/PKG-INFO +1 -1
  2. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/schemas/scenarios.py +52 -3
  3. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq.egg-info/PKG-INFO +1 -1
  4. brynq_sdk_brynq-4.1.0/brynq_sdk_brynq.egg-info/requires.txt +2 -0
  5. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/setup.py +3 -2
  6. brynq_sdk_brynq-4.0.10/brynq_sdk_brynq.egg-info/requires.txt +0 -1
  7. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/__init__.py +0 -0
  8. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/brynq.py +0 -0
  9. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/credentials.py +0 -0
  10. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/customers.py +0 -0
  11. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/interfaces.py +0 -0
  12. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/mappings.py +0 -0
  13. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/organization_chart.py +0 -0
  14. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/roles.py +0 -0
  15. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/scenarios.py +0 -0
  16. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/schemas/__init__.py +0 -0
  17. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/schemas/credentials.py +0 -0
  18. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/schemas/customers.py +0 -0
  19. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/schemas/interfaces.py +0 -0
  20. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/schemas/organization_chart.py +0 -0
  21. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/schemas/roles.py +0 -0
  22. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/schemas/users.py +0 -0
  23. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/source_systems.py +0 -0
  24. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq/users.py +0 -0
  25. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq.egg-info/SOURCES.txt +0 -0
  26. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq.egg-info/dependency_links.txt +0 -0
  27. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq.egg-info/not-zip-safe +0 -0
  28. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/brynq_sdk_brynq.egg-info/top_level.txt +0 -0
  29. {brynq_sdk_brynq-4.0.10 → brynq_sdk_brynq-4.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq_sdk_brynq
3
- Version: 4.0.10
3
+ Version: 4.1.0
4
4
  Summary: BrynQ SDK for the BrynQ.com platform
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -1,8 +1,12 @@
1
+ import re
1
2
  from collections import defaultdict
2
3
  from datetime import date
3
4
  from typing import Any, Dict, List, Literal, Optional, Set, Tuple, Type, Union
4
5
 
6
+ import pandera as pa
7
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
5
8
  from pydantic import BaseModel, ConfigDict, Field
9
+ from pandera.typing import Series, String # type: ignore[attr-defined]
6
10
  from typing_extensions import Annotated
7
11
 
8
12
 
@@ -186,8 +190,8 @@ class ParsedScenario(BaseModel):
186
190
  all_target_fields: Set[str]
187
191
  unique_fields: List[str]
188
192
  required_fields: List[str]
189
-
190
-
193
+ custom_source_fields: List[str]
194
+ custom_fields_model: Optional[type] = None
191
195
  alias_to_pythonic: Optional[Dict[str, str]] = None
192
196
  pythonic_to_alias: Optional[Dict[str, str]] = None
193
197
  all_pythonic_source_fields: Optional[List[str]] = None
@@ -336,6 +340,11 @@ class ParsedScenario(BaseModel):
336
340
  all_source_fields = set(src_map.keys())
337
341
  unique_fields = [fid for fid, props in props.items() if props.unique]
338
342
  required_fields = [fid for fid, props in props.items() if props.required]
343
+ custom_source_fields = list(dict.fromkeys(
344
+ fid for fid, field_props in props.items()
345
+ if field_props.system_type == "source" and
346
+ field_props.source.get('type') == 'CUSTOM'
347
+ ))
339
348
  source_to_target_map = {k: sorted(v) for k, v in src_map.items()}
340
349
  target_to_source_map = {k: sorted(v) for k, v in tgt_map.items()}
341
350
  all_target_fields = set(tgt_map.keys())
@@ -380,6 +389,8 @@ class ParsedScenario(BaseModel):
380
389
 
381
390
 
382
391
  # --- 3. Construct the final, frozen instance in a single call ---
392
+ custom_fields_model = cls._build_custom_field_model(custom_source_fields) if custom_source_fields else None
393
+
383
394
  instance = cls(
384
395
  name=scenario.get("name", "Unnamed"),
385
396
  id=scenario.get("id", ""),
@@ -389,6 +400,7 @@ class ParsedScenario(BaseModel):
389
400
  field_properties=props,
390
401
  unique_fields=unique_fields,
391
402
  required_fields=required_fields,
403
+ custom_source_fields=custom_source_fields,
392
404
  all_source_fields=all_source_fields,
393
405
  all_pythonic_source_fields=all_pythonic_source_fields,
394
406
  all_target_fields=all_target_fields,
@@ -396,7 +408,8 @@ class ParsedScenario(BaseModel):
396
408
  alias_to_pythonic=alias_to_pythonic,
397
409
  source_pythonic_to_target=source_pythonic_to_target,
398
410
  target_to_source_pythonic=target_to_source_pythonic,
399
- pythonic_to_alias={v: k for k, v in alias_to_pythonic.items()} if alias_to_pythonic else None
411
+ pythonic_to_alias={v: k for k, v in alias_to_pythonic.items()} if alias_to_pythonic else None,
412
+ custom_fields_model=custom_fields_model
400
413
  )
401
414
  return instance
402
415
 
@@ -446,6 +459,42 @@ class ParsedScenario(BaseModel):
446
459
  source_alias_to_pythonic[alias] = pythonic_field_name
447
460
 
448
461
  return source_alias_to_pythonic
462
+
463
+ @staticmethod
464
+ def _build_custom_field_model(custom_fields: List[str]) -> Optional[type]:
465
+ """
466
+ Create a Pandera schema model for custom fields configured in a scenario.
467
+
468
+ Args:
469
+ custom_fields: Source field names from the BrynQ scenario.
470
+
471
+ Returns:
472
+ A dynamically generated BrynQ Pandera model class or None when no fields can be mapped.
473
+ """
474
+ annotations: Dict[str, Any] = {}
475
+ model_fields: Dict[str, Any] = {}
476
+
477
+ for field in custom_fields:
478
+ alias = str(field)
479
+
480
+ # Convert to valid pythonic identifier
481
+ if alias.isidentifier():
482
+ pythonic_name = alias
483
+ else:
484
+ # Sanitize: replace non-word chars with underscore, handle digits
485
+ pythonic_name = re.sub(r"\W|^(?=\d)", "_", alias)
486
+ pythonic_name = re.sub(r"_+", "_", pythonic_name).strip("_").lower()
487
+ if not pythonic_name:
488
+ pythonic_name = "field"
489
+ if pythonic_name[0].isdigit():
490
+ pythonic_name = f"field_{pythonic_name}"
491
+
492
+ annotations[pythonic_name] = Optional[Series[String]]
493
+ model_fields[pythonic_name] = pa.Field(coerce=True, nullable=True, alias=str(alias))
494
+
495
+ model_fields["__annotations__"] = annotations
496
+ model = type("CustomFieldModel", (BrynQPanderaDataFrameModel,), model_fields)
497
+ return model
449
498
  class Config:
450
499
  frozen = True
451
500
  strict = True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq-sdk-brynq
3
- Version: 4.0.10
3
+ Version: 4.1.0
4
4
  Summary: BrynQ SDK for the BrynQ.com platform
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -0,0 +1,2 @@
1
+ requests<=3,>=2
2
+ pandera<=1.0.0,>=0.26.0
@@ -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.10',
5
+ version='4.1.0',
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',
@@ -10,7 +10,8 @@ setup(
10
10
  packages=find_namespace_packages(include=['brynq_sdk*']),
11
11
  license='BrynQ License',
12
12
  install_requires=[
13
- 'requests>=2,<=3'
13
+ 'requests>=2,<=3',
14
+ 'pandera>=0.26.0,<=1.0.0'
14
15
  ],
15
16
  zip_safe=False,
16
17
  )
@@ -1 +0,0 @@
1
- requests<=3,>=2