diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..73a7e26 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,18 @@ +[run] +branch = True + +[report] +fail_under = 100 +show_missing = True +omit = + google/cloud/notebooks/__init__.py +exclude_lines = + # Re-enable the standard pragma + pragma: NO COVER + # Ignore debug-only repr + def __repr__ + # Ignore pkg_resources exceptions. + # This is added at the module level as a safeguard for if someone + # generates the code and tries to run it without pip installing. This + # makes it virtually impossible to test properly. + except pkg_resources.DistributionNotFound diff --git a/.gitignore b/.gitignore index b9daa52..b4243ce 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,10 @@ docs.metadata # Virtual environment env/ + +# Test logs coverage.xml -sponge_log.xml +*sponge_log.xml # System test environment variables. system_tests/local_test_setup diff --git a/.kokoro/build.sh b/.kokoro/build.sh index 6c4a64d..ab9b6e2 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -40,6 +40,16 @@ python3 -m pip uninstall --yes --quiet nox-automation python3 -m pip install --upgrade --quiet nox python3 -m nox --version +# If this is a continuous build, send the test log to the FlakyBot. +# See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. +if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then + cleanup() { + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + } + trap cleanup EXIT HUP +fi + # If NOX_SESSION is set, it only runs the specified session, # otherwise run all the sessions. if [[ -n "${NOX_SESSION:-}" ]]; then diff --git a/.kokoro/samples/python3.6/periodic-head.cfg b/.kokoro/samples/python3.6/periodic-head.cfg new file mode 100644 index 0000000..f9cfcd3 --- /dev/null +++ b/.kokoro/samples/python3.6/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.7/periodic-head.cfg b/.kokoro/samples/python3.7/periodic-head.cfg new file mode 100644 index 0000000..f9cfcd3 --- /dev/null +++ b/.kokoro/samples/python3.7/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.8/periodic-head.cfg b/.kokoro/samples/python3.8/periodic-head.cfg new file mode 100644 index 0000000..f9cfcd3 --- /dev/null +++ b/.kokoro/samples/python3.8/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/test-samples-against-head.sh b/.kokoro/test-samples-against-head.sh new file mode 100755 index 0000000..f5e0618 --- /dev/null +++ b/.kokoro/test-samples-against-head.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# A customized test runner for samples. +# +# For periodic builds, you can specify this file for testing against head. + +# `-e` enables the script to automatically fail when a command fails +# `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero +set -eo pipefail +# Enables `**` to include files nested inside sub-folders +shopt -s globstar + +cd github/python-notebooks + +exec .kokoro/test-samples-impl.sh diff --git a/.kokoro/test-samples-impl.sh b/.kokoro/test-samples-impl.sh new file mode 100755 index 0000000..cf5de74 --- /dev/null +++ b/.kokoro/test-samples-impl.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# `-e` enables the script to automatically fail when a command fails +# `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero +set -eo pipefail +# Enables `**` to include files nested inside sub-folders +shopt -s globstar + +# Exit early if samples directory doesn't exist +if [ ! -d "./samples" ]; then + echo "No tests run. `./samples` not found" + exit 0 +fi + +# Disable buffering, so that the logs stream through. +export PYTHONUNBUFFERED=1 + +# Debug: show build environment +env | grep KOKORO + +# Install nox +python3.6 -m pip install --upgrade --quiet nox + +# Use secrets acessor service account to get secrets +if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then + gcloud auth activate-service-account \ + --key-file="${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" \ + --project="cloud-devrel-kokoro-resources" +fi + +# This script will create 3 files: +# - testing/test-env.sh +# - testing/service-account.json +# - testing/client-secrets.json +./scripts/decrypt-secrets.sh + +source ./testing/test-env.sh +export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/testing/service-account.json + +# For cloud-run session, we activate the service account for gcloud sdk. +gcloud auth activate-service-account \ + --key-file "${GOOGLE_APPLICATION_CREDENTIALS}" + +export GOOGLE_CLIENT_SECRETS=$(pwd)/testing/client-secrets.json + +echo -e "\n******************** TESTING PROJECTS ********************" + +# Switch to 'fail at end' to allow all tests to complete before exiting. +set +e +# Use RTN to return a non-zero value if the test fails. +RTN=0 +ROOT=$(pwd) +# Find all requirements.txt in the samples directory (may break on whitespace). +for file in samples/**/requirements.txt; do + cd "$ROOT" + # Navigate to the project folder. + file=$(dirname "$file") + cd "$file" + + echo "------------------------------------------------------------" + echo "- testing $file" + echo "------------------------------------------------------------" + + # Use nox to execute the tests for the project. + python3.6 -m nox -s "$RUN_TESTS_SESSION" + EXIT=$? + + # If this is a periodic build, send the test log to the FlakyBot. + # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. + if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + fi + + if [[ $EXIT -ne 0 ]]; then + RTN=1 + echo -e "\n Testing failed: Nox returned a non-zero exit code. \n" + else + echo -e "\n Testing completed.\n" + fi + +done +cd "$ROOT" + +# Workaround for Kokoro permissions issue: delete secrets +rm testing/{test-env.sh,client-secrets.json,service-account.json} + +exit "$RTN" diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index f05fb0a..1273a87 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -13,6 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# The default test runner for samples. +# +# For periodic builds, we rewinds the repo to the latest release, and +# run test-samples-impl.sh. # `-e` enables the script to automatically fail when a command fails # `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero @@ -24,87 +28,19 @@ cd github/python-notebooks # Run periodic samples tests at latest release if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then + # preserving the test runner implementation. + cp .kokoro/test-samples-impl.sh "${TMPDIR}/test-samples-impl.sh" + echo "--- IMPORTANT IMPORTANT IMPORTANT ---" + echo "Now we rewind the repo back to the latest release..." LATEST_RELEASE=$(git describe --abbrev=0 --tags) git checkout $LATEST_RELEASE -fi - -# Exit early if samples directory doesn't exist -if [ ! -d "./samples" ]; then - echo "No tests run. `./samples` not found" - exit 0 -fi - -# Disable buffering, so that the logs stream through. -export PYTHONUNBUFFERED=1 - -# Debug: show build environment -env | grep KOKORO - -# Install nox -python3.6 -m pip install --upgrade --quiet nox - -# Use secrets acessor service account to get secrets -if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then - gcloud auth activate-service-account \ - --key-file="${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" \ - --project="cloud-devrel-kokoro-resources" -fi - -# This script will create 3 files: -# - testing/test-env.sh -# - testing/service-account.json -# - testing/client-secrets.json -./scripts/decrypt-secrets.sh - -source ./testing/test-env.sh -export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/testing/service-account.json - -# For cloud-run session, we activate the service account for gcloud sdk. -gcloud auth activate-service-account \ - --key-file "${GOOGLE_APPLICATION_CREDENTIALS}" - -export GOOGLE_CLIENT_SECRETS=$(pwd)/testing/client-secrets.json - -echo -e "\n******************** TESTING PROJECTS ********************" - -# Switch to 'fail at end' to allow all tests to complete before exiting. -set +e -# Use RTN to return a non-zero value if the test fails. -RTN=0 -ROOT=$(pwd) -# Find all requirements.txt in the samples directory (may break on whitespace). -for file in samples/**/requirements.txt; do - cd "$ROOT" - # Navigate to the project folder. - file=$(dirname "$file") - cd "$file" - - echo "------------------------------------------------------------" - echo "- testing $file" - echo "------------------------------------------------------------" - - # Use nox to execute the tests for the project. - python3.6 -m nox -s "$RUN_TESTS_SESSION" - EXIT=$? - - # If this is a periodic build, send the test log to the FlakyBot. - # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. - if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then - chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot - $KOKORO_GFILE_DIR/linux_amd64/flakybot + echo "The current head is: " + echo $(git rev-parse --verify HEAD) + echo "--- IMPORTANT IMPORTANT IMPORTANT ---" + # move back the test runner implementation if there's no file. + if [ ! -f .kokoro/test-samples-impl.sh ]; then + cp "${TMPDIR}/test-samples-impl.sh" .kokoro/test-samples-impl.sh fi +fi - if [[ $EXIT -ne 0 ]]; then - RTN=1 - echo -e "\n Testing failed: Nox returned a non-zero exit code. \n" - else - echo -e "\n Testing completed.\n" - fi - -done -cd "$ROOT" - -# Workaround for Kokoro permissions issue: delete secrets -rm testing/{test-env.sh,client-secrets.json,service-account.json} - -exit "$RTN" +exec .kokoro/test-samples-impl.sh diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a9024b1..32302e4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,6 +12,6 @@ repos: hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.4 + rev: 3.9.0 hooks: - id: flake8 diff --git a/docs/notebooks_v1beta1/notebook_service.rst b/docs/notebooks_v1beta1/notebook_service.rst new file mode 100644 index 0000000..6f8cc21 --- /dev/null +++ b/docs/notebooks_v1beta1/notebook_service.rst @@ -0,0 +1,11 @@ +NotebookService +--------------------------------- + +.. automodule:: google.cloud.notebooks_v1beta1.services.notebook_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.notebooks_v1beta1.services.notebook_service.pagers + :members: + :inherited-members: diff --git a/docs/notebooks_v1beta1/services.rst b/docs/notebooks_v1beta1/services.rst index a88bad5..33b3547 100644 --- a/docs/notebooks_v1beta1/services.rst +++ b/docs/notebooks_v1beta1/services.rst @@ -1,6 +1,6 @@ Services for Google Cloud Notebooks v1beta1 API =============================================== +.. toctree:: + :maxdepth: 2 -.. automodule:: google.cloud.notebooks_v1beta1.services.notebook_service - :members: - :inherited-members: + notebook_service diff --git a/docs/notebooks_v1beta1/types.rst b/docs/notebooks_v1beta1/types.rst index b981f31..7cdeaf4 100644 --- a/docs/notebooks_v1beta1/types.rst +++ b/docs/notebooks_v1beta1/types.rst @@ -3,4 +3,5 @@ Types for Google Cloud Notebooks v1beta1 API .. automodule:: google.cloud.notebooks_v1beta1.types :members: + :undoc-members: :show-inheritance: diff --git a/google/cloud/notebooks_v1beta1/services/notebook_service/async_client.py b/google/cloud/notebooks_v1beta1/services/notebook_service/async_client.py index 99fafe3..98eb73d 100644 --- a/google/cloud/notebooks_v1beta1/services/notebook_service/async_client.py +++ b/google/cloud/notebooks_v1beta1/services/notebook_service/async_client.py @@ -84,7 +84,36 @@ class NotebookServiceAsyncClient: NotebookServiceClient.parse_common_location_path ) - from_service_account_file = NotebookServiceClient.from_service_account_file + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + NotebookServiceAsyncClient: The constructed client. + """ + return NotebookServiceClient.from_service_account_info.__func__(NotebookServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + NotebookServiceAsyncClient: The constructed client. + """ + return NotebookServiceClient.from_service_account_file.__func__(NotebookServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -159,7 +188,7 @@ async def list_instances( r"""Lists instances in a given project and location. Args: - request (:class:`~.service.ListInstancesRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.ListInstancesRequest`): The request object. Request for listing notebook instances. @@ -170,7 +199,7 @@ async def list_instances( sent along with the request as metadata. Returns: - ~.pagers.ListInstancesAsyncPager: + google.cloud.notebooks_v1beta1.services.notebook_service.pagers.ListInstancesAsyncPager: Response for listing notebook instances. Iterating over this object will yield @@ -219,7 +248,7 @@ async def get_instance( r"""Gets details of a single Instance. Args: - request (:class:`~.service.GetInstanceRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.GetInstanceRequest`): The request object. Request for getting a notebook instance. @@ -230,7 +259,7 @@ async def get_instance( sent along with the request as metadata. Returns: - ~.instance.Instance: + google.cloud.notebooks_v1beta1.types.Instance: The definition of a notebook instance. @@ -271,7 +300,7 @@ async def create_instance( location. Args: - request (:class:`~.service.CreateInstanceRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.CreateInstanceRequest`): The request object. Request for creating a notebook instance. @@ -282,12 +311,12 @@ async def create_instance( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -338,7 +367,7 @@ async def register_instance( API. Args: - request (:class:`~.service.RegisterInstanceRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.RegisterInstanceRequest`): The request object. Request for registering a notebook instance. @@ -349,12 +378,12 @@ async def register_instance( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -400,7 +429,7 @@ async def set_instance_accelerator( r"""Updates the guest accelerators of a single Instance. Args: - request (:class:`~.service.SetInstanceAcceleratorRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.SetInstanceAcceleratorRequest`): The request object. Request for setting instance accelerator. @@ -411,12 +440,12 @@ async def set_instance_accelerator( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -462,7 +491,7 @@ async def set_instance_machine_type( r"""Updates the machine type of a single Instance. Args: - request (:class:`~.service.SetInstanceMachineTypeRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.SetInstanceMachineTypeRequest`): The request object. Request for setting instance machine type. @@ -473,12 +502,12 @@ async def set_instance_machine_type( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -524,7 +553,7 @@ async def set_instance_labels( r"""Updates the labels of an Instance. Args: - request (:class:`~.service.SetInstanceLabelsRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.SetInstanceLabelsRequest`): The request object. Request for setting instance labels. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -534,12 +563,12 @@ async def set_instance_labels( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -585,7 +614,7 @@ async def delete_instance( r"""Deletes a single Instance. Args: - request (:class:`~.service.DeleteInstanceRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.DeleteInstanceRequest`): The request object. Request for deleting a notebook instance. @@ -596,24 +625,22 @@ async def delete_instance( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.empty.Empty``: A generic empty message that - you can re-use to avoid defining duplicated empty - messages in your APIs. A typical example is to use it as - the request or the response type of an API method. For - instance: + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: - :: + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); - service Foo { - rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); - } + } - The JSON representation for ``Empty`` is empty JSON - object ``{}``. + The JSON representation for Empty is empty JSON + object {}. """ # Create or coerce a protobuf request object. @@ -659,7 +686,7 @@ async def start_instance( r"""Starts a notebook instance. Args: - request (:class:`~.service.StartInstanceRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.StartInstanceRequest`): The request object. Request for starting a notebook instance @@ -670,12 +697,12 @@ async def start_instance( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -721,7 +748,7 @@ async def stop_instance( r"""Stops a notebook instance. Args: - request (:class:`~.service.StopInstanceRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.StopInstanceRequest`): The request object. Request for stopping a notebook instance @@ -732,12 +759,12 @@ async def stop_instance( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -783,7 +810,7 @@ async def reset_instance( r"""Resets a notebook instance. Args: - request (:class:`~.service.ResetInstanceRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.ResetInstanceRequest`): The request object. Request for reseting a notebook instance @@ -794,12 +821,12 @@ async def reset_instance( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -849,7 +876,7 @@ async def report_instance_info( this method directly. Args: - request (:class:`~.service.ReportInstanceInfoRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.ReportInstanceInfoRequest`): The request object. Request for notebook instances to report information to Notebooks API. @@ -860,12 +887,12 @@ async def report_instance_info( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -911,7 +938,7 @@ async def is_instance_upgradeable( r"""Check if a notebook instance is upgradable. Args: - request (:class:`~.service.IsInstanceUpgradeableRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.IsInstanceUpgradeableRequest`): The request object. Request for checking if a notebook instance is upgradeable. @@ -922,7 +949,7 @@ async def is_instance_upgradeable( sent along with the request as metadata. Returns: - ~.service.IsInstanceUpgradeableResponse: + google.cloud.notebooks_v1beta1.types.IsInstanceUpgradeableResponse: Response for checking if a notebook instance is upgradeable. @@ -964,7 +991,7 @@ async def upgrade_instance( r"""Upgrades a notebook instance to the latest version. Args: - request (:class:`~.service.UpgradeInstanceRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.UpgradeInstanceRequest`): The request object. Request for upgrading a notebook instance @@ -975,12 +1002,12 @@ async def upgrade_instance( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -1028,7 +1055,7 @@ async def upgrade_instance_internal( this method directly. Args: - request (:class:`~.service.UpgradeInstanceInternalRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.UpgradeInstanceInternalRequest`): The request object. Request for upgrading a notebook instance from within the VM @@ -1039,12 +1066,12 @@ async def upgrade_instance_internal( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -1090,7 +1117,7 @@ async def list_environments( r"""Lists environments in a project. Args: - request (:class:`~.service.ListEnvironmentsRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.ListEnvironmentsRequest`): The request object. Request for listing environments. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -1100,7 +1127,7 @@ async def list_environments( sent along with the request as metadata. Returns: - ~.pagers.ListEnvironmentsAsyncPager: + google.cloud.notebooks_v1beta1.services.notebook_service.pagers.ListEnvironmentsAsyncPager: Response for listing environments. Iterating over this object will yield results and resolve additional pages @@ -1148,7 +1175,7 @@ async def get_environment( r"""Gets details of a single Environment. Args: - request (:class:`~.service.GetEnvironmentRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.GetEnvironmentRequest`): The request object. Request for getting a notebook environment. @@ -1159,7 +1186,7 @@ async def get_environment( sent along with the request as metadata. Returns: - ~.environment.Environment: + google.cloud.notebooks_v1beta1.types.Environment: Definition of a software environment that is used to start a notebook instance. @@ -1200,7 +1227,7 @@ async def create_environment( r"""Creates a new Environment. Args: - request (:class:`~.service.CreateEnvironmentRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.CreateEnvironmentRequest`): The request object. Request for creating a notebook environment. @@ -1211,13 +1238,11 @@ async def create_environment( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.environment.Environment``: Definition of a - software environment that is used to start a notebook - instance. + The result type for the operation will be :class:`google.cloud.notebooks_v1beta1.types.Environment` Definition of a software environment that is used to start a notebook + instance. """ # Create or coerce a protobuf request object. @@ -1263,7 +1288,7 @@ async def delete_environment( r"""Deletes a single Environment. Args: - request (:class:`~.service.DeleteEnvironmentRequest`): + request (:class:`google.cloud.notebooks_v1beta1.types.DeleteEnvironmentRequest`): The request object. Request for deleting a notebook environment. @@ -1274,24 +1299,22 @@ async def delete_environment( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.empty.Empty``: A generic empty message that - you can re-use to avoid defining duplicated empty - messages in your APIs. A typical example is to use it as - the request or the response type of an API method. For - instance: + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: - :: + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); - service Foo { - rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); - } + } - The JSON representation for ``Empty`` is empty JSON - object ``{}``. + The JSON representation for Empty is empty JSON + object {}. """ # Create or coerce a protobuf request object. diff --git a/google/cloud/notebooks_v1beta1/services/notebook_service/client.py b/google/cloud/notebooks_v1beta1/services/notebook_service/client.py index 059c910..97acda4 100644 --- a/google/cloud/notebooks_v1beta1/services/notebook_service/client.py +++ b/google/cloud/notebooks_v1beta1/services/notebook_service/client.py @@ -116,6 +116,22 @@ def _get_default_mtls_endpoint(api_endpoint): DEFAULT_ENDPOINT ) + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + NotebookServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials @@ -128,7 +144,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): kwargs: Additional arguments to pass to the constructor. Returns: - {@api.name}: The constructed client. + NotebookServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -248,10 +264,10 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.NotebookServiceTransport]): The + transport (Union[str, NotebookServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (client_options_lib.ClientOptions): Custom options for the + client_options (google.api_core.client_options.ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT @@ -287,21 +303,17 @@ def __init__( util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) ) - ssl_credentials = None + client_cert_source_func = None is_mtls = False if use_client_cert: if client_options.client_cert_source: - import grpc # type: ignore - - cert, key = client_options.client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) is_mtls = True + client_cert_source_func = client_options.client_cert_source else: - creds = SslCredentials() - is_mtls = creds.is_mtls - ssl_credentials = creds.ssl_credentials if is_mtls else None + is_mtls = mtls.has_default_client_cert_source() + client_cert_source_func = ( + mtls.default_client_cert_source() if is_mtls else None + ) # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -344,7 +356,7 @@ def __init__( credentials_file=client_options.credentials_file, host=api_endpoint, scopes=client_options.scopes, - ssl_channel_credentials=ssl_credentials, + client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, ) @@ -360,7 +372,7 @@ def list_instances( r"""Lists instances in a given project and location. Args: - request (:class:`~.service.ListInstancesRequest`): + request (google.cloud.notebooks_v1beta1.types.ListInstancesRequest): The request object. Request for listing notebook instances. @@ -371,7 +383,7 @@ def list_instances( sent along with the request as metadata. Returns: - ~.pagers.ListInstancesPager: + google.cloud.notebooks_v1beta1.services.notebook_service.pagers.ListInstancesPager: Response for listing notebook instances. Iterating over this object will yield @@ -421,7 +433,7 @@ def get_instance( r"""Gets details of a single Instance. Args: - request (:class:`~.service.GetInstanceRequest`): + request (google.cloud.notebooks_v1beta1.types.GetInstanceRequest): The request object. Request for getting a notebook instance. @@ -432,7 +444,7 @@ def get_instance( sent along with the request as metadata. Returns: - ~.instance.Instance: + google.cloud.notebooks_v1beta1.types.Instance: The definition of a notebook instance. @@ -474,7 +486,7 @@ def create_instance( location. Args: - request (:class:`~.service.CreateInstanceRequest`): + request (google.cloud.notebooks_v1beta1.types.CreateInstanceRequest): The request object. Request for creating a notebook instance. @@ -485,12 +497,12 @@ def create_instance( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -542,7 +554,7 @@ def register_instance( API. Args: - request (:class:`~.service.RegisterInstanceRequest`): + request (google.cloud.notebooks_v1beta1.types.RegisterInstanceRequest): The request object. Request for registering a notebook instance. @@ -553,12 +565,12 @@ def register_instance( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -605,7 +617,7 @@ def set_instance_accelerator( r"""Updates the guest accelerators of a single Instance. Args: - request (:class:`~.service.SetInstanceAcceleratorRequest`): + request (google.cloud.notebooks_v1beta1.types.SetInstanceAcceleratorRequest): The request object. Request for setting instance accelerator. @@ -616,12 +628,12 @@ def set_instance_accelerator( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -668,7 +680,7 @@ def set_instance_machine_type( r"""Updates the machine type of a single Instance. Args: - request (:class:`~.service.SetInstanceMachineTypeRequest`): + request (google.cloud.notebooks_v1beta1.types.SetInstanceMachineTypeRequest): The request object. Request for setting instance machine type. @@ -679,12 +691,12 @@ def set_instance_machine_type( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -733,7 +745,7 @@ def set_instance_labels( r"""Updates the labels of an Instance. Args: - request (:class:`~.service.SetInstanceLabelsRequest`): + request (google.cloud.notebooks_v1beta1.types.SetInstanceLabelsRequest): The request object. Request for setting instance labels. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -743,12 +755,12 @@ def set_instance_labels( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -795,7 +807,7 @@ def delete_instance( r"""Deletes a single Instance. Args: - request (:class:`~.service.DeleteInstanceRequest`): + request (google.cloud.notebooks_v1beta1.types.DeleteInstanceRequest): The request object. Request for deleting a notebook instance. @@ -806,24 +818,22 @@ def delete_instance( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.empty.Empty``: A generic empty message that - you can re-use to avoid defining duplicated empty - messages in your APIs. A typical example is to use it as - the request or the response type of an API method. For - instance: + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: - :: + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); - service Foo { - rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); - } + } - The JSON representation for ``Empty`` is empty JSON - object ``{}``. + The JSON representation for Empty is empty JSON + object {}. """ # Create or coerce a protobuf request object. @@ -870,7 +880,7 @@ def start_instance( r"""Starts a notebook instance. Args: - request (:class:`~.service.StartInstanceRequest`): + request (google.cloud.notebooks_v1beta1.types.StartInstanceRequest): The request object. Request for starting a notebook instance @@ -881,12 +891,12 @@ def start_instance( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -933,7 +943,7 @@ def stop_instance( r"""Stops a notebook instance. Args: - request (:class:`~.service.StopInstanceRequest`): + request (google.cloud.notebooks_v1beta1.types.StopInstanceRequest): The request object. Request for stopping a notebook instance @@ -944,12 +954,12 @@ def stop_instance( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -996,7 +1006,7 @@ def reset_instance( r"""Resets a notebook instance. Args: - request (:class:`~.service.ResetInstanceRequest`): + request (google.cloud.notebooks_v1beta1.types.ResetInstanceRequest): The request object. Request for reseting a notebook instance @@ -1007,12 +1017,12 @@ def reset_instance( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -1063,7 +1073,7 @@ def report_instance_info( this method directly. Args: - request (:class:`~.service.ReportInstanceInfoRequest`): + request (google.cloud.notebooks_v1beta1.types.ReportInstanceInfoRequest): The request object. Request for notebook instances to report information to Notebooks API. @@ -1074,12 +1084,12 @@ def report_instance_info( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -1126,7 +1136,7 @@ def is_instance_upgradeable( r"""Check if a notebook instance is upgradable. Args: - request (:class:`~.service.IsInstanceUpgradeableRequest`): + request (google.cloud.notebooks_v1beta1.types.IsInstanceUpgradeableRequest): The request object. Request for checking if a notebook instance is upgradeable. @@ -1137,7 +1147,7 @@ def is_instance_upgradeable( sent along with the request as metadata. Returns: - ~.service.IsInstanceUpgradeableResponse: + google.cloud.notebooks_v1beta1.types.IsInstanceUpgradeableResponse: Response for checking if a notebook instance is upgradeable. @@ -1180,7 +1190,7 @@ def upgrade_instance( r"""Upgrades a notebook instance to the latest version. Args: - request (:class:`~.service.UpgradeInstanceRequest`): + request (google.cloud.notebooks_v1beta1.types.UpgradeInstanceRequest): The request object. Request for upgrading a notebook instance @@ -1191,12 +1201,12 @@ def upgrade_instance( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -1245,7 +1255,7 @@ def upgrade_instance_internal( this method directly. Args: - request (:class:`~.service.UpgradeInstanceInternalRequest`): + request (google.cloud.notebooks_v1beta1.types.UpgradeInstanceInternalRequest): The request object. Request for upgrading a notebook instance from within the VM @@ -1256,12 +1266,12 @@ def upgrade_instance_internal( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.instance.Instance``: The definition of a - notebook instance. + :class:`google.cloud.notebooks_v1beta1.types.Instance` + The definition of a notebook instance. """ # Create or coerce a protobuf request object. @@ -1310,7 +1320,7 @@ def list_environments( r"""Lists environments in a project. Args: - request (:class:`~.service.ListEnvironmentsRequest`): + request (google.cloud.notebooks_v1beta1.types.ListEnvironmentsRequest): The request object. Request for listing environments. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -1320,7 +1330,7 @@ def list_environments( sent along with the request as metadata. Returns: - ~.pagers.ListEnvironmentsPager: + google.cloud.notebooks_v1beta1.services.notebook_service.pagers.ListEnvironmentsPager: Response for listing environments. Iterating over this object will yield results and resolve additional pages @@ -1369,7 +1379,7 @@ def get_environment( r"""Gets details of a single Environment. Args: - request (:class:`~.service.GetEnvironmentRequest`): + request (google.cloud.notebooks_v1beta1.types.GetEnvironmentRequest): The request object. Request for getting a notebook environment. @@ -1380,7 +1390,7 @@ def get_environment( sent along with the request as metadata. Returns: - ~.environment.Environment: + google.cloud.notebooks_v1beta1.types.Environment: Definition of a software environment that is used to start a notebook instance. @@ -1422,7 +1432,7 @@ def create_environment( r"""Creates a new Environment. Args: - request (:class:`~.service.CreateEnvironmentRequest`): + request (google.cloud.notebooks_v1beta1.types.CreateEnvironmentRequest): The request object. Request for creating a notebook environment. @@ -1433,13 +1443,11 @@ def create_environment( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.environment.Environment``: Definition of a - software environment that is used to start a notebook - instance. + The result type for the operation will be :class:`google.cloud.notebooks_v1beta1.types.Environment` Definition of a software environment that is used to start a notebook + instance. """ # Create or coerce a protobuf request object. @@ -1486,7 +1494,7 @@ def delete_environment( r"""Deletes a single Environment. Args: - request (:class:`~.service.DeleteEnvironmentRequest`): + request (google.cloud.notebooks_v1beta1.types.DeleteEnvironmentRequest): The request object. Request for deleting a notebook environment. @@ -1497,24 +1505,22 @@ def delete_environment( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.empty.Empty``: A generic empty message that - you can re-use to avoid defining duplicated empty - messages in your APIs. A typical example is to use it as - the request or the response type of an API method. For - instance: + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: - :: + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); - service Foo { - rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); - } + } - The JSON representation for ``Empty`` is empty JSON - object ``{}``. + The JSON representation for Empty is empty JSON + object {}. """ # Create or coerce a protobuf request object. diff --git a/google/cloud/notebooks_v1beta1/services/notebook_service/pagers.py b/google/cloud/notebooks_v1beta1/services/notebook_service/pagers.py index 15c54f6..ec305f6 100644 --- a/google/cloud/notebooks_v1beta1/services/notebook_service/pagers.py +++ b/google/cloud/notebooks_v1beta1/services/notebook_service/pagers.py @@ -15,7 +15,16 @@ # limitations under the License. # -from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) from google.cloud.notebooks_v1beta1.types import environment from google.cloud.notebooks_v1beta1.types import instance @@ -26,7 +35,7 @@ class ListInstancesPager: """A pager for iterating through ``list_instances`` requests. This class thinly wraps an initial - :class:`~.service.ListInstancesResponse` object, and + :class:`google.cloud.notebooks_v1beta1.types.ListInstancesResponse` object, and provides an ``__iter__`` method to iterate through its ``instances`` field. @@ -35,7 +44,7 @@ class ListInstancesPager: through the ``instances`` field on the corresponding responses. - All the usual :class:`~.service.ListInstancesResponse` + All the usual :class:`google.cloud.notebooks_v1beta1.types.ListInstancesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -53,9 +62,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.service.ListInstancesRequest`): + request (google.cloud.notebooks_v1beta1.types.ListInstancesRequest): The initial request object. - response (:class:`~.service.ListInstancesResponse`): + response (google.cloud.notebooks_v1beta1.types.ListInstancesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -88,7 +97,7 @@ class ListInstancesAsyncPager: """A pager for iterating through ``list_instances`` requests. This class thinly wraps an initial - :class:`~.service.ListInstancesResponse` object, and + :class:`google.cloud.notebooks_v1beta1.types.ListInstancesResponse` object, and provides an ``__aiter__`` method to iterate through its ``instances`` field. @@ -97,7 +106,7 @@ class ListInstancesAsyncPager: through the ``instances`` field on the corresponding responses. - All the usual :class:`~.service.ListInstancesResponse` + All the usual :class:`google.cloud.notebooks_v1beta1.types.ListInstancesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -115,9 +124,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.service.ListInstancesRequest`): + request (google.cloud.notebooks_v1beta1.types.ListInstancesRequest): The initial request object. - response (:class:`~.service.ListInstancesResponse`): + response (google.cloud.notebooks_v1beta1.types.ListInstancesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -154,7 +163,7 @@ class ListEnvironmentsPager: """A pager for iterating through ``list_environments`` requests. This class thinly wraps an initial - :class:`~.service.ListEnvironmentsResponse` object, and + :class:`google.cloud.notebooks_v1beta1.types.ListEnvironmentsResponse` object, and provides an ``__iter__`` method to iterate through its ``environments`` field. @@ -163,7 +172,7 @@ class ListEnvironmentsPager: through the ``environments`` field on the corresponding responses. - All the usual :class:`~.service.ListEnvironmentsResponse` + All the usual :class:`google.cloud.notebooks_v1beta1.types.ListEnvironmentsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -181,9 +190,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.service.ListEnvironmentsRequest`): + request (google.cloud.notebooks_v1beta1.types.ListEnvironmentsRequest): The initial request object. - response (:class:`~.service.ListEnvironmentsResponse`): + response (google.cloud.notebooks_v1beta1.types.ListEnvironmentsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -216,7 +225,7 @@ class ListEnvironmentsAsyncPager: """A pager for iterating through ``list_environments`` requests. This class thinly wraps an initial - :class:`~.service.ListEnvironmentsResponse` object, and + :class:`google.cloud.notebooks_v1beta1.types.ListEnvironmentsResponse` object, and provides an ``__aiter__`` method to iterate through its ``environments`` field. @@ -225,7 +234,7 @@ class ListEnvironmentsAsyncPager: through the ``environments`` field on the corresponding responses. - All the usual :class:`~.service.ListEnvironmentsResponse` + All the usual :class:`google.cloud.notebooks_v1beta1.types.ListEnvironmentsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -243,9 +252,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.service.ListEnvironmentsRequest`): + request (google.cloud.notebooks_v1beta1.types.ListEnvironmentsRequest): The initial request object. - response (:class:`~.service.ListEnvironmentsResponse`): + response (google.cloud.notebooks_v1beta1.types.ListEnvironmentsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/notebooks_v1beta1/services/notebook_service/transports/base.py b/google/cloud/notebooks_v1beta1/services/notebook_service/transports/base.py index 240525b..d72ee7b 100644 --- a/google/cloud/notebooks_v1beta1/services/notebook_service/transports/base.py +++ b/google/cloud/notebooks_v1beta1/services/notebook_service/transports/base.py @@ -71,10 +71,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -82,6 +82,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -91,20 +94,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc.py b/google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc.py index 9b30743..5aed906 100644 --- a/google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc.py +++ b/google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc.py @@ -61,6 +61,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -91,6 +92,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -105,72 +110,61 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -178,18 +172,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - self._operations_client = None - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -203,7 +187,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc_asyncio.py b/google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc_asyncio.py index a68037d..9cf81f5 100644 --- a/google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc_asyncio.py +++ b/google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc_asyncio.py @@ -65,7 +65,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -105,6 +105,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -136,12 +137,16 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -150,72 +155,61 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -223,18 +217,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} - self._operations_client = None + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/notebooks_v1beta1/types/__init__.py b/google/cloud/notebooks_v1beta1/types/__init__.py index 853a88d..6b8325a 100644 --- a/google/cloud/notebooks_v1beta1/types/__init__.py +++ b/google/cloud/notebooks_v1beta1/types/__init__.py @@ -16,63 +16,63 @@ # from .environment import ( + ContainerImage, Environment, VmImage, - ContainerImage, ) from .instance import Instance from .service import ( - OperationMetadata, + CreateEnvironmentRequest, + CreateInstanceRequest, + DeleteEnvironmentRequest, + DeleteInstanceRequest, + GetEnvironmentRequest, + GetInstanceRequest, + IsInstanceUpgradeableRequest, + IsInstanceUpgradeableResponse, + ListEnvironmentsRequest, + ListEnvironmentsResponse, ListInstancesRequest, ListInstancesResponse, - GetInstanceRequest, - CreateInstanceRequest, + OperationMetadata, RegisterInstanceRequest, + ReportInstanceInfoRequest, + ResetInstanceRequest, SetInstanceAcceleratorRequest, - SetInstanceMachineTypeRequest, SetInstanceLabelsRequest, - DeleteInstanceRequest, + SetInstanceMachineTypeRequest, StartInstanceRequest, StopInstanceRequest, - ResetInstanceRequest, - ReportInstanceInfoRequest, - IsInstanceUpgradeableRequest, - IsInstanceUpgradeableResponse, - UpgradeInstanceRequest, UpgradeInstanceInternalRequest, - ListEnvironmentsRequest, - ListEnvironmentsResponse, - GetEnvironmentRequest, - CreateEnvironmentRequest, - DeleteEnvironmentRequest, + UpgradeInstanceRequest, ) __all__ = ( + "ContainerImage", "Environment", "VmImage", - "ContainerImage", "Instance", - "OperationMetadata", + "CreateEnvironmentRequest", + "CreateInstanceRequest", + "DeleteEnvironmentRequest", + "DeleteInstanceRequest", + "GetEnvironmentRequest", + "GetInstanceRequest", + "IsInstanceUpgradeableRequest", + "IsInstanceUpgradeableResponse", + "ListEnvironmentsRequest", + "ListEnvironmentsResponse", "ListInstancesRequest", "ListInstancesResponse", - "GetInstanceRequest", - "CreateInstanceRequest", + "OperationMetadata", "RegisterInstanceRequest", + "ReportInstanceInfoRequest", + "ResetInstanceRequest", "SetInstanceAcceleratorRequest", - "SetInstanceMachineTypeRequest", "SetInstanceLabelsRequest", - "DeleteInstanceRequest", + "SetInstanceMachineTypeRequest", "StartInstanceRequest", "StopInstanceRequest", - "ResetInstanceRequest", - "ReportInstanceInfoRequest", - "IsInstanceUpgradeableRequest", - "IsInstanceUpgradeableResponse", - "UpgradeInstanceRequest", "UpgradeInstanceInternalRequest", - "ListEnvironmentsRequest", - "ListEnvironmentsResponse", - "GetEnvironmentRequest", - "CreateEnvironmentRequest", - "DeleteEnvironmentRequest", + "UpgradeInstanceRequest", ) diff --git a/google/cloud/notebooks_v1beta1/types/environment.py b/google/cloud/notebooks_v1beta1/types/environment.py index 5f13677..4e02c7e 100644 --- a/google/cloud/notebooks_v1beta1/types/environment.py +++ b/google/cloud/notebooks_v1beta1/types/environment.py @@ -39,10 +39,10 @@ class Environment(proto.Message): Display name of this environment for the UI. description (str): A brief description of this environment. - vm_image (~.environment.VmImage): + vm_image (google.cloud.notebooks_v1beta1.types.VmImage): Use a Compute Engine VM image to start the notebook instance. - container_image (~.environment.ContainerImage): + container_image (google.cloud.notebooks_v1beta1.types.ContainerImage): Use a container image to start the notebook instance. post_startup_script (str): @@ -50,7 +50,7 @@ class Environment(proto.Message): notebook instance fully boots up. The path must be a URL or Cloud Storage path. Example: ``"gs://path-to-file/file-name"`` - create_time (~.timestamp.Timestamp): + create_time (google.protobuf.timestamp_pb2.Timestamp): Output only. The time at which this environment was created. """ diff --git a/google/cloud/notebooks_v1beta1/types/instance.py b/google/cloud/notebooks_v1beta1/types/instance.py index 9a775f3..636825e 100644 --- a/google/cloud/notebooks_v1beta1/types/instance.py +++ b/google/cloud/notebooks_v1beta1/types/instance.py @@ -34,10 +34,10 @@ class Instance(proto.Message): name (str): Output only. The name of this notebook instance. Format: ``projects/{project_id}/locations/{location}/instances/{instance_id}`` - vm_image (~.environment.VmImage): + vm_image (google.cloud.notebooks_v1beta1.types.VmImage): Use a Compute Engine VM image to start the notebook instance. - container_image (~.environment.ContainerImage): + container_image (google.cloud.notebooks_v1beta1.types.ContainerImage): Use a container image to start the notebook instance. post_startup_script (str): @@ -67,12 +67,12 @@ class Instance(proto.Message): Required. The `Compute Engine machine type `__ of this instance. - accelerator_config (~.instance.Instance.AcceleratorConfig): + accelerator_config (google.cloud.notebooks_v1beta1.types.Instance.AcceleratorConfig): The hardware accelerator used on this instance. If you use accelerators, make sure that your configuration has `enough vCPUs and memory to support the ``machine_type`` you have selected `__. - state (~.instance.Instance.State): + state (google.cloud.notebooks_v1beta1.types.Instance.State): Output only. The state of this instance. install_gpu_driver (bool): Whether the end user authorizes Google Cloud @@ -84,7 +84,7 @@ class Instance(proto.Message): Specify a custom Cloud Storage path where the GPU driver is stored. If not specified, we'll automatically choose from official GPU drivers. - boot_disk_type (~.instance.Instance.DiskType): + boot_disk_type (google.cloud.notebooks_v1beta1.types.Instance.DiskType): Input only. The type of the boot disk attached to this instance, defaults to standard persistent disk (``PD_STANDARD``). @@ -94,7 +94,7 @@ class Instance(proto.Message): 64000 GB (64 TB). The minimum recommended value is 100 GB. If not specified, this defaults to 100. - data_disk_type (~.instance.Instance.DiskType): + data_disk_type (google.cloud.notebooks_v1beta1.types.Instance.DiskType): Input only. The type of the data disk attached to this instance, defaults to standard persistent disk (``PD_STANDARD``). @@ -108,7 +108,7 @@ class Instance(proto.Message): no_remove_data_disk (bool): Input only. If true, the data disk will not be auto deleted when deleting the instance. - disk_encryption (~.instance.Instance.DiskEncryption): + disk_encryption (google.cloud.notebooks_v1beta1.types.Instance.DiskEncryption): Input only. Disk encryption method used on the boot and data disks, defaults to GMEK. kms_key (str): @@ -130,15 +130,15 @@ class Instance(proto.Message): subnet (str): The name of the subnet that this instance is in. Format: ``projects/{project_id}/regions/{region}/subnetworks/{subnetwork_id}`` - labels (Sequence[~.instance.Instance.LabelsEntry]): + labels (Sequence[google.cloud.notebooks_v1beta1.types.Instance.LabelsEntry]): Labels to apply to this instance. These can be later modified by the setLabels method. - metadata (Sequence[~.instance.Instance.MetadataEntry]): + metadata (Sequence[google.cloud.notebooks_v1beta1.types.Instance.MetadataEntry]): Custom metadata to apply to this instance. - create_time (~.timestamp.Timestamp): + create_time (google.protobuf.timestamp_pb2.Timestamp): Output only. Instance creation time. - update_time (~.timestamp.Timestamp): + update_time (google.protobuf.timestamp_pb2.Timestamp): Output only. Instance update time. """ @@ -191,7 +191,7 @@ class AcceleratorConfig(proto.Message): combination. TPUs are not supported. Attributes: - type_ (~.instance.Instance.AcceleratorType): + type_ (google.cloud.notebooks_v1beta1.types.Instance.AcceleratorType): Type of this accelerator. core_count (int): Count of cores of this accelerator. diff --git a/google/cloud/notebooks_v1beta1/types/service.py b/google/cloud/notebooks_v1beta1/types/service.py index 75b9cc7..ddabeea 100644 --- a/google/cloud/notebooks_v1beta1/types/service.py +++ b/google/cloud/notebooks_v1beta1/types/service.py @@ -57,9 +57,9 @@ class OperationMetadata(proto.Message): r"""Represents the metadata of the long-running operation. Attributes: - create_time (~.timestamp.Timestamp): + create_time (google.protobuf.timestamp_pb2.Timestamp): The time the operation was created. - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): The time the operation finished running. target (str): Server-defined resource path for the target @@ -123,7 +123,7 @@ class ListInstancesResponse(proto.Message): r"""Response for listing notebook instances. Attributes: - instances (Sequence[~.gcn_instance.Instance]): + instances (Sequence[google.cloud.notebooks_v1beta1.types.Instance]): A list of returned instances. next_page_token (str): Page token that can be used to continue @@ -170,7 +170,7 @@ class CreateInstanceRequest(proto.Message): instance_id (str): Required. User-defined unique ID of this instance. - instance (~.gcn_instance.Instance): + instance (google.cloud.notebooks_v1beta1.types.Instance): Required. The instance to be created. """ @@ -208,7 +208,7 @@ class SetInstanceAcceleratorRequest(proto.Message): name (str): Required. Format: ``projects/{project_id}/locations/{location}/instances/{instance_id}`` - type_ (~.gcn_instance.Instance.AcceleratorType): + type_ (google.cloud.notebooks_v1beta1.types.Instance.AcceleratorType): Required. Type of this accelerator. core_count (int): Required. Count of cores of this accelerator. Note that not @@ -251,7 +251,7 @@ class SetInstanceLabelsRequest(proto.Message): name (str): Required. Format: ``projects/{project_id}/locations/{location}/instances/{instance_id}`` - labels (Sequence[~.service.SetInstanceLabelsRequest.LabelsEntry]): + labels (Sequence[google.cloud.notebooks_v1beta1.types.SetInstanceLabelsRequest.LabelsEntry]): Labels to apply to this instance. These can be later modified by the setLabels method @@ -323,7 +323,7 @@ class ReportInstanceInfoRequest(proto.Message): authenticating the VM. https://cloud.google.com/compute/docs/instances/verifying- instance-identity - metadata (Sequence[~.service.ReportInstanceInfoRequest.MetadataEntry]): + metadata (Sequence[google.cloud.notebooks_v1beta1.types.ReportInstanceInfoRequest.MetadataEntry]): The metadata reported to Notebooks API. This will be merged to the instance metadata store """ @@ -424,7 +424,7 @@ class ListEnvironmentsResponse(proto.Message): r"""Response for listing environments. Attributes: - environments (Sequence[~.gcn_environment.Environment]): + environments (Sequence[google.cloud.notebooks_v1beta1.types.Environment]): A list of returned environments. next_page_token (str): A page token that can be used to continue @@ -472,7 +472,7 @@ class CreateEnvironmentRequest(proto.Message): contain only lowercase letters, numeric characters, and dashes. The first character must be a lowercase letter and the last character cannot be a dash. - environment (~.gcn_environment.Environment): + environment (google.cloud.notebooks_v1beta1.types.Environment): Required. The environment to be created. """ diff --git a/noxfile.py b/noxfile.py index 70d9c13..4d37cd3 100644 --- a/noxfile.py +++ b/noxfile.py @@ -18,6 +18,7 @@ from __future__ import absolute_import import os +import pathlib import shutil import nox @@ -30,6 +31,8 @@ SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() + # 'docfx' is excluded since it only needs to run in 'docs-presubmit' nox.options.sessions = [ "unit", @@ -41,6 +44,9 @@ "docs", ] +# Error if a python version is missing +nox.options.error_on_missing_interpreters = True + @nox.session(python=DEFAULT_PYTHON_VERSION) def lint(session): @@ -81,18 +87,21 @@ def lint_setup_py(session): def default(session): # Install all test dependencies, then install this package in-place. - session.install("asyncmock", "pytest-asyncio") - session.install( - "mock", "pytest", "pytest-cov", + constraints_path = str( + CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" ) + session.install("asyncmock", "pytest-asyncio", "-c", constraints_path) - session.install("-e", ".") + session.install("mock", "pytest", "pytest-cov", "-c", constraints_path) + + session.install("-e", ".", "-c", constraints_path) # Run py.test against the unit tests. session.run( "py.test", "--quiet", + f"--junitxml=unit_{session.python}_sponge_log.xml", "--cov=google/cloud", "--cov=tests/unit", "--cov-append", @@ -113,6 +122,9 @@ def unit(session): @nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS) def system(session): """Run the system test suite.""" + constraints_path = str( + CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" + ) system_test_path = os.path.join("tests", "system.py") system_test_folder_path = os.path.join("tests", "system") @@ -122,6 +134,9 @@ def system(session): # Sanity check: Only run tests if the environment variable is set. if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): session.skip("Credentials must be set via environment variable") + # Install pyopenssl for mTLS testing. + if os.environ.get("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true": + session.install("pyopenssl") system_test_exists = os.path.exists(system_test_path) system_test_folder_exists = os.path.exists(system_test_folder_path) @@ -134,16 +149,26 @@ def system(session): # Install all test dependencies, then install this package into the # virtualenv's dist-packages. - session.install( - "mock", "pytest", "google-cloud-testutils", - ) - session.install("-e", ".") + session.install("mock", "pytest", "google-cloud-testutils", "-c", constraints_path) + session.install("-e", ".", "-c", constraints_path) # Run py.test against the system tests. if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_path, + *session.posargs, + ) if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_folder_path, + *session.posargs, + ) @nox.session(python=DEFAULT_PYTHON_VERSION) @@ -154,7 +179,7 @@ def cover(session): test runs (not system test runs), and then erases coverage data. """ session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=99") + session.run("coverage", "report", "--show-missing", "--fail-under=98") session.run("coverage", "erase") @@ -186,9 +211,7 @@ def docfx(session): """Build the docfx yaml files for this library.""" session.install("-e", ".") - # sphinx-docfx-yaml supports up to sphinx version 1.5.5. - # https://github.com/docascode/sphinx-docfx-yaml/issues/97 - session.install("sphinx==1.5.5", "alabaster", "recommonmark", "sphinx-docfx-yaml") + session.install("sphinx", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml") shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( diff --git a/renovate.json b/renovate.json index 4fa9493..f08bc22 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,6 @@ { "extends": [ "config:base", ":preserveSemverRanges" - ] + ], + "ignorePaths": [".pre-commit-config.yaml"] } diff --git a/setup.py b/setup.py index 1f140be..d36d61d 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ platforms="Posix; MacOS X; Windows", include_package_data=True, install_requires=( - "google-api-core[grpc] >= 1.22.0, < 2.0.0dev", + "google-api-core[grpc] >= 1.22.2, < 2.0.0dev", "proto-plus >= 1.1.0", ), python_requires=">=3.6", diff --git a/synth.metadata b/synth.metadata index 596ea25..1839ad1 100644 --- a/synth.metadata +++ b/synth.metadata @@ -3,30 +3,30 @@ { "git": { "name": ".", - "remote": "https://github.com/googleapis/python-notebooks.git", - "sha": "bf6d2d927132a8c49872bce622eba5b863157f3b" + "remote": "git@github.com:googleapis/python-notebooks", + "sha": "8d668f883761f7c77d6aeeb5ef5834cd097f1ceb" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "dd372aa22ded7a8ba6f0e03a80e06358a3fa0907", - "internalRef": "347055288" + "sha": "95dd24960cf9f794ef583e59ad9f1fabe1c4a924", + "internalRef": "365882072" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4679e7e415221f03ff2a71e3ffad75b9ec41d87e" + "sha": "551dd78ca04f7989abc9e63e392f8b8cfa1a0ef9" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4679e7e415221f03ff2a71e3ffad75b9ec41d87e" + "sha": "551dd78ca04f7989abc9e63e392f8b8cfa1a0ef9" } } ], @@ -40,94 +40,5 @@ "generator": "bazel" } } - ], - "generatedFiles": [ - ".flake8", - ".github/CONTRIBUTING.md", - ".github/ISSUE_TEMPLATE/bug_report.md", - ".github/ISSUE_TEMPLATE/feature_request.md", - ".github/ISSUE_TEMPLATE/support_request.md", - ".github/PULL_REQUEST_TEMPLATE.md", - ".github/header-checker-lint.yml", - ".github/release-please.yml", - ".github/snippet-bot.yml", - ".gitignore", - ".kokoro/build.sh", - ".kokoro/continuous/common.cfg", - ".kokoro/continuous/continuous.cfg", - ".kokoro/docker/docs/Dockerfile", - ".kokoro/docker/docs/fetch_gpg_keys.sh", - ".kokoro/docs/common.cfg", - ".kokoro/docs/docs-presubmit.cfg", - ".kokoro/docs/docs.cfg", - ".kokoro/populate-secrets.sh", - ".kokoro/presubmit/common.cfg", - ".kokoro/presubmit/presubmit.cfg", - ".kokoro/publish-docs.sh", - ".kokoro/release.sh", - ".kokoro/release/common.cfg", - ".kokoro/release/release.cfg", - ".kokoro/samples/lint/common.cfg", - ".kokoro/samples/lint/continuous.cfg", - ".kokoro/samples/lint/periodic.cfg", - ".kokoro/samples/lint/presubmit.cfg", - ".kokoro/samples/python3.6/common.cfg", - ".kokoro/samples/python3.6/continuous.cfg", - ".kokoro/samples/python3.6/periodic.cfg", - ".kokoro/samples/python3.6/presubmit.cfg", - ".kokoro/samples/python3.7/common.cfg", - ".kokoro/samples/python3.7/continuous.cfg", - ".kokoro/samples/python3.7/periodic.cfg", - ".kokoro/samples/python3.7/presubmit.cfg", - ".kokoro/samples/python3.8/common.cfg", - ".kokoro/samples/python3.8/continuous.cfg", - ".kokoro/samples/python3.8/periodic.cfg", - ".kokoro/samples/python3.8/presubmit.cfg", - ".kokoro/test-samples.sh", - ".kokoro/trampoline.sh", - ".kokoro/trampoline_v2.sh", - ".pre-commit-config.yaml", - ".trampolinerc", - "CODE_OF_CONDUCT.md", - "CONTRIBUTING.rst", - "LICENSE", - "MANIFEST.in", - "docs/_static/custom.css", - "docs/_templates/layout.html", - "docs/conf.py", - "docs/multiprocessing.rst", - "docs/notebooks_v1beta1/services.rst", - "docs/notebooks_v1beta1/types.rst", - "google/cloud/notebooks/__init__.py", - "google/cloud/notebooks/py.typed", - "google/cloud/notebooks_v1beta1/__init__.py", - "google/cloud/notebooks_v1beta1/py.typed", - "google/cloud/notebooks_v1beta1/services/__init__.py", - "google/cloud/notebooks_v1beta1/services/notebook_service/__init__.py", - "google/cloud/notebooks_v1beta1/services/notebook_service/async_client.py", - "google/cloud/notebooks_v1beta1/services/notebook_service/client.py", - "google/cloud/notebooks_v1beta1/services/notebook_service/pagers.py", - "google/cloud/notebooks_v1beta1/services/notebook_service/transports/__init__.py", - "google/cloud/notebooks_v1beta1/services/notebook_service/transports/base.py", - "google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc.py", - "google/cloud/notebooks_v1beta1/services/notebook_service/transports/grpc_asyncio.py", - "google/cloud/notebooks_v1beta1/types/__init__.py", - "google/cloud/notebooks_v1beta1/types/environment.py", - "google/cloud/notebooks_v1beta1/types/instance.py", - "google/cloud/notebooks_v1beta1/types/service.py", - "mypy.ini", - "noxfile.py", - "renovate.json", - "scripts/decrypt-secrets.sh", - "scripts/readme-gen/readme_gen.py", - "scripts/readme-gen/templates/README.tmpl.rst", - "scripts/readme-gen/templates/auth.tmpl.rst", - "scripts/readme-gen/templates/auth_api_key.tmpl.rst", - "scripts/readme-gen/templates/install_deps.tmpl.rst", - "scripts/readme-gen/templates/install_portaudio.tmpl.rst", - "setup.cfg", - "testing/.gitignore", - "tests/unit/gapic/notebooks_v1beta1/__init__.py", - "tests/unit/gapic/notebooks_v1beta1/test_notebook_service.py" ] } \ No newline at end of file diff --git a/synth.py b/synth.py index a77bad9..8c05f67 100644 --- a/synth.py +++ b/synth.py @@ -37,7 +37,7 @@ # ---------------------------------------------------------------------------- # Add templated files # ---------------------------------------------------------------------------- -templated_files = common.py_library(cov_level=99, microgenerator=True) +templated_files = common.py_library(cov_level=98, microgenerator=True) s.move( templated_files, excludes=[".coveragerc"] ) # the microgenerator has a good coveragerc file diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index a9e749b..2de4f17 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -5,5 +5,5 @@ # # e.g., if setup.py has "foo >= 1.14.0, < 2.0.0dev", # Then this file should have foo==1.14.0 -google-api-core==1.22.0 -proto-plus==1.1.0 \ No newline at end of file +google-api-core==1.22.2 +proto-plus==1.1.0 diff --git a/tests/unit/gapic/notebooks_v1beta1/__init__.py b/tests/unit/gapic/notebooks_v1beta1/__init__.py index 8b13789..42ffdf2 100644 --- a/tests/unit/gapic/notebooks_v1beta1/__init__.py +++ b/tests/unit/gapic/notebooks_v1beta1/__init__.py @@ -1 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/unit/gapic/notebooks_v1beta1/test_notebook_service.py b/tests/unit/gapic/notebooks_v1beta1/test_notebook_service.py index d0c6432..97a18c7 100644 --- a/tests/unit/gapic/notebooks_v1beta1/test_notebook_service.py +++ b/tests/unit/gapic/notebooks_v1beta1/test_notebook_service.py @@ -96,7 +96,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [NotebookServiceClient, NotebookServiceAsyncClient] + "client_class", [NotebookServiceClient, NotebookServiceAsyncClient,] +) +def test_notebook_service_client_from_service_account_info(client_class): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "notebooks.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [NotebookServiceClient, NotebookServiceAsyncClient,] ) def test_notebook_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -106,16 +123,21 @@ def test_notebook_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "notebooks.googleapis.com:443" def test_notebook_service_client_get_transport_class(): transport = NotebookServiceClient.get_transport_class() - assert transport == transports.NotebookServiceGrpcTransport + available_transports = [ + transports.NotebookServiceGrpcTransport, + ] + assert transport in available_transports transport = NotebookServiceClient.get_transport_class("grpc") assert transport == transports.NotebookServiceGrpcTransport @@ -166,7 +188,7 @@ def test_notebook_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -182,7 +204,7 @@ def test_notebook_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -198,7 +220,7 @@ def test_notebook_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -226,7 +248,7 @@ def test_notebook_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -287,29 +309,25 @@ def test_notebook_service_client_mtls_env_auto( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - ssl_channel_creds = mock.Mock() - with mock.patch( - "grpc.ssl_channel_credentials", return_value=ssl_channel_creds - ): - patched.return_value = None - client = client_class(client_options=options) + patched.return_value = None + client = client_class(client_options=options) - if use_client_cert_env == "false": - expected_ssl_channel_creds = None - expected_host = client.DEFAULT_ENDPOINT - else: - expected_ssl_channel_creds = ssl_channel_creds - expected_host = client.DEFAULT_MTLS_ENDPOINT + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client.DEFAULT_ENDPOINT + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) # Check the case ADC client cert is provided. Whether client cert is used depends on # GOOGLE_API_USE_CLIENT_CERTIFICATE value. @@ -318,66 +336,53 @@ def test_notebook_service_client_mtls_env_auto( ): with mock.patch.object(transport_class, "__init__") as patched: with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, ): with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.ssl_credentials", - new_callable=mock.PropertyMock, - ) as ssl_credentials_mock: - if use_client_cert_env == "false": - is_mtls_mock.return_value = False - ssl_credentials_mock.return_value = None - expected_host = client.DEFAULT_ENDPOINT - expected_ssl_channel_creds = None - else: - is_mtls_mock.return_value = True - ssl_credentials_mock.return_value = mock.Mock() - expected_host = client.DEFAULT_MTLS_ENDPOINT - expected_ssl_channel_creds = ( - ssl_credentials_mock.return_value - ) - - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client.DEFAULT_ENDPOINT + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback - # Check the case client_cert_source and ADC client cert are not provided. - with mock.patch.dict( - os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} - ): - with mock.patch.object(transport_class, "__init__") as patched: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None - ): - with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - is_mtls_mock.return_value = False patched.return_value = None client = client_class() patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=expected_host, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -403,7 +408,7 @@ def test_notebook_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -433,7 +438,7 @@ def test_notebook_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -452,7 +457,7 @@ def test_notebook_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -497,6 +502,22 @@ def test_list_instances_from_dict(): test_list_instances(request_type=dict) +def test_list_instances_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_instances), "__call__") as call: + client.list_instances() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListInstancesRequest() + + @pytest.mark.asyncio async def test_list_instances_async( transport: str = "grpc_asyncio", request_type=service.ListInstancesRequest @@ -822,6 +843,22 @@ def test_get_instance_from_dict(): test_get_instance(request_type=dict) +def test_get_instance_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + client.get_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.GetInstanceRequest() + + @pytest.mark.asyncio async def test_get_instance_async( transport: str = "grpc_asyncio", request_type=service.GetInstanceRequest @@ -1000,6 +1037,22 @@ def test_create_instance_from_dict(): test_create_instance(request_type=dict) +def test_create_instance_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + client.create_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.CreateInstanceRequest() + + @pytest.mark.asyncio async def test_create_instance_async( transport: str = "grpc_asyncio", request_type=service.CreateInstanceRequest @@ -1121,6 +1174,24 @@ def test_register_instance_from_dict(): test_register_instance(request_type=dict) +def test_register_instance_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.register_instance), "__call__" + ) as call: + client.register_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.RegisterInstanceRequest() + + @pytest.mark.asyncio async def test_register_instance_async( transport: str = "grpc_asyncio", request_type=service.RegisterInstanceRequest @@ -1248,6 +1319,24 @@ def test_set_instance_accelerator_from_dict(): test_set_instance_accelerator(request_type=dict) +def test_set_instance_accelerator_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.set_instance_accelerator), "__call__" + ) as call: + client.set_instance_accelerator() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.SetInstanceAcceleratorRequest() + + @pytest.mark.asyncio async def test_set_instance_accelerator_async( transport: str = "grpc_asyncio", request_type=service.SetInstanceAcceleratorRequest @@ -1375,6 +1464,24 @@ def test_set_instance_machine_type_from_dict(): test_set_instance_machine_type(request_type=dict) +def test_set_instance_machine_type_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.set_instance_machine_type), "__call__" + ) as call: + client.set_instance_machine_type() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.SetInstanceMachineTypeRequest() + + @pytest.mark.asyncio async def test_set_instance_machine_type_async( transport: str = "grpc_asyncio", request_type=service.SetInstanceMachineTypeRequest @@ -1502,6 +1609,24 @@ def test_set_instance_labels_from_dict(): test_set_instance_labels(request_type=dict) +def test_set_instance_labels_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.set_instance_labels), "__call__" + ) as call: + client.set_instance_labels() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.SetInstanceLabelsRequest() + + @pytest.mark.asyncio async def test_set_instance_labels_async( transport: str = "grpc_asyncio", request_type=service.SetInstanceLabelsRequest @@ -1627,6 +1752,22 @@ def test_delete_instance_from_dict(): test_delete_instance(request_type=dict) +def test_delete_instance_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: + client.delete_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.DeleteInstanceRequest() + + @pytest.mark.asyncio async def test_delete_instance_async( transport: str = "grpc_asyncio", request_type=service.DeleteInstanceRequest @@ -1746,6 +1887,22 @@ def test_start_instance_from_dict(): test_start_instance(request_type=dict) +def test_start_instance_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.start_instance), "__call__") as call: + client.start_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.StartInstanceRequest() + + @pytest.mark.asyncio async def test_start_instance_async( transport: str = "grpc_asyncio", request_type=service.StartInstanceRequest @@ -1865,6 +2022,22 @@ def test_stop_instance_from_dict(): test_stop_instance(request_type=dict) +def test_stop_instance_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.stop_instance), "__call__") as call: + client.stop_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.StopInstanceRequest() + + @pytest.mark.asyncio async def test_stop_instance_async( transport: str = "grpc_asyncio", request_type=service.StopInstanceRequest @@ -1984,6 +2157,22 @@ def test_reset_instance_from_dict(): test_reset_instance(request_type=dict) +def test_reset_instance_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.reset_instance), "__call__") as call: + client.reset_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ResetInstanceRequest() + + @pytest.mark.asyncio async def test_reset_instance_async( transport: str = "grpc_asyncio", request_type=service.ResetInstanceRequest @@ -2105,6 +2294,24 @@ def test_report_instance_info_from_dict(): test_report_instance_info(request_type=dict) +def test_report_instance_info_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.report_instance_info), "__call__" + ) as call: + client.report_instance_info() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ReportInstanceInfoRequest() + + @pytest.mark.asyncio async def test_report_instance_info_async( transport: str = "grpc_asyncio", request_type=service.ReportInstanceInfoRequest @@ -2243,6 +2450,24 @@ def test_is_instance_upgradeable_from_dict(): test_is_instance_upgradeable(request_type=dict) +def test_is_instance_upgradeable_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.is_instance_upgradeable), "__call__" + ) as call: + client.is_instance_upgradeable() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.IsInstanceUpgradeableRequest() + + @pytest.mark.asyncio async def test_is_instance_upgradeable_async( transport: str = "grpc_asyncio", request_type=service.IsInstanceUpgradeableRequest @@ -2384,6 +2609,22 @@ def test_upgrade_instance_from_dict(): test_upgrade_instance(request_type=dict) +def test_upgrade_instance_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.upgrade_instance), "__call__") as call: + client.upgrade_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.UpgradeInstanceRequest() + + @pytest.mark.asyncio async def test_upgrade_instance_async( transport: str = "grpc_asyncio", request_type=service.UpgradeInstanceRequest @@ -2505,6 +2746,24 @@ def test_upgrade_instance_internal_from_dict(): test_upgrade_instance_internal(request_type=dict) +def test_upgrade_instance_internal_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.upgrade_instance_internal), "__call__" + ) as call: + client.upgrade_instance_internal() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.UpgradeInstanceInternalRequest() + + @pytest.mark.asyncio async def test_upgrade_instance_internal_async( transport: str = "grpc_asyncio", request_type=service.UpgradeInstanceInternalRequest @@ -2639,6 +2898,24 @@ def test_list_environments_from_dict(): test_list_environments(request_type=dict) +def test_list_environments_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_environments), "__call__" + ) as call: + client.list_environments() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListEnvironmentsRequest() + + @pytest.mark.asyncio async def test_list_environments_async( transport: str = "grpc_asyncio", request_type=service.ListEnvironmentsRequest @@ -2932,6 +3209,22 @@ def test_get_environment_from_dict(): test_get_environment(request_type=dict) +def test_get_environment_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_environment), "__call__") as call: + client.get_environment() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.GetEnvironmentRequest() + + @pytest.mark.asyncio async def test_get_environment_async( transport: str = "grpc_asyncio", request_type=service.GetEnvironmentRequest @@ -3066,6 +3359,24 @@ def test_create_environment_from_dict(): test_create_environment(request_type=dict) +def test_create_environment_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_environment), "__call__" + ) as call: + client.create_environment() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.CreateEnvironmentRequest() + + @pytest.mark.asyncio async def test_create_environment_async( transport: str = "grpc_asyncio", request_type=service.CreateEnvironmentRequest @@ -3193,6 +3504,24 @@ def test_delete_environment_from_dict(): test_delete_environment(request_type=dict) +def test_delete_environment_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = NotebookServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_environment), "__call__" + ) as call: + client.delete_environment() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.DeleteEnvironmentRequest() + + @pytest.mark.asyncio async def test_delete_environment_async( transport: str = "grpc_asyncio", request_type=service.DeleteEnvironmentRequest @@ -3468,6 +3797,51 @@ def test_notebook_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.NotebookServiceGrpcTransport, + transports.NotebookServiceGrpcAsyncIOTransport, + ], +) +def test_notebook_service_grpc_transport_client_cert_source_for_mtls(transport_class): + cred = credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + def test_notebook_service_host_no_port(): client = NotebookServiceClient( credentials=credentials.AnonymousCredentials(), @@ -3489,7 +3863,7 @@ def test_notebook_service_host_with_port(): def test_notebook_service_grpc_transport_channel(): - channel = grpc.insecure_channel("http://localhost/") + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.NotebookServiceGrpcTransport( @@ -3501,7 +3875,7 @@ def test_notebook_service_grpc_transport_channel(): def test_notebook_service_grpc_asyncio_transport_channel(): - channel = aio.insecure_channel("http://localhost/") + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.NotebookServiceGrpcAsyncIOTransport( @@ -3512,6 +3886,8 @@ def test_notebook_service_grpc_asyncio_transport_channel(): assert transport._ssl_channel_credentials == None +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -3526,7 +3902,7 @@ def test_notebook_service_transport_channel_mtls_with_client_cert_source( "grpc.ssl_channel_credentials", autospec=True ) as grpc_ssl_channel_cred: with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_ssl_cred = mock.Mock() grpc_ssl_channel_cred.return_value = mock_ssl_cred @@ -3564,6 +3940,8 @@ def test_notebook_service_transport_channel_mtls_with_client_cert_source( assert transport._ssl_channel_credentials == mock_ssl_cred +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -3579,7 +3957,7 @@ def test_notebook_service_transport_channel_mtls_with_adc(transport_class): ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel