@@ -2795,6 +2795,176 @@ def test_delete_table_w_not_found_ok_true(self):
2795
2795
2796
2796
conn .api_request .assert_called_with (method = "DELETE" , path = path , timeout = None )
2797
2797
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
+
2798
2968
def test_job_from_resource_unknown_type (self ):
2799
2969
from google .cloud .bigquery .job import UnknownJob
2800
2970
0 commit comments