@@ -2795,6 +2795,176 @@ def test_delete_table_w_not_found_ok_true(self):
27952795
27962796 conn .api_request .assert_called_with (method = "DELETE" , path = path , timeout = None )
27972797
2798+ def _create_job_helper (self , job_config , client_method ):
2799+ creds = _make_credentials ()
2800+ http = object ()
2801+ client = self ._make_one (project = self .PROJECT , credentials = creds , _http = http )
2802+
2803+ client ._connection = make_connection ()
2804+ rf1 = mock .Mock ()
2805+ get_config_patch = mock .patch (
2806+ "google.cloud.bigquery.job._JobConfig.from_api_repr" , return_value = rf1 ,
2807+ )
2808+ load_patch = mock .patch (client_method , autospec = True )
2809+
2810+ with load_patch as client_method , get_config_patch :
2811+ client .create_job (job_config = job_config )
2812+ client_method .assert_called_once ()
2813+
2814+ def test_create_job_load_config (self ):
2815+ configuration = {
2816+ "load" : {
2817+ "destinationTable" : {
2818+ "projectId" : self .PROJECT ,
2819+ "datasetId" : self .DS_ID ,
2820+ "tableId" : "source_table" ,
2821+ },
2822+ "sourceUris" : ["gs://test_bucket/src_object*" ],
2823+ }
2824+ }
2825+
2826+ self ._create_job_helper (
2827+ configuration , "google.cloud.bigquery.client.Client.load_table_from_uri"
2828+ )
2829+
2830+ def test_create_job_copy_config (self ):
2831+ configuration = {
2832+ "copy" : {
2833+ "sourceTables" : [
2834+ {
2835+ "projectId" : self .PROJECT ,
2836+ "datasetId" : self .DS_ID ,
2837+ "tableId" : "source_table" ,
2838+ }
2839+ ],
2840+ "destinationTable" : {
2841+ "projectId" : self .PROJECT ,
2842+ "datasetId" : self .DS_ID ,
2843+ "tableId" : "destination_table" ,
2844+ },
2845+ }
2846+ }
2847+
2848+ self ._create_job_helper (
2849+ configuration , "google.cloud.bigquery.client.Client.copy_table" ,
2850+ )
2851+
2852+ def test_create_job_copy_config_w_single_source (self ):
2853+ configuration = {
2854+ "copy" : {
2855+ "sourceTable" : {
2856+ "projectId" : self .PROJECT ,
2857+ "datasetId" : self .DS_ID ,
2858+ "tableId" : "source_table" ,
2859+ },
2860+ "destinationTable" : {
2861+ "projectId" : self .PROJECT ,
2862+ "datasetId" : self .DS_ID ,
2863+ "tableId" : "destination_table" ,
2864+ },
2865+ }
2866+ }
2867+
2868+ self ._create_job_helper (
2869+ configuration , "google.cloud.bigquery.client.Client.copy_table" ,
2870+ )
2871+
2872+ def test_create_job_extract_config (self ):
2873+ configuration = {
2874+ "extract" : {
2875+ "sourceTable" : {
2876+ "projectId" : self .PROJECT ,
2877+ "datasetId" : self .DS_ID ,
2878+ "tableId" : "source_table" ,
2879+ },
2880+ "destinationUris" : ["gs://test_bucket/dst_object*" ],
2881+ }
2882+ }
2883+ self ._create_job_helper (
2884+ configuration , "google.cloud.bigquery.client.Client.extract_table" ,
2885+ )
2886+
2887+ def test_create_job_query_config (self ):
2888+ configuration = {
2889+ "query" : {"query" : "query" , "destinationTable" : {"tableId" : "table_id" }}
2890+ }
2891+ self ._create_job_helper (
2892+ configuration , "google.cloud.bigquery.client.Client.query" ,
2893+ )
2894+
2895+ def test_create_job_query_config_w_rateLimitExceeded_error (self ):
2896+ from google .cloud .exceptions import Forbidden
2897+ from google .cloud .bigquery .retry import DEFAULT_RETRY
2898+
2899+ query = "select count(*) from persons"
2900+ configuration = {
2901+ "query" : {
2902+ "query" : query ,
2903+ "useLegacySql" : False ,
2904+ "destinationTable" : {"tableId" : "table_id" },
2905+ }
2906+ }
2907+ resource = {
2908+ "jobReference" : {"projectId" : self .PROJECT , "jobId" : mock .ANY },
2909+ "configuration" : {
2910+ "query" : {
2911+ "query" : query ,
2912+ "useLegacySql" : False ,
2913+ "destinationTable" : {
2914+ "projectId" : self .PROJECT ,
2915+ "datasetId" : self .DS_ID ,
2916+ "tableId" : "query_destination_table" ,
2917+ },
2918+ }
2919+ },
2920+ }
2921+ data_without_destination = {
2922+ "jobReference" : {"projectId" : self .PROJECT , "jobId" : mock .ANY },
2923+ "configuration" : {"query" : {"query" : query , "useLegacySql" : False }},
2924+ }
2925+
2926+ creds = _make_credentials ()
2927+ http = object ()
2928+ retry = DEFAULT_RETRY .with_deadline (1 ).with_predicate (
2929+ lambda exc : isinstance (exc , Forbidden )
2930+ )
2931+ client = self ._make_one (project = self .PROJECT , credentials = creds , _http = http )
2932+
2933+ api_request_patcher = mock .patch .object (
2934+ client ._connection ,
2935+ "api_request" ,
2936+ side_effect = [
2937+ Forbidden ("" , errors = [{"reason" : "rateLimitExceeded" }]),
2938+ resource ,
2939+ ],
2940+ )
2941+
2942+ with api_request_patcher as fake_api_request :
2943+ job = client .create_job (job_config = configuration , retry = retry )
2944+
2945+ self .assertEqual (job .destination .table_id , "query_destination_table" )
2946+ self .assertEqual (len (fake_api_request .call_args_list ), 2 ) # was retried once
2947+ self .assertEqual (
2948+ fake_api_request .call_args_list [1 ],
2949+ mock .call (
2950+ method = "POST" ,
2951+ path = "/projects/PROJECT/jobs" ,
2952+ data = data_without_destination ,
2953+ timeout = None ,
2954+ ),
2955+ )
2956+
2957+ def test_create_job_w_invalid_job_config (self ):
2958+ configuration = {"unknown" : {}}
2959+ creds = _make_credentials ()
2960+ http = object ()
2961+ client = self ._make_one (project = self .PROJECT , credentials = creds , _http = http )
2962+
2963+ with self .assertRaises (TypeError ) as exc :
2964+ client .create_job (job_config = configuration )
2965+
2966+ self .assertIn ("Invalid job configuration" , exc .exception .args [0 ])
2967+
27982968 def test_job_from_resource_unknown_type (self ):
27992969 from google .cloud .bigquery .job import UnknownJob
28002970
0 commit comments