aepp 0.4.0.post2__py3-none-any.whl → 0.4.1.post1__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.
- aepp/__version__.py +1 -1
- aepp/classmanager.py +140 -54
- aepp/connector.py +4 -1
- aepp/datatypemanager.py +220 -55
- aepp/fieldgroupmanager.py +190 -59
- aepp/queryservice.py +9 -1
- aepp/schemamanager.py +9 -9
- aepp/segmentation.py +19 -2
- aepp/synchronizer.py +14 -9
- {aepp-0.4.0.post2.dist-info → aepp-0.4.1.post1.dist-info}/METADATA +1 -1
- {aepp-0.4.0.post2.dist-info → aepp-0.4.1.post1.dist-info}/RECORD +14 -14
- {aepp-0.4.0.post2.dist-info → aepp-0.4.1.post1.dist-info}/WHEEL +0 -0
- {aepp-0.4.0.post2.dist-info → aepp-0.4.1.post1.dist-info}/licenses/LICENSE +0 -0
- {aepp-0.4.0.post2.dist-info → aepp-0.4.1.post1.dist-info}/top_level.txt +0 -0
aepp/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.4.
|
|
1
|
+
__version__ = "0.4.1-1"
|
aepp/classmanager.py
CHANGED
|
@@ -4,6 +4,7 @@ import aepp
|
|
|
4
4
|
from .configs import ConnectObject
|
|
5
5
|
from aepp.schema import Schema
|
|
6
6
|
import pandas as pd
|
|
7
|
+
import numpy as np
|
|
7
8
|
from copy import deepcopy
|
|
8
9
|
from io import FileIO
|
|
9
10
|
from pathlib import Path
|
|
@@ -451,11 +452,7 @@ class ClassManager:
|
|
|
451
452
|
res,foundFlag = self.__setField__(completePathList,fieldGroup[key]['properties'],newField,obj)
|
|
452
453
|
fieldGroup[key]['properties'] = res
|
|
453
454
|
else:
|
|
454
|
-
|
|
455
|
-
fieldGroup[key]['properties'][newField]['title'] = obj["title"]
|
|
456
|
-
fieldGroup[key]['properties'][newField]['description'] = obj["description"]
|
|
457
|
-
else:
|
|
458
|
-
fieldGroup[key]['properties'][newField] = obj
|
|
455
|
+
fieldGroup[key]['properties'][newField] = obj
|
|
459
456
|
foundFlag = True
|
|
460
457
|
return fieldGroup,foundFlag
|
|
461
458
|
elif 'items' in level.keys():
|
|
@@ -464,11 +461,7 @@ class ClassManager:
|
|
|
464
461
|
res, foundFlag = self.__setField__(completePathList,fieldGroup[key]['items']['properties'],newField,obj)
|
|
465
462
|
fieldGroup[key]['items']['properties'] = res
|
|
466
463
|
else:
|
|
467
|
-
|
|
468
|
-
fieldGroup[key]['items']['properties'][newField]['title'] = obj['title']
|
|
469
|
-
fieldGroup[key]['items']['properties'][newField]['description'] = obj['description']
|
|
470
|
-
else:
|
|
471
|
-
fieldGroup[key]['items']['properties'][newField] = obj
|
|
464
|
+
fieldGroup[key]['items']['properties'][newField] = obj
|
|
472
465
|
foundFlag = True
|
|
473
466
|
return fieldGroup,foundFlag
|
|
474
467
|
return fieldGroup,foundFlag
|
|
@@ -504,9 +497,16 @@ class ClassManager:
|
|
|
504
497
|
return success
|
|
505
498
|
return success
|
|
506
499
|
|
|
507
|
-
def __transformFieldType__(self,dataType:str=None)->dict:
|
|
500
|
+
def __transformFieldType__(self,dataType:str=None,**kwargs)->dict:
|
|
508
501
|
"""
|
|
509
502
|
return the object with the type and possible meta attribute.
|
|
503
|
+
possible kwargs:
|
|
504
|
+
minimum : minimum value for number/integer
|
|
505
|
+
maximum : maximum value for number/integer
|
|
506
|
+
pattern : pattern for string
|
|
507
|
+
minLength : minimum length for string
|
|
508
|
+
maxLength : maximum length for string
|
|
509
|
+
default : default value for the field
|
|
510
510
|
"""
|
|
511
511
|
obj = {}
|
|
512
512
|
if dataType == 'double':
|
|
@@ -531,6 +531,10 @@ class ClassManager:
|
|
|
531
531
|
obj['minimum'] = -128
|
|
532
532
|
else:
|
|
533
533
|
obj['type'] = dataType
|
|
534
|
+
list_possible_kwargs = ['minimum','maximum','pattern','minLength','maxLength','enum','default']
|
|
535
|
+
for kw in kwargs:
|
|
536
|
+
if kw in list_possible_kwargs:
|
|
537
|
+
obj[kw] = kwargs[kw]
|
|
534
538
|
return obj
|
|
535
539
|
|
|
536
540
|
def __transformationDict__(self,mydict:dict=None,typed:bool=False,dictionary:dict=None)->dict:
|
|
@@ -651,9 +655,8 @@ class ClassManager:
|
|
|
651
655
|
dictionary:dict=None,
|
|
652
656
|
path:str=None,
|
|
653
657
|
queryPath:bool=False,
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
required:bool=False)->dict:
|
|
658
|
+
required:bool=False,
|
|
659
|
+
full:bool=False)->dict:
|
|
657
660
|
"""
|
|
658
661
|
Transform the current XDM schema to a dictionary.
|
|
659
662
|
Arguments:
|
|
@@ -664,15 +667,22 @@ class ClassManager:
|
|
|
664
667
|
description : boolean to tell if you want to retrieve the description
|
|
665
668
|
xdmType : boolean to know if you want to retrieve the xdm Type
|
|
666
669
|
required : boolean to know if you want to retrieve the required fields
|
|
670
|
+
full : boolean : to know if you want to retrieve all the information (minLength, etc)
|
|
667
671
|
"""
|
|
668
672
|
if dictionary is None:
|
|
669
|
-
dictionary = {'path':[],'type':[],'title':[]}
|
|
670
|
-
if queryPath:
|
|
673
|
+
dictionary = {'path':[],'type':[],'title':[],'description':[],'xdmType':[],'mapType':[]}
|
|
674
|
+
if queryPath or full:
|
|
671
675
|
dictionary['querypath'] = []
|
|
672
|
-
if
|
|
673
|
-
dictionary['
|
|
674
|
-
|
|
675
|
-
dictionary['
|
|
676
|
+
if full:
|
|
677
|
+
dictionary['minLength'] = []
|
|
678
|
+
dictionary['maxLength'] = []
|
|
679
|
+
dictionary['minimum'] = []
|
|
680
|
+
dictionary['maximum'] = []
|
|
681
|
+
dictionary['pattern'] = []
|
|
682
|
+
dictionary['enumValues'] = []
|
|
683
|
+
dictionary['enum'] = []
|
|
684
|
+
dictionary['default'] = []
|
|
685
|
+
dictionary['metaStatus'] = []
|
|
676
686
|
else:
|
|
677
687
|
dictionary = dictionary
|
|
678
688
|
for key in mydict:
|
|
@@ -687,14 +697,30 @@ class ClassManager:
|
|
|
687
697
|
tmp_path = f"{path}.{key}"
|
|
688
698
|
if tmp_path is not None:
|
|
689
699
|
dictionary["path"].append(tmp_path)
|
|
690
|
-
dictionary["type"].append(f"{mydict[key].get('type')}")
|
|
691
|
-
dictionary["title"].append(f"{mydict[key].get('title')}")
|
|
692
|
-
|
|
700
|
+
dictionary["type"].append(f"{mydict[key].get('type','')}")
|
|
701
|
+
dictionary["title"].append(f"{mydict[key].get('title','')}")
|
|
702
|
+
dictionary["description"].append(f"{mydict[key].get('description','')}")
|
|
703
|
+
dictionary["xdmType"].append(f"{mydict[key].get('meta:xdmType','')}")
|
|
704
|
+
if mydict[key].get('meta:xdmType') == 'map':
|
|
705
|
+
dictionary["mapType"].append(f"{mydict[key].get('additionalProperties',{}).get('type','string')}")
|
|
706
|
+
else:
|
|
707
|
+
dictionary["mapType"].append(pd.NA)
|
|
708
|
+
if queryPath or full:
|
|
693
709
|
dictionary["querypath"].append(self.__cleanPath__(tmp_path))
|
|
694
|
-
if
|
|
695
|
-
dictionary[
|
|
696
|
-
|
|
697
|
-
dictionary[
|
|
710
|
+
if full:
|
|
711
|
+
dictionary['metaStatus'].append(mydict[key].get('meta:status',pd.NA))
|
|
712
|
+
dictionary['minLength'].append(mydict[key].get('minLength',np.nan))
|
|
713
|
+
dictionary['maxLength'].append(mydict[key].get('maxLength',np.nan))
|
|
714
|
+
dictionary['minimum'].append(mydict[key].get('minimum',np.nan))
|
|
715
|
+
dictionary['maximum'].append(mydict[key].get('maximum',np.nan))
|
|
716
|
+
dictionary['pattern'].append(mydict[key].get('pattern',pd.NA))
|
|
717
|
+
dictionary['default'].append(mydict[key].get('default',pd.NA))
|
|
718
|
+
enumValues = mydict[key].get('meta:enum',pd.NA)
|
|
719
|
+
dictionary['enumValues'].append(enumValues)
|
|
720
|
+
if len(mydict[key].get('enum',[])) > 0:
|
|
721
|
+
dictionary['enum'].append(True)
|
|
722
|
+
else:
|
|
723
|
+
dictionary['enum'].append(False)
|
|
698
724
|
if required:
|
|
699
725
|
if len(mydict[key].get('required',[])) > 0:
|
|
700
726
|
for elRequired in mydict[key].get('required',[]):
|
|
@@ -705,7 +731,7 @@ class ClassManager:
|
|
|
705
731
|
self.requiredFields.add(tmp_reqPath)
|
|
706
732
|
properties = mydict[key].get('properties',None)
|
|
707
733
|
if properties is not None:
|
|
708
|
-
self.__transformationDF__(properties,dictionary,tmp_path,queryPath,
|
|
734
|
+
self.__transformationDF__(properties,dictionary,tmp_path,queryPath,required,full=full)
|
|
709
735
|
elif mydict[key].get('type') == 'array':
|
|
710
736
|
levelProperties = mydict[key]['items'].get('properties',None)
|
|
711
737
|
if levelProperties is not None: ## array of objects
|
|
@@ -715,13 +741,29 @@ class ClassManager:
|
|
|
715
741
|
tmp_path = f"{path}.{key}[]{{}}"
|
|
716
742
|
dictionary["path"].append(tmp_path)
|
|
717
743
|
dictionary["type"].append(f"{mydict[key].get('type')}")
|
|
718
|
-
dictionary["title"].append(f"{mydict[key].get('title')}")
|
|
719
|
-
|
|
744
|
+
dictionary["title"].append(f"{mydict[key].get('title','')}")
|
|
745
|
+
dictionary["description"].append(mydict[key].get('description',''))
|
|
746
|
+
dictionary["xdmType"].append(f"{mydict[key].get('meta:xdmType','')}")
|
|
747
|
+
if mydict[key].get('meta:xdmType') == 'map':
|
|
748
|
+
dictionary["mapType"].append(f"{mydict[key].get('additionalProperties',{}).get('type','string')}")
|
|
749
|
+
else:
|
|
750
|
+
dictionary["mapType"].append(pd.NA)
|
|
751
|
+
if (queryPath or full) and tmp_path is not None:
|
|
720
752
|
dictionary["querypath"].append(self.__cleanPath__(tmp_path))
|
|
721
|
-
if
|
|
722
|
-
dictionary[
|
|
723
|
-
|
|
724
|
-
dictionary[
|
|
753
|
+
if full:
|
|
754
|
+
dictionary['metaStatus'].append(mydict[key].get('meta:status',pd.NA))
|
|
755
|
+
dictionary['minLength'].append(mydict[key].get('minLength',np.nan))
|
|
756
|
+
dictionary['maxLength'].append(mydict[key].get('maxLength',np.nan))
|
|
757
|
+
dictionary['minimum'].append(mydict[key].get('minimum',np.nan))
|
|
758
|
+
dictionary['maximum'].append(mydict[key].get('maximum',np.nan))
|
|
759
|
+
dictionary['pattern'].append(mydict[key].get('pattern',pd.NA))
|
|
760
|
+
dictionary['default'].append(mydict[key].get('default',pd.NA))
|
|
761
|
+
enumValues = mydict[key].get('meta:enum',pd.NA)
|
|
762
|
+
dictionary['enumValues'].append(enumValues)
|
|
763
|
+
if len(mydict[key].get('enum',[])) > 0:
|
|
764
|
+
dictionary['enum'].append(True)
|
|
765
|
+
else:
|
|
766
|
+
dictionary['enum'].append(False)
|
|
725
767
|
if required:
|
|
726
768
|
if len(mydict[key].get('required',[])) > 0:
|
|
727
769
|
for elRequired in mydict[key].get('required',[]):
|
|
@@ -730,21 +772,37 @@ class ClassManager:
|
|
|
730
772
|
else:
|
|
731
773
|
tmp_reqPath = f"{elRequired}"
|
|
732
774
|
self.requiredFields.add(tmp_reqPath)
|
|
733
|
-
self.__transformationDF__(levelProperties,dictionary,tmp_path,queryPath,
|
|
775
|
+
self.__transformationDF__(levelProperties,dictionary,tmp_path,queryPath,required,full=full)
|
|
734
776
|
else: ## simple arrays
|
|
735
777
|
if path is None:
|
|
736
778
|
finalpath = f"{key}[]"
|
|
737
779
|
else:
|
|
738
780
|
finalpath = f"{path}.{key}[]"
|
|
739
781
|
dictionary["path"].append(finalpath)
|
|
740
|
-
dictionary["type"].append(f"{mydict[key]['items'].get('type')}[]")
|
|
741
|
-
dictionary["title"].append(f"{mydict[key].get('title')}")
|
|
742
|
-
|
|
782
|
+
dictionary["type"].append(f"{mydict[key]['items'].get('type','')}[]")
|
|
783
|
+
dictionary["title"].append(f"{mydict[key].get('title','')}")
|
|
784
|
+
dictionary["description"].append(mydict[key].get('description',''))
|
|
785
|
+
dictionary["xdmType"].append(mydict[key]['items'].get('meta:xdmType',''))
|
|
786
|
+
if mydict[key]['items'].get('meta:xdmType') == 'map':
|
|
787
|
+
dictionary["mapType"].append(f"{mydict[key]['items'].get('additionalProperties',{}).get('type','string')}")
|
|
788
|
+
else:
|
|
789
|
+
dictionary["mapType"].append(pd.NA)
|
|
790
|
+
if queryPath or full:
|
|
743
791
|
dictionary["querypath"].append(self.__cleanPath__(finalpath))
|
|
744
|
-
if
|
|
745
|
-
dictionary[
|
|
746
|
-
|
|
747
|
-
dictionary[
|
|
792
|
+
if full:
|
|
793
|
+
dictionary['metaStatus'].append(mydict[key]['items'].get('meta:status',pd.NA))
|
|
794
|
+
dictionary['minLength'].append(mydict[key]['items'].get('minLength',np.nan))
|
|
795
|
+
dictionary['maxLength'].append(mydict[key]['items'].get('maxLength',np.nan))
|
|
796
|
+
dictionary['minimum'].append(mydict[key]['items'].get('minimum',np.nan))
|
|
797
|
+
dictionary['maximum'].append(mydict[key]['items'].get('maximum',np.nan))
|
|
798
|
+
dictionary['pattern'].append(mydict[key]['items'].get('pattern',np.nan))
|
|
799
|
+
dictionary['default'].append(mydict[key]['items'].get('default',np.nan))
|
|
800
|
+
enumValues = mydict[key]['items'].get('meta:enum',pd.NA)
|
|
801
|
+
dictionary['enumValues'].append(enumValues)
|
|
802
|
+
if len(mydict[key]['items'].get('enum',[])) > 0:
|
|
803
|
+
dictionary['enum'].append(True)
|
|
804
|
+
else:
|
|
805
|
+
dictionary['enum'].append(False)
|
|
748
806
|
if required:
|
|
749
807
|
if len(mydict[key].get('required',[])) > 0:
|
|
750
808
|
for elRequired in mydict[key].get('required',[]):
|
|
@@ -758,12 +816,28 @@ class ClassManager:
|
|
|
758
816
|
dictionary["path"].append(finalpath)
|
|
759
817
|
dictionary["type"].append(mydict[key].get('type','object'))
|
|
760
818
|
dictionary["title"].append(mydict[key].get('title',''))
|
|
761
|
-
|
|
819
|
+
dictionary["description"].append(mydict[key].get('description',''))
|
|
820
|
+
dictionary["xdmType"].append(mydict[key].get('meta:xdmType',''))
|
|
821
|
+
if mydict[key].get('meta:xdmType') == 'map':
|
|
822
|
+
dictionary["mapType"].append(f"{mydict[key].get('additionalProperties',{}).get('type','string')}")
|
|
823
|
+
else:
|
|
824
|
+
dictionary["mapType"].append(pd.NA)
|
|
825
|
+
if queryPath or full:
|
|
762
826
|
dictionary["querypath"].append(self.__cleanPath__(finalpath))
|
|
763
|
-
if
|
|
764
|
-
dictionary[
|
|
765
|
-
|
|
766
|
-
dictionary[
|
|
827
|
+
if full:
|
|
828
|
+
dictionary['metaStatus'].append(mydict[key].get('meta:status',pd.NA))
|
|
829
|
+
dictionary['minLength'].append(mydict[key].get('minLength',np.nan))
|
|
830
|
+
dictionary['maxLength'].append(mydict[key].get('maxLength',np.nan))
|
|
831
|
+
dictionary['minimum'].append(mydict[key].get('minimum',np.nan))
|
|
832
|
+
dictionary['maximum'].append(mydict[key].get('maximum',np.nan))
|
|
833
|
+
dictionary['pattern'].append(mydict[key].get('pattern',pd.NA))
|
|
834
|
+
dictionary['default'].append(mydict[key].get('default',pd.NA))
|
|
835
|
+
enumValues = mydict[key].get('meta:enum',pd.NA)
|
|
836
|
+
dictionary['enumValues'].append(enumValues)
|
|
837
|
+
if len(mydict[key].get('enum',[])) > 0:
|
|
838
|
+
dictionary['enum'].append(True)
|
|
839
|
+
else:
|
|
840
|
+
dictionary['enum'].append(False)
|
|
767
841
|
if required:
|
|
768
842
|
if len(mydict[key].get('required',[])) > 0:
|
|
769
843
|
for elRequired in mydict[key].get('required',[]):
|
|
@@ -857,6 +931,12 @@ class ClassManager:
|
|
|
857
931
|
possible kwargs:
|
|
858
932
|
defaultPath : Define which path to take by default for adding new field on tenant. Default "customFields", possible alternative : "property"
|
|
859
933
|
description : if you want to add a description on your field
|
|
934
|
+
maximum : if you want to add a maximum value for numeric field
|
|
935
|
+
minimum : if you want to add a minimum value for numeric field
|
|
936
|
+
pattern : if you want to add a pattern for string field
|
|
937
|
+
minLength : if you want to add a minimum length for string field
|
|
938
|
+
maxLength : if you want to add a maximum length for string field
|
|
939
|
+
default : if you want to add a default value for the field
|
|
860
940
|
"""
|
|
861
941
|
if self.EDITABLE == False:
|
|
862
942
|
raise Exception("The Field Group is not Editable via Field Group Manager")
|
|
@@ -916,14 +996,20 @@ class ClassManager:
|
|
|
916
996
|
"title":title
|
|
917
997
|
}
|
|
918
998
|
else:
|
|
919
|
-
|
|
999
|
+
minimum = kwargs.get('minimum',None)
|
|
1000
|
+
maximum = kwargs.get('maximum',None)
|
|
1001
|
+
pattern = kwargs.get('pattern',None)
|
|
1002
|
+
minLength = kwargs.get('minLength',None)
|
|
1003
|
+
maxLength = kwargs.get('maxLength',None)
|
|
1004
|
+
default = kwargs.get('default',None)
|
|
1005
|
+
obj = self.__transformFieldType__(dataType,minimum=minimum,maximum=maximum,pattern=pattern,minLength=minLength,maxLength=maxLength,default=default)
|
|
920
1006
|
obj['title'] = title
|
|
921
1007
|
obj["description"] = description,
|
|
922
1008
|
if type(obj["description"]) == tuple:
|
|
923
1009
|
obj["description"] = obj["description"][0]
|
|
924
1010
|
if array:
|
|
925
1011
|
obj['type'] = "array"
|
|
926
|
-
obj['items'] = self.__transformFieldType__(dataType)
|
|
1012
|
+
obj['items'] = self.__transformFieldType__(dataType,minimum=minimum,maximum=maximum,pattern=pattern,minLength=minLength,maxLength=maxLength,default=default)
|
|
927
1013
|
if enumValues is not None and type(enumValues) == dict:
|
|
928
1014
|
if array == False:
|
|
929
1015
|
obj['meta:enum'] = enumValues
|
|
@@ -987,28 +1073,28 @@ class ClassManager:
|
|
|
987
1073
|
xdmType:bool=True,
|
|
988
1074
|
editable:bool=False,
|
|
989
1075
|
excludeObjects:bool=False,
|
|
990
|
-
required:bool=False
|
|
1076
|
+
required:bool=False,
|
|
1077
|
+
full:bool=False)->pd.DataFrame:
|
|
991
1078
|
"""
|
|
992
1079
|
Generate a dataframe with the row representing each possible path.
|
|
993
1080
|
Arguments:
|
|
994
1081
|
save : OPTIONAL : If you wish to save it with the title used by the field group.
|
|
995
1082
|
save as csv with the title used. Not title, used "unknown_fieldGroup_" + timestamp.
|
|
996
1083
|
queryPath : OPTIONAL : If you want to have the query path to be used.
|
|
997
|
-
description : OPTIONAL : If you want to have the description used (default False)
|
|
998
|
-
xdmType : OPTIONAL : If you want to have the xdmType also returned (default True)
|
|
999
1084
|
editable : OPTIONAL : If you can manipulate the structure of the field groups (default False)
|
|
1000
1085
|
excludeObjects : OPTIONAL : Remove the fields that are noted down as object so only fields containing data are returned.
|
|
1001
1086
|
required : OPTIONAL : If you want to have the required field in the dataframe (default False)
|
|
1087
|
+
full : OPTIONAL : If you want to have all the possible attributes (minLength, maxLength, pattern, enum, default) in the dataframe (default False)
|
|
1002
1088
|
"""
|
|
1003
1089
|
definition = self.aepclass.get('definitions',self.aepclass.get('properties',{}))
|
|
1004
|
-
data = self.__transformationDF__(definition,queryPath=queryPath,
|
|
1090
|
+
data = self.__transformationDF__(definition,queryPath=queryPath,required=required,full=full)
|
|
1005
1091
|
df = pd.DataFrame(data)
|
|
1006
1092
|
df = df[~df.path.duplicated()].copy() ## dedup the paths
|
|
1007
1093
|
df = df[~(df['path']==self.tenantId)].copy()## remove the root
|
|
1008
1094
|
df['origin'] = 'class'
|
|
1009
1095
|
if self.EDITABLE:
|
|
1010
1096
|
behaviorDefinition = self.behaviorDefinition.get('properties')
|
|
1011
|
-
dataBehavior = self.__transformationDF__(behaviorDefinition,queryPath=queryPath,
|
|
1097
|
+
dataBehavior = self.__transformationDF__(behaviorDefinition,queryPath=queryPath,required=required,full=full)
|
|
1012
1098
|
dfBehavior = pd.DataFrame(dataBehavior)
|
|
1013
1099
|
dfBehavior['origin'] = 'class behavior'
|
|
1014
1100
|
df = pd.concat([df,dfBehavior],axis=0,ignore_index=True)
|
aepp/connector.py
CHANGED
|
@@ -250,7 +250,10 @@ class AdobeRequest:
|
|
|
250
250
|
endpoint = f"{self.endpoints['global']}{self.endpoints['sandboxes']}/sandboxes/{sandbox}"
|
|
251
251
|
res = self.getData(endpoint)
|
|
252
252
|
if "id" not in res:
|
|
253
|
-
|
|
253
|
+
error_message = res.get("message", "sandbox Id not found")
|
|
254
|
+
if self.loggingEnabled:
|
|
255
|
+
self.logger.error(f"sandbox id '{sandbox}' retrieval failed: {error_message}")
|
|
256
|
+
raise Exception(error_message)
|
|
254
257
|
sandbox_id = res["id"]
|
|
255
258
|
self.header["x-sandbox-id"] = sandbox_id
|
|
256
259
|
|