Repository: PrefectHQ/prefect

Issue:
Google Imports are Tied Together
## Description
*A clear description of the bug*
I’m using the new `GCSResult` and I’m getting an import error when I don’t also specify `google-cloud-bigquery` as a dependency since they’re imports occur in the same file, I think?

```
Unexpected error: ImportError("cannot import name 'bigquery' from 'google.cloud' (unknown location)")
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/prefect/engine/runner.py", line 48, in inner
    new_state = method(self, state, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/prefect/engine/task_runner.py", line 986, in get_task_run_state
    result = self.result.write(value, filename="output", **prefect.context)
  File "/usr/local/lib/python3.7/site-packages/prefect/engine/results/gcs_result.py", line 73, in write
    self.gcs_bucket.blob(new.location).upload_from_string(binary_data)
  File "/usr/local/lib/python3.7/site-packages/prefect/engine/results/gcs_result.py", line 35, in gcs_bucket
    from prefect.utilities.gcp import get_storage_client
  File "/usr/local/lib/python3.7/site-packages/prefect/utilities/gcp.py", line 6, in <module>
    from google.cloud import bigquery, storage
ImportError: cannot import name 'bigquery' from 'google.cloud' (unknown location)
```
https://cloud.prefect.io/prefect/flow-run/6704aa4e-ba9b-40ed-a4f8-386920839a8e?logId=75b1fc01-0ee8-4061-ab8b-5481e6123a79

On a cool note, changing to `python_dependencies=["prefect[google]"]` did work 🎉 

## Expected Behavior
*What did you expect to happen instead?*
I'd like to be able to specify one import in insolation (in this case `google-cloud-storage`) 


## Reproduction
*A minimal example that exhibits the behavior.*
```
from prefect import task, Flow
from prefect.tasks.notifications.slack_task import SlackTask
from prefect.schedules import CronSchedule
from prefect.environments.storage import Docker
from prefect.engine.results import GCSResult

import pendulum
import datetime


@task(name="Get Week Message", max_retries=5, retry_delay=datetime.timedelta(seconds=5))
def get_week_message():
    prefects_birthday = pendulum.date(2018, 1, 17)
    current_week = prefects_birthday.diff(pendulum.now()).in_weeks()
    return f"Hello, Jeremiah! It is week {current_week}."


send_message = SlackTask(
    name="Slack Jeremiah",
    max_retries=5,
    retry_delay=datetime.timedelta(seconds=5),
    webhook_secret="SLACK_WEBHOOK",
)

schedule = CronSchedule(cron="50 11 * * MON", start_date=pendulum.now(tz="US/Eastern"))

storage = Docker(
    base_image="prefecthq/prefect:latest-python3.7",
    registry_url=URL,
    python_dependencies=["google-cloud-storage"],
    files={
        FILE_LOCATION: FILENAME
    },
    env_vars={"GOOGLE_APPLICATION_CREDENTIALS": FILENAME},
)

gcs_result = GCSResult(bucket="what_week_is_it_results")

with Flow(
    name="What Week is It?", schedule=schedule, storage=storage, result=gcs_result
) as flow:
    week_message = get_week_message()
    result = send_message(message=week_message)
```



## Environment
*Any additional information about your environment*


*Optionally run `prefect diagnostics` from the command line and paste the information here*
```
{
  "config_overrides": {
    "cloud": {
      "auth_token": true,
      "use_local_secrets": true
    },
    "context": {
      "secrets": false
    },
    "home_dir": true
  },
  "env_vars": [],
  "system_information": {
    "platform": "Darwin-19.4.0-x86_64-i386-64bit",
    "prefect_version": "0.11.2",
    "python_version": "3.7.7"
  }
}
```


Discussion:

Resolving patch:
diff --git a/src/prefect/utilities/gcp.py b/src/prefect/utilities/gcp.py
--- a/src/prefect/utilities/gcp.py
+++ b/src/prefect/utilities/gcp.py
@@ -3,7 +3,6 @@
 """
 import prefect
 
-from google.cloud import bigquery, storage
 from google.oauth2.service_account import Credentials
 
 
@@ -47,6 +46,8 @@ def get_storage_client(credentials: dict = None, project: str = None):
     Returns:
         - Client: an initialized and authenticated Google Client
     """
+    from google.cloud import storage
+
     return get_google_client(storage, credentials=credentials, project=project)
 
 
@@ -63,4 +64,6 @@ def get_bigquery_client(credentials: dict = None, project: str = None):
     Returns:
         - Client: an initialized and authenticated Google Client
     """
+    from google.cloud import bigquery
+
     return get_google_client(bigquery, credentials=credentials, project=project)


Test patch:
diff --git a/tests/tasks/gcp/test_gcs_upload_download.py b/tests/tasks/gcp/test_gcs_upload_download.py
--- a/tests/tasks/gcp/test_gcs_upload_download.py
+++ b/tests/tasks/gcp/test_gcs_upload_download.py
@@ -53,8 +53,7 @@ def test_bucket_name_can_be_overwritten_at_runtime(self, monkeypatch, klass):
         run_arg = "data" if isinstance(task, GCSUpload) else "blob"
 
         client = MagicMock()
-        monkeypatch.setattr("prefect.utilities.gcp.Credentials", MagicMock())
-        monkeypatch.setattr("prefect.utilities.gcp.storage", MagicMock(Client=client))
+        monkeypatch.setattr("prefect.tasks.gcp.storage.get_storage_client", client)
 
         task.run(**{run_arg: "empty"}, credentials={})
         task.run(**{run_arg: "empty", "bucket": "run"}, credentials={})
@@ -71,8 +70,7 @@ def test_bucket_doesnt_exist_raises_by_default(self, monkeypatch, klass):
         client.return_value = MagicMock(
             get_bucket=MagicMock(side_effect=NotFound("no bucket"))
         )
-        monkeypatch.setattr("prefect.utilities.gcp.Credentials", MagicMock())
-        monkeypatch.setattr("prefect.utilities.gcp.storage", MagicMock(Client=client))
+        monkeypatch.setattr("prefect.tasks.gcp.storage.get_storage_client", client)
 
         with pytest.raises(NotFound, match="no bucket"):
             task.run(**{run_arg: "empty"}, credentials={})
@@ -84,8 +82,7 @@ def test_bucket_doesnt_exist_can_be_created_on_upload(self, monkeypatch):
         client.return_value = MagicMock(
             get_bucket=MagicMock(side_effect=NotFound("no bucket"))
         )
-        monkeypatch.setattr("prefect.utilities.gcp.Credentials", MagicMock())
-        monkeypatch.setattr("prefect.utilities.gcp.storage", MagicMock(Client=client))
+        monkeypatch.setattr("prefect.tasks.gcp.storage.get_storage_client", client)
 
         task.run(data="empty", credentials={})
         task.run(data="empty", bucket="run", credentials={})
@@ -104,8 +101,7 @@ def test_blob_name_can_be_overwritten_at_runtime_by_upload(self, monkeypatch):
         client.return_value = MagicMock(
             get_bucket=MagicMock(return_value=MagicMock(blob=blob))
         )
-        monkeypatch.setattr("prefect.utilities.gcp.Credentials", MagicMock())
-        monkeypatch.setattr("prefect.utilities.gcp.storage", MagicMock(Client=client))
+        monkeypatch.setattr("prefect.tasks.gcp.storage.get_storage_client", client)
 
         task.run(data="empty", credentials={})
         task.run(data="empty", blob="run-time", credentials={})
@@ -122,8 +118,7 @@ def test_blob_name_can_be_overwritten_at_runtime_by_download(self, monkeypatch):
         client.return_value = MagicMock(
             get_bucket=MagicMock(return_value=MagicMock(blob=blob))
         )
-        monkeypatch.setattr("prefect.utilities.gcp.Credentials", MagicMock())
-        monkeypatch.setattr("prefect.utilities.gcp.storage", MagicMock(Client=client))
+        monkeypatch.setattr("prefect.tasks.gcp.storage.get_storage_client", client)
 
         task.run(blob="run-time", credentials={})