11
11
12
12
from .exceptions import TypeSalesforceException
13
13
from .rate_limiting import default_backoff_handler
14
- from .utils import filter_streams
14
+ from .utils import filter_streams_by_criteria
15
15
16
16
STRING_TYPES = [
17
17
"byte" ,
@@ -191,7 +191,9 @@ def __init__(
191
191
self .access_token = None
192
192
self .instance_url = None
193
193
self .session = requests .Session ()
194
- self .is_sandbox = is_sandbox is True or (isinstance (is_sandbox , str ) and is_sandbox .lower () == "true" )
194
+ self .is_sandbox = is_sandbox in [True , "true" ]
195
+ if self .is_sandbox :
196
+ self .logger .info ("using SANDBOX of Salesforce" )
195
197
self .start_date = start_date
196
198
197
199
def _get_standard_headers (self ):
@@ -206,30 +208,37 @@ def filter_streams(self, stream_name: str) -> bool:
206
208
return False
207
209
return True
208
210
209
- def get_validated_streams (self , config : Mapping [str , Any ], catalog : ConfiguredAirbyteCatalog = None ):
210
- salesforce_objects = self .describe ()["sobjects" ]
211
- stream_objects = []
212
- for stream_object in salesforce_objects :
211
+ def get_validated_streams (self , config : Mapping [str , Any ], catalog : ConfiguredAirbyteCatalog = None ) -> Mapping [str , Any ]:
212
+ """Selects all validated streams with additional filtering:
213
+ 1) skip all sobjects with negative value of the flag "queryable"
214
+ 2) user can set search criterias of necessary streams
215
+ 3) selection by catalog settings
216
+ """
217
+ stream_objects = {}
218
+ for stream_object in self .describe ()["sobjects" ]:
213
219
if stream_object ["queryable" ]:
214
- stream_objects . append ( stream_object )
220
+ stream_objects [ stream_object . pop ( "name" )] = stream_object
215
221
else :
216
222
self .logger .warn (f"Stream { stream_object ['name' ]} is not queryable and will be ignored." )
217
223
218
- stream_names = [stream_object ["name" ] for stream_object in stream_objects ]
219
224
if catalog :
220
- return [configured_stream .stream .name for configured_stream in catalog .streams ], stream_objects
225
+ return {
226
+ configured_stream .stream .name : stream_objects [configured_stream .stream .name ]
227
+ for configured_stream in catalog .streams
228
+ if configured_stream .stream .name in stream_objects
229
+ }
221
230
231
+ stream_names = list (stream_objects .keys ())
222
232
if config .get ("streams_criteria" ):
223
233
filtered_stream_list = []
224
234
for stream_criteria in config ["streams_criteria" ]:
225
- filtered_stream_list += filter_streams (
235
+ filtered_stream_list += filter_streams_by_criteria (
226
236
streams_list = stream_names , search_word = stream_criteria ["value" ], search_criteria = stream_criteria ["criteria" ]
227
237
)
228
238
stream_names = list (set (filtered_stream_list ))
229
239
230
240
validated_streams = [stream_name for stream_name in stream_names if self .filter_streams (stream_name )]
231
- validated_stream_objects = [stream_object for stream_object in stream_objects if stream_object ["name" ] in validated_streams ]
232
- return validated_streams , validated_stream_objects
241
+ return {stream_name : sobject_options for stream_name , sobject_options in stream_objects .items () if stream_name in validated_streams }
233
242
234
243
@default_backoff_handler (max_tries = 5 , factor = 15 )
235
244
def _make_request (
@@ -261,20 +270,20 @@ def login(self):
261
270
self .access_token = auth ["access_token" ]
262
271
self .instance_url = auth ["instance_url" ]
263
272
264
- def describe (self , sobject : str = None , stream_objects : List = None ) -> Mapping [str , Any ]:
273
+ def describe (self , sobject : str = None , sobject_options : Mapping [ str , Any ] = None ) -> Mapping [str , Any ]:
265
274
"""Describes all objects or a specific object"""
266
275
headers = self ._get_standard_headers ()
267
276
268
277
endpoint = "sobjects" if not sobject else f"sobjects/{ sobject } /describe"
269
278
270
279
url = f"{ self .instance_url } /services/data/{ self .version } /{ endpoint } "
271
280
resp = self ._make_request ("GET" , url , headers = headers )
272
- if resp .status_code == 404 :
273
- self .logger .error (f"Filtered stream objects : { stream_objects } " )
281
+ if resp .status_code == 404 and sobject :
282
+ self .logger .error (f"not found a description for the sobject ' { sobject } '. Sobject options : { sobject_options } " )
274
283
return resp .json ()
275
284
276
- def generate_schema (self , stream_name : str = None , stream_objects : List = None ) -> Mapping [str , Any ]:
277
- response = self .describe (stream_name , stream_objects )
285
+ def generate_schema (self , stream_name : str = None , stream_options : Mapping [ str , Any ] = None ) -> Mapping [str , Any ]:
286
+ response = self .describe (stream_name , stream_options )
278
287
schema = {"$schema" : "http://json-schema.org/draft-07/schema#" , "type" : "object" , "additionalProperties" : True , "properties" : {}}
279
288
for field in response ["fields" ]:
280
289
schema ["properties" ][field ["name" ]] = self .field_to_property_schema (field )
0 commit comments