You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by GitBox <gi...@apache.org> on 2019/01/12 09:07:47 UTC

[GitHub] feng-tao closed pull request #4484: [AIRFLOW-3675] Use googlapiclient for google apis

feng-tao closed pull request #4484: [AIRFLOW-3675] Use googlapiclient for google apis
URL: https://github.com/apache/airflow/pull/4484
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/airflow/contrib/hooks/bigquery_hook.py b/airflow/contrib/hooks/bigquery_hook.py
index 6dabd3ea4a..fabcc80c25 100644
--- a/airflow/contrib/hooks/bigquery_hook.py
+++ b/airflow/contrib/hooks/bigquery_hook.py
@@ -34,8 +34,8 @@
 from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
 from airflow.hooks.dbapi_hook import DbApiHook
 from airflow.utils.log.logging_mixin import LoggingMixin
-from apiclient.discovery import HttpError, build
-from googleapiclient import errors
+from googleapiclient.discovery import build
+from googleapiclient.errors import HttpError
 from pandas_gbq.gbq import \
     _check_google_client_version as gbq_check_google_client_version
 from pandas_gbq import read_gbq
@@ -136,7 +136,7 @@ def table_exists(self, project_id, dataset_id, table_id):
                 projectId=project_id, datasetId=dataset_id,
                 tableId=table_id).execute()
             return True
-        except errors.HttpError as e:
+        except HttpError as e:
             if e.resp['status'] == '404':
                 return False
             raise
diff --git a/airflow/contrib/hooks/datastore_hook.py b/airflow/contrib/hooks/datastore_hook.py
index c055e347d6..308809e141 100644
--- a/airflow/contrib/hooks/datastore_hook.py
+++ b/airflow/contrib/hooks/datastore_hook.py
@@ -19,7 +19,7 @@
 #
 
 import time
-from apiclient.discovery import build
+from googleapiclient.discovery import build
 from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
 
 
diff --git a/airflow/contrib/hooks/gcp_api_base_hook.py b/airflow/contrib/hooks/gcp_api_base_hook.py
index 696f00da6a..26768b0fde 100644
--- a/airflow/contrib/hooks/gcp_api_base_hook.py
+++ b/airflow/contrib/hooks/gcp_api_base_hook.py
@@ -37,22 +37,24 @@ class GoogleCloudBaseHook(BaseHook, LoggingMixin):
     A base hook for Google cloud-related hooks. Google cloud has a shared REST
     API client that is built in the same way no matter which service you use.
     This class helps construct and authorize the credentials needed to then
-    call apiclient.discovery.build() to actually discover and build a client
+    call googleapiclient.discovery.build() to actually discover and build a client
     for a Google cloud service.
 
     The class also contains some miscellaneous helper functions.
 
     All hook derived from this base hook use the 'Google Cloud Platform' connection
-    type. Two ways of authentication are supported:
+    type. Three ways of authentication are supported:
 
     Default credentials: Only the 'Project Id' is required. You'll need to
     have set up default credentials, such as by the
     ``GOOGLE_APPLICATION_DEFAULT`` environment variable or from the metadata
     server on Google Compute Engine.
 
-    JSON key file: Specify 'Project Id', 'Key Path' and 'Scope'.
+    JSON key file: Specify 'Project Id', 'Keyfile Path' and 'Scope'.
 
     Legacy P12 key files are not supported.
+
+    JSON data provided in the UI: Specify 'Keyfile JSON'.
     """
 
     def __init__(self, gcp_conn_id='google_cloud_default', delegate_to=None):
diff --git a/airflow/contrib/hooks/gcp_dataflow_hook.py b/airflow/contrib/hooks/gcp_dataflow_hook.py
index 9f3833b4f3..11b96e5228 100644
--- a/airflow/contrib/hooks/gcp_dataflow_hook.py
+++ b/airflow/contrib/hooks/gcp_dataflow_hook.py
@@ -23,7 +23,7 @@
 import time
 import uuid
 
-from apiclient.discovery import build
+from googleapiclient.discovery import build
 
 from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
 from airflow.utils.log.logging_mixin import LoggingMixin
diff --git a/airflow/contrib/hooks/gcp_dataproc_hook.py b/airflow/contrib/hooks/gcp_dataproc_hook.py
index e068d65cbe..7ac5cd8c88 100644
--- a/airflow/contrib/hooks/gcp_dataproc_hook.py
+++ b/airflow/contrib/hooks/gcp_dataproc_hook.py
@@ -20,7 +20,7 @@
 import time
 import uuid
 
-from apiclient.discovery import build
+from googleapiclient.discovery import build
 from zope.deprecation import deprecation
 
 from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
diff --git a/airflow/contrib/hooks/gcp_kms_hook.py b/airflow/contrib/hooks/gcp_kms_hook.py
index 6f2b3aedff..138cc173ed 100644
--- a/airflow/contrib/hooks/gcp_kms_hook.py
+++ b/airflow/contrib/hooks/gcp_kms_hook.py
@@ -22,7 +22,7 @@
 
 from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
 
-from apiclient.discovery import build
+from googleapiclient.discovery import build
 
 
 def _b64encode(s):
@@ -48,7 +48,7 @@ def get_conn(self):
         """
         Returns a KMS service object.
 
-        :rtype: apiclient.discovery.Resource
+        :rtype: googleapiclient.discovery.Resource
         """
         http_authorized = self._authorize()
         return build(
diff --git a/airflow/contrib/hooks/gcp_mlengine_hook.py b/airflow/contrib/hooks/gcp_mlengine_hook.py
index 9c255dbe80..026bfe4c35 100644
--- a/airflow/contrib/hooks/gcp_mlengine_hook.py
+++ b/airflow/contrib/hooks/gcp_mlengine_hook.py
@@ -15,8 +15,8 @@
 # limitations under the License.
 import random
 import time
-from apiclient import errors
-from apiclient.discovery import build
+from googleapiclient.errors import HttpError
+from googleapiclient.discovery import build
 
 from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
 from airflow.utils.log.logging_mixin import LoggingMixin
@@ -37,7 +37,7 @@ def _poll_with_exponential_delay(request, max_n, is_done_func, is_error_func):
                 return response
             else:
                 time.sleep((2**i) + (random.randint(0, 1000) / 1000))
-        except errors.HttpError as e:
+        except HttpError as e:
             if e.resp.status != 429:
                 log.info('Something went wrong. Not retrying: %s', format(e))
                 raise
@@ -96,7 +96,7 @@ def create_job(self, project_id, job, use_existing_job_fn=None):
 
         try:
             request.execute()
-        except errors.HttpError as e:
+        except HttpError as e:
             # 409 means there is an existing job with the same job ID.
             if e.resp.status == 409:
                 if use_existing_job_fn is not None:
@@ -126,14 +126,14 @@ def _get_job(self, project_id, job_id):
         :rtype: dict
 
         Raises:
-            apiclient.errors.HttpError: if HTTP error is returned from server
+            googleapiclient.errors.HttpError: if HTTP error is returned from server
         """
         job_name = 'projects/{}/jobs/{}'.format(project_id, job_id)
         request = self._mlengine.projects().jobs().get(name=job_name)
         while True:
             try:
                 return request.execute()
-            except errors.HttpError as e:
+            except HttpError as e:
                 if e.resp.status == 429:
                     # polling after 30 seconds when quota failure occurs
                     time.sleep(30)
@@ -149,7 +149,7 @@ def _wait_for_job_done(self, project_id, job_id, interval=30):
         a terminal state.
 
         Raises:
-            apiclient.errors.HttpError: if HTTP error is returned when getting
+            googleapiclient.errors.HttpError: if HTTP error is returned when getting
             the job
         """
         if interval <= 0:
@@ -193,7 +193,7 @@ def set_default_version(self, project_id, model_name, version_name):
             response = request.execute()
             self.log.info('Successfully set version: %s to default', response)
             return response
-        except errors.HttpError as e:
+        except HttpError as e:
             self.log.error('Something went wrong: %s', e)
             raise
 
@@ -264,7 +264,7 @@ def get_model(self, project_id, model_name):
         request = self._mlengine.projects().models().get(name=full_model_name)
         try:
             return request.execute()
-        except errors.HttpError as e:
+        except HttpError as e:
             if e.resp.status == 404:
                 self.log.error('Model was not found: %s', e)
                 return None
diff --git a/airflow/contrib/hooks/gcp_pubsub_hook.py b/airflow/contrib/hooks/gcp_pubsub_hook.py
index bf33a9b6bc..33d00bdf54 100644
--- a/airflow/contrib/hooks/gcp_pubsub_hook.py
+++ b/airflow/contrib/hooks/gcp_pubsub_hook.py
@@ -19,8 +19,8 @@
 
 from uuid import uuid4
 
-from apiclient.discovery import build
-from apiclient import errors
+from googleapiclient.discovery import build
+from googleapiclient.errors import HttpError
 
 from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
 
@@ -50,7 +50,7 @@ def __init__(self, gcp_conn_id='google_cloud_default', delegate_to=None):
     def get_conn(self):
         """Returns a Pub/Sub service object.
 
-        :rtype: apiclient.discovery.Resource
+        :rtype: googleapiclient.discovery.Resource
         """
         http_authorized = self._authorize()
         return build(
@@ -75,7 +75,7 @@ def publish(self, project, topic, messages):
             topic=full_topic, body=body)
         try:
             request.execute()
-        except errors.HttpError as e:
+        except HttpError as e:
             raise PubSubException(
                 'Error publishing to topic {}'.format(full_topic), e)
 
@@ -97,7 +97,7 @@ def create_topic(self, project, topic, fail_if_exists=False):
         try:
             service.projects().topics().create(
                 name=full_topic, body={}).execute()
-        except errors.HttpError as e:
+        except HttpError as e:
             # Status code 409 indicates that the topic already exists.
             if str(e.resp['status']) == '409':
                 message = 'Topic already exists: {}'.format(full_topic)
@@ -124,7 +124,7 @@ def delete_topic(self, project, topic, fail_if_not_exists=False):
         full_topic = _format_topic(project, topic)
         try:
             service.projects().topics().delete(topic=full_topic).execute()
-        except errors.HttpError as e:
+        except HttpError as e:
             # Status code 409 indicates that the topic was not found
             if str(e.resp['status']) == '404':
                 message = 'Topic does not exist: {}'.format(full_topic)
@@ -178,7 +178,7 @@ def create_subscription(self, topic_project, topic, subscription=None,
         try:
             service.projects().subscriptions().create(
                 name=full_subscription, body=body).execute()
-        except errors.HttpError as e:
+        except HttpError as e:
             # Status code 409 indicates that the subscription already exists.
             if str(e.resp['status']) == '409':
                 message = 'Subscription already exists: {}'.format(
@@ -210,7 +210,7 @@ def delete_subscription(self, project, subscription,
         try:
             service.projects().subscriptions().delete(
                 subscription=full_subscription).execute()
-        except errors.HttpError as e:
+        except HttpError as e:
             # Status code 404 indicates that the subscription was not found
             if str(e.resp['status']) == '404':
                 message = 'Subscription does not exist: {}'.format(
@@ -255,7 +255,7 @@ def pull(self, project, subscription, max_messages,
             response = service.projects().subscriptions().pull(
                 subscription=full_subscription, body=body).execute()
             return response.get('receivedMessages', [])
-        except errors.HttpError as e:
+        except HttpError as e:
             raise PubSubException(
                 'Error pulling messages from subscription {}'.format(
                     full_subscription), e)
@@ -279,7 +279,7 @@ def acknowledge(self, project, subscription, ack_ids):
             service.projects().subscriptions().acknowledge(
                 subscription=full_subscription, body={'ackIds': ack_ids}
             ).execute()
-        except errors.HttpError as e:
+        except HttpError as e:
             raise PubSubException(
                 'Error acknowledging {} messages pulled from subscription {}'
                 .format(len(ack_ids), full_subscription), e)
diff --git a/airflow/contrib/hooks/gcp_sql_hook.py b/airflow/contrib/hooks/gcp_sql_hook.py
index af9ad57003..1fed0576df 100644
--- a/airflow/contrib/hooks/gcp_sql_hook.py
+++ b/airflow/contrib/hooks/gcp_sql_hook.py
@@ -30,7 +30,7 @@
 import time
 import uuid
 from os.path import isfile
-from googleapiclient import errors
+from googleapiclient.errors import HttpError
 from subprocess import Popen, PIPE
 from six.moves.urllib.parse import quote_plus
 
@@ -284,7 +284,7 @@ def export_instance(self, project_id, instance_id, body):
             ).execute(num_retries=NUM_RETRIES)
             operation_name = response["name"]
             return self._wait_for_operation_to_complete(project_id, operation_name)
-        except errors.HttpError as ex:
+        except HttpError as ex:
             raise AirflowException(
                 'Exporting instance {} failed: {}'.format(instance_id, ex.content)
             )
@@ -313,7 +313,7 @@ def import_instance(self, project_id, instance_id, body):
             ).execute(num_retries=NUM_RETRIES)
             operation_name = response["name"]
             return self._wait_for_operation_to_complete(project_id, operation_name)
-        except errors.HttpError as ex:
+        except HttpError as ex:
             raise AirflowException(
                 'Importing instance {} failed: {}'.format(instance_id, ex.content)
             )
diff --git a/airflow/contrib/hooks/gcs_hook.py b/airflow/contrib/hooks/gcs_hook.py
index 6499ea38b5..d43c2a19fd 100644
--- a/airflow/contrib/hooks/gcs_hook.py
+++ b/airflow/contrib/hooks/gcs_hook.py
@@ -17,9 +17,9 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-from apiclient.discovery import build
-from apiclient.http import MediaFileUpload
-from googleapiclient import errors
+from googleapiclient.discovery import build
+from googleapiclient.http import MediaFileUpload
+from googleapiclient.errors import HttpError
 
 from airflow.contrib.hooks.gcp_api_base_hook import GoogleCloudBaseHook
 from airflow.exceptions import AirflowException
@@ -91,7 +91,7 @@ def copy(self, source_bucket, source_object, destination_bucket=None,
                       destinationObject=destination_object, body='') \
                 .execute()
             return True
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] == '404':
                 return False
             raise
@@ -144,7 +144,7 @@ def rewrite(self, source_bucket, source_object, destination_bucket,
                     .execute()
                 self.log.info('Rewrite request #%s: %s', request_count, result)
             return True
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] == '404':
                 return False
             raise
@@ -239,7 +239,7 @@ def upload(self, bucket, object, filename,
                     .insert(bucket=bucket, name=object, media_body=media) \
                     .execute(num_retries=num_retries)
 
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] == '404':
                 return False
             raise
@@ -268,7 +268,7 @@ def exists(self, bucket, object):
                 .get(bucket=bucket, object=object) \
                 .execute()
             return True
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] == '404':
                 return False
             raise
@@ -306,7 +306,7 @@ def is_updated_after(self, bucket, object, ts):
                 if updated > ts:
                     return True
 
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] != '404':
                 raise
 
@@ -333,7 +333,7 @@ def delete(self, bucket, object, generation=None):
                 .delete(bucket=bucket, object=object, generation=generation) \
                 .execute()
             return True
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] == '404':
                 return False
             raise
@@ -418,7 +418,7 @@ def get_size(self, bucket, object):
                 return size
             else:
                 raise ValueError('Object is not a file')
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] == '404':
                 raise ValueError('Object Not Found')
 
@@ -445,7 +445,7 @@ def get_crc32c(self, bucket, object):
             self.log.info('The crc32c checksum of %s is %s', object, crc32c)
             return crc32c
 
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] == '404':
                 raise ValueError('Object Not Found')
 
@@ -472,7 +472,7 @@ def get_md5hash(self, bucket, object):
             self.log.info('The md5Hash of %s is %s', object, md5hash)
             return md5hash
 
-        except errors.HttpError as ex:
+        except HttpError as ex:
             if ex.resp['status'] == '404':
                 raise ValueError('Object Not Found')
 
@@ -563,7 +563,7 @@ def create_bucket(self,
 
             return response['id']
 
-        except errors.HttpError as ex:
+        except HttpError as ex:
             raise AirflowException(
                 'Bucket creation failed. Error was: {}'.format(ex.content)
             )
@@ -601,7 +601,7 @@ def insert_bucket_acl(self, bucket, entity, role, user_project):
             ).execute()
             if response:
                 self.log.info('A new ACL entry created in bucket: %s', bucket)
-        except errors.HttpError as ex:
+        except HttpError as ex:
             raise AirflowException(
                 'Bucket ACL entry creation failed. Error was: {}'.format(ex.content)
             )
@@ -651,7 +651,7 @@ def insert_object_acl(self, bucket, object_name, entity, role, generation,
             if response:
                 self.log.info('A new ACL entry created for object: %s in bucket: %s',
                               object_name, bucket)
-        except errors.HttpError as ex:
+        except HttpError as ex:
             raise AirflowException(
                 'Object ACL entry creation failed. Error was: {}'.format(ex.content)
             )
diff --git a/airflow/contrib/operators/mlengine_operator.py b/airflow/contrib/operators/mlengine_operator.py
index 101c99d41b..22cabbf607 100644
--- a/airflow/contrib/operators/mlengine_operator.py
+++ b/airflow/contrib/operators/mlengine_operator.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 import re
 
-from apiclient import errors
+from googleapiclient.errors import HttpError
 
 from airflow.contrib.hooks.gcp_mlengine_hook import MLEngineHook
 from airflow.exceptions import AirflowException
@@ -264,7 +264,7 @@ def check_existing_job(existing_job):
         try:
             finished_prediction_job = hook.create_job(
                 self._project_id, prediction_request, check_existing_job)
-        except errors.HttpError:
+        except HttpError:
             raise
 
         if finished_prediction_job['state'] != 'SUCCEEDED':
@@ -614,7 +614,7 @@ def check_existing_job(existing_job):
         try:
             finished_training_job = hook.create_job(
                 self._project_id, training_request, check_existing_job)
-        except errors.HttpError:
+        except HttpError:
             raise
 
         if finished_training_job['state'] != 'SUCCEEDED':
diff --git a/docs/conf.py b/docs/conf.py
index 7c17f97bf9..577b86da70 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -36,9 +36,10 @@
 import mock
 
 MOCK_MODULES = [
-    'apiclient',
-    'apiclient.discovery',
-    'apiclient.http',
+    'googleapiclient',
+    'googleapiclient.errors',
+    'googleapiclient.discovery',
+    'googleapiclient.http',
     'mesos',
     'mesos.interface',
     'mesos.native',
diff --git a/tests/contrib/hooks/test_bigquery_hook.py b/tests/contrib/hooks/test_bigquery_hook.py
index 244574e5e3..f3a4f346b8 100644
--- a/tests/contrib/hooks/test_bigquery_hook.py
+++ b/tests/contrib/hooks/test_bigquery_hook.py
@@ -22,7 +22,7 @@
 
 from google.auth.exceptions import GoogleAuthError
 import mock
-from apiclient.errors import HttpError
+from googleapiclient.errors import HttpError
 
 from airflow.contrib.hooks import bigquery_hook as hook
 from airflow.contrib.hooks.bigquery_hook import _cleanse_time_partitioning, \
diff --git a/tests/contrib/hooks/test_gcp_mlengine_hook.py b/tests/contrib/hooks/test_gcp_mlengine_hook.py
index f986354503..7313d8dc9b 100644
--- a/tests/contrib/hooks/test_gcp_mlengine_hook.py
+++ b/tests/contrib/hooks/test_gcp_mlengine_hook.py
@@ -25,9 +25,9 @@
     from urllib.parse import urlparse, parse_qsl
 
 from airflow.contrib.hooks import gcp_mlengine_hook as hook
-from apiclient import errors
-from apiclient.discovery import build_from_document
-from apiclient.http import HttpMockSequence
+from googleapiclient.errors import HttpError
+from googleapiclient.discovery import build_from_document
+from googleapiclient.http import HttpMockSequence
 from google.auth.exceptions import GoogleAuthError
 import requests
 
@@ -392,7 +392,7 @@ def check_input(existing_job):
                 self,
                 responses=responses,
                 expected_requests=expected_requests) as cml_hook:
-            with self.assertRaises(errors.HttpError):
+            with self.assertRaises(HttpError):
                 cml_hook.create_job(
                     project_id=project, job=my_job,
                     use_existing_job_fn=check_input)
diff --git a/tests/contrib/hooks/test_gcp_pubsub_hook.py b/tests/contrib/hooks/test_gcp_pubsub_hook.py
index b1290fb332..3cd6e2a89b 100644
--- a/tests/contrib/hooks/test_gcp_pubsub_hook.py
+++ b/tests/contrib/hooks/test_gcp_pubsub_hook.py
@@ -23,7 +23,7 @@
 from base64 import b64encode as b64e
 import unittest
 
-from apiclient.errors import HttpError
+from googleapiclient.errors import HttpError
 
 from airflow.contrib.hooks.gcp_pubsub_hook import PubSubException, PubSubHook
 
diff --git a/tests/contrib/hooks/test_gcs_hook.py b/tests/contrib/hooks/test_gcs_hook.py
index eea79a376c..98ce7ab33d 100644
--- a/tests/contrib/hooks/test_gcs_hook.py
+++ b/tests/contrib/hooks/test_gcs_hook.py
@@ -23,7 +23,7 @@
 
 from airflow.contrib.hooks import gcs_hook
 from airflow.exceptions import AirflowException
-from apiclient.errors import HttpError
+from googleapiclient.errors import HttpError
 
 try:
     from unittest import mock
diff --git a/tests/contrib/operators/test_mlengine_operator.py b/tests/contrib/operators/test_mlengine_operator.py
index 9a8d56cfb2..bceeb5c225 100644
--- a/tests/contrib/operators/test_mlengine_operator.py
+++ b/tests/contrib/operators/test_mlengine_operator.py
@@ -22,7 +22,7 @@
 import unittest
 
 import httplib2
-from apiclient import errors
+from googleapiclient.errors import HttpError
 from mock import ANY, patch
 
 from airflow import DAG, configuration
@@ -85,7 +85,7 @@ def testSuccessWithModel(self):
             success_message['predictionInput'] = input_with_model
 
             hook_instance = mock_hook.return_value
-            hook_instance.get_job.side_effect = errors.HttpError(
+            hook_instance.get_job.side_effect = HttpError(
                 resp=httplib2.Response({
                     'status': 404
                 }), content=b'some bytes')
@@ -123,7 +123,7 @@ def testSuccessWithVersion(self):
             success_message['predictionInput'] = input_with_version
 
             hook_instance = mock_hook.return_value
-            hook_instance.get_job.side_effect = errors.HttpError(
+            hook_instance.get_job.side_effect = HttpError(
                 resp=httplib2.Response({
                     'status': 404
                 }), content=b'some bytes')
@@ -161,7 +161,7 @@ def testSuccessWithURI(self):
             success_message['predictionInput'] = input_with_uri
 
             hook_instance = mock_hook.return_value
-            hook_instance.get_job.side_effect = errors.HttpError(
+            hook_instance.get_job.side_effect = HttpError(
                 resp=httplib2.Response({
                     'status': 404
                 }), content=b'some bytes')
@@ -238,13 +238,13 @@ def testHttpError(self):
                 'projects/experimental/models/test_model'
 
             hook_instance = mock_hook.return_value
-            hook_instance.create_job.side_effect = errors.HttpError(
+            hook_instance.create_job.side_effect = HttpError(
                 resp=httplib2.Response({
                     'status': http_error_code
                 }),
                 content=b'Forbidden')
 
-            with self.assertRaises(errors.HttpError) as context:
+            with self.assertRaises(HttpError) as context:
                 prediction_task = MLEngineBatchPredictionOperator(
                     job_id='test_prediction',
                     project_id='test-project',
@@ -356,13 +356,13 @@ def testHttpError(self):
         with patch('airflow.contrib.operators.mlengine_operator.MLEngineHook') \
                 as mock_hook:
             hook_instance = mock_hook.return_value
-            hook_instance.create_job.side_effect = errors.HttpError(
+            hook_instance.create_job.side_effect = HttpError(
                 resp=httplib2.Response({
                     'status': http_error_code
                 }),
                 content=b'Forbidden')
 
-            with self.assertRaises(errors.HttpError) as context:
+            with self.assertRaises(HttpError) as context:
                 training_op = MLEngineTrainingOperator(
                     **self.TRAINING_DEFAULT_ARGS)
                 training_op.execute(None)


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services