@@ -334,6 +334,7 @@ def test_finish_nonempty(self):
334334 result = batch .finish ()
335335
336336 self .assertEqual (len (result ), len (batch ._requests ))
337+ self .assertEqual (len (result ), len (batch ._responses ))
337338
338339 response1 , response2 , response3 = result
339340
@@ -438,6 +439,55 @@ def test_finish_nonempty_with_status_failure(self):
438439 self ._check_subrequest_payload (chunks [0 ], "GET" , url , {})
439440 self ._check_subrequest_payload (chunks [1 ], "GET" , url , {})
440441
442+ def test_finish_no_raise_exception (self ):
443+ url = "http://api.example.com/other_api"
444+ expected_response = _make_response (
445+ content = _TWO_PART_MIME_RESPONSE_WITH_FAIL ,
446+ headers = {"content-type" : 'multipart/mixed; boundary="DEADBEEF="' },
447+ )
448+ http = _make_requests_session ([expected_response ])
449+ connection = _Connection (http = http )
450+ client = _Client (connection )
451+ batch = self ._make_one (client )
452+ batch .API_BASE_URL = "http://api.example.com"
453+ target1 = _MockObject ()
454+ target2 = _MockObject ()
455+
456+ batch ._do_request ("GET" , url , {}, None , target1 , timeout = 42 )
457+ batch ._do_request ("GET" , url , {}, None , target2 , timeout = 420 )
458+
459+ # Make sure futures are not populated.
460+ self .assertEqual (
461+ [future for future in batch ._target_objects ], [target1 , target2 ]
462+ )
463+
464+ batch .finish (raise_exception = False )
465+
466+ self .assertEqual (len (batch ._requests ), 2 )
467+ self .assertEqual (len (batch ._responses ), 2 )
468+
469+ # Make sure NotFound exception is added to responses and target2
470+ self .assertEqual (target1 ._properties , {"foo" : 1 , "bar" : 2 })
471+ self .assertEqual (target2 ._properties , {"error" : {"message" : "Not Found" }})
472+
473+ expected_url = f"{ batch .API_BASE_URL } /batch/storage/v1"
474+ http .request .assert_called_once_with (
475+ method = "POST" ,
476+ url = expected_url ,
477+ headers = mock .ANY ,
478+ data = mock .ANY ,
479+ timeout = 420 , # the last request timeout prevails
480+ )
481+
482+ _ , request_body , _ , boundary = self ._get_mutlipart_request (http )
483+
484+ chunks = self ._get_payload_chunks (boundary , request_body )
485+ self .assertEqual (len (chunks ), 2 )
486+ self ._check_subrequest_payload (chunks [0 ], "GET" , url , {})
487+ self ._check_subrequest_payload (chunks [1 ], "GET" , url , {})
488+ self .assertEqual (batch ._responses [0 ].status_code , 200 )
489+ self .assertEqual (batch ._responses [1 ].status_code , 404 )
490+
441491 def test_finish_nonempty_non_multipart_response (self ):
442492 url = "http://api.example.com/other_api"
443493 http = _make_requests_session ([_make_response ()])
@@ -497,6 +547,7 @@ def test_as_context_mgr_wo_error(self):
497547
498548 self .assertEqual (list (client ._batch_stack ), [])
499549 self .assertEqual (len (batch ._requests ), 3 )
550+ self .assertEqual (len (batch ._responses ), 3 )
500551 self .assertEqual (batch ._requests [0 ][0 ], "POST" )
501552 self .assertEqual (batch ._requests [1 ][0 ], "PATCH" )
502553 self .assertEqual (batch ._requests [2 ][0 ], "DELETE" )
@@ -505,6 +556,43 @@ def test_as_context_mgr_wo_error(self):
505556 self .assertEqual (target2 ._properties , {"foo" : 1 , "bar" : 3 })
506557 self .assertEqual (target3 ._properties , b"" )
507558
559+ def test_as_context_mgr_no_raise_exception (self ):
560+ from google .cloud .storage .client import Client
561+
562+ url = "http://api.example.com/other_api"
563+ expected_response = _make_response (
564+ content = _TWO_PART_MIME_RESPONSE_WITH_FAIL ,
565+ headers = {"content-type" : 'multipart/mixed; boundary="DEADBEEF="' },
566+ )
567+ http = _make_requests_session ([expected_response ])
568+ project = "PROJECT"
569+ credentials = _make_credentials ()
570+ client = Client (project = project , credentials = credentials )
571+ client ._http_internal = http
572+
573+ self .assertEqual (list (client ._batch_stack ), [])
574+
575+ target1 = _MockObject ()
576+ target2 = _MockObject ()
577+
578+ with self ._make_one (client , raise_exception = False ) as batch :
579+ self .assertEqual (list (client ._batch_stack ), [batch ])
580+ batch ._make_request ("GET" , url , {}, target_object = target1 )
581+ batch ._make_request ("GET" , url , {}, target_object = target2 )
582+
583+ self .assertEqual (list (client ._batch_stack ), [])
584+ self .assertEqual (len (batch ._requests ), 2 )
585+ self .assertEqual (len (batch ._responses ), 2 )
586+ self .assertEqual (batch ._requests [0 ][0 ], "GET" )
587+ self .assertEqual (batch ._requests [1 ][0 ], "GET" )
588+ self .assertEqual (batch ._target_objects , [target1 , target2 ])
589+
590+ # Make sure NotFound exception is added to responses and target2
591+ self .assertEqual (batch ._responses [0 ].status_code , 200 )
592+ self .assertEqual (batch ._responses [1 ].status_code , 404 )
593+ self .assertEqual (target1 ._properties , {"foo" : 1 , "bar" : 2 })
594+ self .assertEqual (target2 ._properties , {"error" : {"message" : "Not Found" }})
595+
508596 def test_as_context_mgr_w_error (self ):
509597 from google .cloud .storage .batch import _FutureDict
510598 from google .cloud .storage .client import Client
0 commit comments