diff --git a/.gitignore b/.gitignore index b9daa52f..b4243ced 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 1cf977a8..ca2d1d18 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 00000000..f9cfcd33 --- /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 00000000..f9cfcd33 --- /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 00000000..f9cfcd33 --- /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 00000000..0eff88b3 --- /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-vision + +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 00000000..cf5de74c --- /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 ec890026..0cc1a852 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-vision # 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 a9024b15..32302e48 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/UPGRADING.md b/UPGRADING.md index c630a3b4..c3c1cd93 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -17,10 +17,10 @@ The 2.0.0 release requires Python 3.6+. Methods expect request objects. We provide a script that will convert most common use cases. -* Install the library +* Install the library with `libcst`. ```py -python3 -m pip install google-cloud-vision +python3 -m pip install google-cloud-vision[libcst] ``` * The script `fixup_vision_v1_keywords.py` is shipped with the library. It expects @@ -159,4 +159,4 @@ project = "my-project" location = "location" location_path = f"projects/{project}/locations/{location}" -``` \ No newline at end of file +``` diff --git a/google/cloud/vision_v1/services/image_annotator/async_client.py b/google/cloud/vision_v1/services/image_annotator/async_client.py index 8dc41443..1a5ea404 100644 --- a/google/cloud/vision_v1/services/image_annotator/async_client.py +++ b/google/cloud/vision_v1/services/image_annotator/async_client.py @@ -83,8 +83,36 @@ class ImageAnnotatorAsyncClient: ImageAnnotatorClient.parse_common_location_path ) - from_service_account_info = ImageAnnotatorClient.from_service_account_info - from_service_account_file = ImageAnnotatorClient.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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_info.__func__(ImageAnnotatorAsyncClient, 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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_file.__func__(ImageAnnotatorAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -213,6 +241,7 @@ async def batch_annotate_images( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -295,6 +324,7 @@ async def batch_annotate_files( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -395,6 +425,7 @@ async def async_batch_annotate_images( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -487,6 +518,7 @@ async def async_batch_annotate_files( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/vision_v1/services/image_annotator/transports/base.py b/google/cloud/vision_v1/services/image_annotator/transports/base.py index 5648dc5c..97293fb0 100644 --- a/google/cloud/vision_v1/services/image_annotator/transports/base.py +++ b/google/cloud/vision_v1/services/image_annotator/transports/base.py @@ -72,10 +72,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. @@ -83,6 +83,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: @@ -92,20 +95,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 = { @@ -118,6 +118,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -131,6 +132,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -144,6 +146,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -157,6 +160,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/vision_v1/services/image_annotator/transports/grpc.py b/google/cloud/vision_v1/services/image_annotator/transports/grpc.py index 2f4c0437..81f91a2e 100644 --- a/google/cloud/vision_v1/services/image_annotator/transports/grpc.py +++ b/google/cloud/vision_v1/services/image_annotator/transports/grpc.py @@ -111,7 +111,10 @@ 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) @@ -119,70 +122,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -190,18 +173,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( @@ -215,7 +188,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/vision_v1/services/image_annotator/transports/grpc_asyncio.py b/google/cloud/vision_v1/services/image_annotator/transports/grpc_asyncio.py index f1c4dd2a..90ecf41e 100644 --- a/google/cloud/vision_v1/services/image_annotator/transports/grpc_asyncio.py +++ b/google/cloud/vision_v1/services/image_annotator/transports/grpc_asyncio.py @@ -66,7 +66,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 @@ -144,10 +144,10 @@ def __init__( 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: @@ -156,7 +156,10 @@ 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) @@ -164,70 +167,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -235,18 +218,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/vision_v1/services/product_search/async_client.py b/google/cloud/vision_v1/services/product_search/async_client.py index 2bb84807..c6b6cc7b 100644 --- a/google/cloud/vision_v1/services/product_search/async_client.py +++ b/google/cloud/vision_v1/services/product_search/async_client.py @@ -107,8 +107,36 @@ class ProductSearchAsyncClient: ProductSearchClient.parse_common_location_path ) - from_service_account_info = ProductSearchClient.from_service_account_info - from_service_account_file = ProductSearchClient.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: + ProductSearchAsyncClient: The constructed client. + """ + return ProductSearchClient.from_service_account_info.__func__(ProductSearchAsyncClient, 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: + ProductSearchAsyncClient: The constructed client. + """ + return ProductSearchClient.from_service_account_file.__func__(ProductSearchAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -265,6 +293,7 @@ async def create_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -355,6 +384,7 @@ async def list_product_sets( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -451,6 +481,7 @@ async def get_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -555,6 +586,7 @@ async def update_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -637,6 +669,7 @@ async def delete_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -745,6 +778,7 @@ async def create_product( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -835,6 +869,7 @@ async def list_products( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -926,6 +961,7 @@ async def get_product( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1034,6 +1070,7 @@ async def update_product( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1118,6 +1155,7 @@ async def delete_product( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1244,6 +1282,7 @@ async def create_reference_image( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1328,6 +1367,7 @@ async def delete_reference_image( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1419,6 +1459,7 @@ async def list_reference_images( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1513,6 +1554,7 @@ async def get_reference_image( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1612,6 +1654,7 @@ async def add_product_to_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1702,6 +1745,7 @@ async def remove_product_from_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1795,6 +1839,7 @@ async def list_products_in_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1912,6 +1957,7 @@ async def import_product_sets( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -2040,6 +2086,7 @@ async def purge_products( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/vision_v1/services/product_search/transports/base.py b/google/cloud/vision_v1/services/product_search/transports/base.py index fd8fa748..851225f1 100644 --- a/google/cloud/vision_v1/services/product_search/transports/base.py +++ b/google/cloud/vision_v1/services/product_search/transports/base.py @@ -73,10 +73,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. @@ -84,6 +84,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: @@ -93,20 +96,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 = { @@ -117,6 +117,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -130,6 +131,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -143,6 +145,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -156,6 +159,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -169,6 +173,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -180,6 +185,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -193,6 +199,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -206,6 +213,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -219,6 +227,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -232,6 +241,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -243,6 +253,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -256,6 +267,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -269,6 +281,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -282,6 +295,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -295,6 +309,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -308,6 +323,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -321,6 +337,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -332,6 +349,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -343,6 +361,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/vision_v1/services/product_search/transports/grpc.py b/google/cloud/vision_v1/services/product_search/transports/grpc.py index fead6543..48c62d94 100644 --- a/google/cloud/vision_v1/services/product_search/transports/grpc.py +++ b/google/cloud/vision_v1/services/product_search/transports/grpc.py @@ -126,7 +126,10 @@ 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) @@ -134,70 +137,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -205,18 +188,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( @@ -230,7 +203,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/vision_v1/services/product_search/transports/grpc_asyncio.py b/google/cloud/vision_v1/services/product_search/transports/grpc_asyncio.py index 9387ce67..765e0f9e 100644 --- a/google/cloud/vision_v1/services/product_search/transports/grpc_asyncio.py +++ b/google/cloud/vision_v1/services/product_search/transports/grpc_asyncio.py @@ -81,7 +81,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 @@ -159,10 +159,10 @@ def __init__( 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: @@ -171,7 +171,10 @@ 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) @@ -179,70 +182,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -250,18 +233,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/vision_v1/types/__init__.py b/google/cloud/vision_v1/types/__init__.py index 4e38e72a..1bb08bbd 100644 --- a/google/cloud/vision_v1/types/__init__.py +++ b/google/cloud/vision_v1/types/__init__.py @@ -16,183 +16,183 @@ # from .geometry import ( - Vertex, - NormalizedVertex, BoundingPoly, + NormalizedVertex, Position, + Vertex, +) +from .image_annotator import ( + AnnotateFileRequest, + AnnotateFileResponse, + AnnotateImageRequest, + AnnotateImageResponse, + AsyncAnnotateFileRequest, + AsyncAnnotateFileResponse, + AsyncBatchAnnotateFilesRequest, + AsyncBatchAnnotateFilesResponse, + AsyncBatchAnnotateImagesRequest, + AsyncBatchAnnotateImagesResponse, + BatchAnnotateFilesRequest, + BatchAnnotateFilesResponse, + BatchAnnotateImagesRequest, + BatchAnnotateImagesResponse, + ColorInfo, + CropHint, + CropHintsAnnotation, + CropHintsParams, + DominantColorsAnnotation, + EntityAnnotation, + FaceAnnotation, + Feature, + GcsDestination, + GcsSource, + Image, + ImageAnnotationContext, + ImageContext, + ImageProperties, + ImageSource, + InputConfig, + LatLongRect, + LocalizedObjectAnnotation, + LocationInfo, + OperationMetadata, + OutputConfig, + Property, + SafeSearchAnnotation, + TextDetectionParams, + WebDetectionParams, + Likelihood, +) +from .product_search import ( + ProductSearchParams, + ProductSearchResults, ) from .product_search_service import ( - Product, - ProductSet, - ReferenceImage, + AddProductToProductSetRequest, + BatchOperationMetadata, CreateProductRequest, - ListProductsRequest, - ListProductsResponse, - GetProductRequest, - UpdateProductRequest, - DeleteProductRequest, CreateProductSetRequest, - ListProductSetsRequest, - ListProductSetsResponse, - GetProductSetRequest, - UpdateProductSetRequest, - DeleteProductSetRequest, CreateReferenceImageRequest, - ListReferenceImagesRequest, - ListReferenceImagesResponse, - GetReferenceImageRequest, + DeleteProductRequest, + DeleteProductSetRequest, DeleteReferenceImageRequest, - AddProductToProductSetRequest, - RemoveProductFromProductSetRequest, - ListProductsInProductSetRequest, - ListProductsInProductSetResponse, + GetProductRequest, + GetProductSetRequest, + GetReferenceImageRequest, ImportProductSetsGcsSource, ImportProductSetsInputConfig, ImportProductSetsRequest, ImportProductSetsResponse, - BatchOperationMetadata, + ListProductSetsRequest, + ListProductSetsResponse, + ListProductsInProductSetRequest, + ListProductsInProductSetResponse, + ListProductsRequest, + ListProductsResponse, + ListReferenceImagesRequest, + ListReferenceImagesResponse, + Product, + ProductSet, ProductSetPurgeConfig, PurgeProductsRequest, -) -from .product_search import ( - ProductSearchParams, - ProductSearchResults, + ReferenceImage, + RemoveProductFromProductSetRequest, + UpdateProductRequest, + UpdateProductSetRequest, ) from .text_annotation import ( - TextAnnotation, - Page, Block, + Page, Paragraph, - Word, Symbol, + TextAnnotation, + Word, ) from .web_detection import WebDetection -from .image_annotator import ( - Feature, - ImageSource, - Image, - FaceAnnotation, - LocationInfo, - Property, - EntityAnnotation, - LocalizedObjectAnnotation, - SafeSearchAnnotation, - LatLongRect, - ColorInfo, - DominantColorsAnnotation, - ImageProperties, - CropHint, - CropHintsAnnotation, - CropHintsParams, - WebDetectionParams, - TextDetectionParams, - ImageContext, - AnnotateImageRequest, - ImageAnnotationContext, - AnnotateImageResponse, - BatchAnnotateImagesRequest, - BatchAnnotateImagesResponse, - AnnotateFileRequest, - AnnotateFileResponse, - BatchAnnotateFilesRequest, - BatchAnnotateFilesResponse, - AsyncAnnotateFileRequest, - AsyncAnnotateFileResponse, - AsyncBatchAnnotateImagesRequest, - AsyncBatchAnnotateImagesResponse, - AsyncBatchAnnotateFilesRequest, - AsyncBatchAnnotateFilesResponse, - InputConfig, - OutputConfig, - GcsSource, - GcsDestination, - OperationMetadata, - Likelihood, -) __all__ = ( - "Vertex", - "NormalizedVertex", "BoundingPoly", + "NormalizedVertex", "Position", - "Product", - "ProductSet", - "ReferenceImage", + "Vertex", + "AnnotateFileRequest", + "AnnotateFileResponse", + "AnnotateImageRequest", + "AnnotateImageResponse", + "AsyncAnnotateFileRequest", + "AsyncAnnotateFileResponse", + "AsyncBatchAnnotateFilesRequest", + "AsyncBatchAnnotateFilesResponse", + "AsyncBatchAnnotateImagesRequest", + "AsyncBatchAnnotateImagesResponse", + "BatchAnnotateFilesRequest", + "BatchAnnotateFilesResponse", + "BatchAnnotateImagesRequest", + "BatchAnnotateImagesResponse", + "ColorInfo", + "CropHint", + "CropHintsAnnotation", + "CropHintsParams", + "DominantColorsAnnotation", + "EntityAnnotation", + "FaceAnnotation", + "Feature", + "GcsDestination", + "GcsSource", + "Image", + "ImageAnnotationContext", + "ImageContext", + "ImageProperties", + "ImageSource", + "InputConfig", + "LatLongRect", + "LocalizedObjectAnnotation", + "LocationInfo", + "OperationMetadata", + "OutputConfig", + "Property", + "SafeSearchAnnotation", + "TextDetectionParams", + "WebDetectionParams", + "Likelihood", + "ProductSearchParams", + "ProductSearchResults", + "AddProductToProductSetRequest", + "BatchOperationMetadata", "CreateProductRequest", - "ListProductsRequest", - "ListProductsResponse", - "GetProductRequest", - "UpdateProductRequest", - "DeleteProductRequest", "CreateProductSetRequest", - "ListProductSetsRequest", - "ListProductSetsResponse", - "GetProductSetRequest", - "UpdateProductSetRequest", - "DeleteProductSetRequest", "CreateReferenceImageRequest", - "ListReferenceImagesRequest", - "ListReferenceImagesResponse", - "GetReferenceImageRequest", + "DeleteProductRequest", + "DeleteProductSetRequest", "DeleteReferenceImageRequest", - "AddProductToProductSetRequest", - "RemoveProductFromProductSetRequest", - "ListProductsInProductSetRequest", - "ListProductsInProductSetResponse", + "GetProductRequest", + "GetProductSetRequest", + "GetReferenceImageRequest", "ImportProductSetsGcsSource", "ImportProductSetsInputConfig", "ImportProductSetsRequest", "ImportProductSetsResponse", - "BatchOperationMetadata", + "ListProductSetsRequest", + "ListProductSetsResponse", + "ListProductsInProductSetRequest", + "ListProductsInProductSetResponse", + "ListProductsRequest", + "ListProductsResponse", + "ListReferenceImagesRequest", + "ListReferenceImagesResponse", + "Product", + "ProductSet", "ProductSetPurgeConfig", "PurgeProductsRequest", - "ProductSearchParams", - "ProductSearchResults", - "TextAnnotation", - "Page", + "ReferenceImage", + "RemoveProductFromProductSetRequest", + "UpdateProductRequest", + "UpdateProductSetRequest", "Block", + "Page", "Paragraph", - "Word", "Symbol", + "TextAnnotation", + "Word", "WebDetection", - "Feature", - "ImageSource", - "Image", - "FaceAnnotation", - "LocationInfo", - "Property", - "EntityAnnotation", - "LocalizedObjectAnnotation", - "SafeSearchAnnotation", - "LatLongRect", - "ColorInfo", - "DominantColorsAnnotation", - "ImageProperties", - "CropHint", - "CropHintsAnnotation", - "CropHintsParams", - "WebDetectionParams", - "TextDetectionParams", - "ImageContext", - "AnnotateImageRequest", - "ImageAnnotationContext", - "AnnotateImageResponse", - "BatchAnnotateImagesRequest", - "BatchAnnotateImagesResponse", - "AnnotateFileRequest", - "AnnotateFileResponse", - "BatchAnnotateFilesRequest", - "BatchAnnotateFilesResponse", - "AsyncAnnotateFileRequest", - "AsyncAnnotateFileResponse", - "AsyncBatchAnnotateImagesRequest", - "AsyncBatchAnnotateImagesResponse", - "AsyncBatchAnnotateFilesRequest", - "AsyncBatchAnnotateFilesResponse", - "InputConfig", - "OutputConfig", - "GcsSource", - "GcsDestination", - "OperationMetadata", - "Likelihood", ) diff --git a/google/cloud/vision_v1p1beta1/services/image_annotator/async_client.py b/google/cloud/vision_v1p1beta1/services/image_annotator/async_client.py index a5154e9d..ed07ee43 100644 --- a/google/cloud/vision_v1p1beta1/services/image_annotator/async_client.py +++ b/google/cloud/vision_v1p1beta1/services/image_annotator/async_client.py @@ -76,8 +76,36 @@ class ImageAnnotatorAsyncClient: ImageAnnotatorClient.parse_common_location_path ) - from_service_account_info = ImageAnnotatorClient.from_service_account_info - from_service_account_file = ImageAnnotatorClient.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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_info.__func__(ImageAnnotatorAsyncClient, 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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_file.__func__(ImageAnnotatorAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -206,6 +234,7 @@ async def batch_annotate_images( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/vision_v1p1beta1/services/image_annotator/transports/base.py b/google/cloud/vision_v1p1beta1/services/image_annotator/transports/base.py index b9ac57ac..51ad8825 100644 --- a/google/cloud/vision_v1p1beta1/services/image_annotator/transports/base.py +++ b/google/cloud/vision_v1p1beta1/services/image_annotator/transports/base.py @@ -70,10 +70,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. @@ -81,6 +81,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: @@ -90,20 +93,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 = { @@ -116,6 +116,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc.py b/google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc.py index 3ed52718..ba4d21c0 100644 --- a/google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc.py +++ b/google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc.py @@ -109,7 +109,9 @@ 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] = {} if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -117,70 +119,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -188,17 +170,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # 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( @@ -212,7 +185,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/vision_v1p1beta1/services/image_annotator/transports/grpc_asyncio.py b/google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc_asyncio.py index 66f68f26..5023707c 100644 --- a/google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc_asyncio.py +++ b/google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc_asyncio.py @@ -64,7 +64,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 @@ -142,10 +142,10 @@ def __init__( 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: @@ -154,7 +154,9 @@ 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] = {} if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -162,70 +164,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -233,17 +215,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 = {} + # 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/vision_v1p1beta1/types/__init__.py b/google/cloud/vision_v1p1beta1/types/__init__.py index e91388a6..196e5262 100644 --- a/google/cloud/vision_v1p1beta1/types/__init__.py +++ b/google/cloud/vision_v1p1beta1/types/__init__.py @@ -16,77 +16,77 @@ # from .geometry import ( - Vertex, BoundingPoly, Position, + Vertex, ) -from .text_annotation import ( - TextAnnotation, - Page, - Block, - Paragraph, - Word, - Symbol, -) -from .web_detection import WebDetection from .image_annotator import ( + AnnotateImageRequest, + AnnotateImageResponse, + BatchAnnotateImagesRequest, + BatchAnnotateImagesResponse, + ColorInfo, + CropHint, + CropHintsAnnotation, + CropHintsParams, + DominantColorsAnnotation, + EntityAnnotation, + FaceAnnotation, Feature, - ImageSource, Image, - FaceAnnotation, + ImageContext, + ImageProperties, + ImageSource, + LatLongRect, LocationInfo, Property, - EntityAnnotation, SafeSearchAnnotation, - LatLongRect, - ColorInfo, - DominantColorsAnnotation, - ImageProperties, - CropHint, - CropHintsAnnotation, - CropHintsParams, - WebDetectionParams, TextDetectionParams, - ImageContext, - AnnotateImageRequest, - AnnotateImageResponse, - BatchAnnotateImagesRequest, - BatchAnnotateImagesResponse, + WebDetectionParams, Likelihood, ) +from .text_annotation import ( + Block, + Page, + Paragraph, + Symbol, + TextAnnotation, + Word, +) +from .web_detection import WebDetection __all__ = ( - "Vertex", "BoundingPoly", "Position", - "TextAnnotation", - "Page", - "Block", - "Paragraph", - "Word", - "Symbol", - "WebDetection", + "Vertex", + "AnnotateImageRequest", + "AnnotateImageResponse", + "BatchAnnotateImagesRequest", + "BatchAnnotateImagesResponse", + "ColorInfo", + "CropHint", + "CropHintsAnnotation", + "CropHintsParams", + "DominantColorsAnnotation", + "EntityAnnotation", + "FaceAnnotation", "Feature", - "ImageSource", "Image", - "FaceAnnotation", + "ImageContext", + "ImageProperties", + "ImageSource", + "LatLongRect", "LocationInfo", "Property", - "EntityAnnotation", "SafeSearchAnnotation", - "LatLongRect", - "ColorInfo", - "DominantColorsAnnotation", - "ImageProperties", - "CropHint", - "CropHintsAnnotation", - "CropHintsParams", - "WebDetectionParams", "TextDetectionParams", - "ImageContext", - "AnnotateImageRequest", - "AnnotateImageResponse", - "BatchAnnotateImagesRequest", - "BatchAnnotateImagesResponse", + "WebDetectionParams", "Likelihood", + "Block", + "Page", + "Paragraph", + "Symbol", + "TextAnnotation", + "Word", + "WebDetection", ) diff --git a/google/cloud/vision_v1p2beta1/services/image_annotator/async_client.py b/google/cloud/vision_v1p2beta1/services/image_annotator/async_client.py index c2efa184..07e33837 100644 --- a/google/cloud/vision_v1p2beta1/services/image_annotator/async_client.py +++ b/google/cloud/vision_v1p2beta1/services/image_annotator/async_client.py @@ -78,8 +78,36 @@ class ImageAnnotatorAsyncClient: ImageAnnotatorClient.parse_common_location_path ) - from_service_account_info = ImageAnnotatorClient.from_service_account_info - from_service_account_file = ImageAnnotatorClient.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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_info.__func__(ImageAnnotatorAsyncClient, 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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_file.__func__(ImageAnnotatorAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -208,6 +236,7 @@ async def batch_annotate_images( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -292,6 +321,7 @@ async def async_batch_annotate_files( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/vision_v1p2beta1/services/image_annotator/transports/base.py b/google/cloud/vision_v1p2beta1/services/image_annotator/transports/base.py index dbfe8e1e..6cd152c0 100644 --- a/google/cloud/vision_v1p2beta1/services/image_annotator/transports/base.py +++ b/google/cloud/vision_v1p2beta1/services/image_annotator/transports/base.py @@ -72,10 +72,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. @@ -83,6 +83,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: @@ -92,20 +95,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 = { @@ -118,6 +118,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -131,6 +132,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc.py b/google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc.py index fb17444c..b0b2f324 100644 --- a/google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc.py +++ b/google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc.py @@ -111,7 +111,10 @@ 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) @@ -119,70 +122,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -190,18 +173,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( @@ -215,7 +188,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/vision_v1p2beta1/services/image_annotator/transports/grpc_asyncio.py b/google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc_asyncio.py index 8b0c705f..21fa5d3a 100644 --- a/google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc_asyncio.py +++ b/google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc_asyncio.py @@ -66,7 +66,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 @@ -144,10 +144,10 @@ def __init__( 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: @@ -156,7 +156,10 @@ 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) @@ -164,70 +167,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -235,18 +218,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/vision_v1p2beta1/types/__init__.py b/google/cloud/vision_v1p2beta1/types/__init__.py index db10dffd..6ad8d27d 100644 --- a/google/cloud/vision_v1p2beta1/types/__init__.py +++ b/google/cloud/vision_v1p2beta1/types/__init__.py @@ -16,101 +16,101 @@ # from .geometry import ( - Vertex, - NormalizedVertex, BoundingPoly, + NormalizedVertex, Position, + Vertex, ) -from .text_annotation import ( - TextAnnotation, - Page, - Block, - Paragraph, - Word, - Symbol, -) -from .web_detection import WebDetection from .image_annotator import ( - Feature, - ImageSource, - Image, - FaceAnnotation, - LocationInfo, - Property, - EntityAnnotation, - SafeSearchAnnotation, - LatLongRect, - ColorInfo, - DominantColorsAnnotation, - ImageProperties, - CropHint, - CropHintsAnnotation, - CropHintsParams, - WebDetectionParams, - TextDetectionParams, - ImageContext, + AnnotateFileResponse, AnnotateImageRequest, - ImageAnnotationContext, AnnotateImageResponse, - AnnotateFileResponse, - BatchAnnotateImagesRequest, - BatchAnnotateImagesResponse, AsyncAnnotateFileRequest, AsyncAnnotateFileResponse, AsyncBatchAnnotateFilesRequest, AsyncBatchAnnotateFilesResponse, - InputConfig, - OutputConfig, - GcsSource, + BatchAnnotateImagesRequest, + BatchAnnotateImagesResponse, + ColorInfo, + CropHint, + CropHintsAnnotation, + CropHintsParams, + DominantColorsAnnotation, + EntityAnnotation, + FaceAnnotation, + Feature, GcsDestination, + GcsSource, + Image, + ImageAnnotationContext, + ImageContext, + ImageProperties, + ImageSource, + InputConfig, + LatLongRect, + LocationInfo, OperationMetadata, + OutputConfig, + Property, + SafeSearchAnnotation, + TextDetectionParams, + WebDetectionParams, Likelihood, ) +from .text_annotation import ( + Block, + Page, + Paragraph, + Symbol, + TextAnnotation, + Word, +) +from .web_detection import WebDetection __all__ = ( - "Vertex", - "NormalizedVertex", "BoundingPoly", + "NormalizedVertex", "Position", - "TextAnnotation", - "Page", - "Block", - "Paragraph", - "Word", - "Symbol", - "WebDetection", - "Feature", - "ImageSource", - "Image", - "FaceAnnotation", - "LocationInfo", - "Property", - "EntityAnnotation", - "SafeSearchAnnotation", - "LatLongRect", - "ColorInfo", - "DominantColorsAnnotation", - "ImageProperties", - "CropHint", - "CropHintsAnnotation", - "CropHintsParams", - "WebDetectionParams", - "TextDetectionParams", - "ImageContext", + "Vertex", + "AnnotateFileResponse", "AnnotateImageRequest", - "ImageAnnotationContext", "AnnotateImageResponse", - "AnnotateFileResponse", - "BatchAnnotateImagesRequest", - "BatchAnnotateImagesResponse", "AsyncAnnotateFileRequest", "AsyncAnnotateFileResponse", "AsyncBatchAnnotateFilesRequest", "AsyncBatchAnnotateFilesResponse", - "InputConfig", - "OutputConfig", - "GcsSource", + "BatchAnnotateImagesRequest", + "BatchAnnotateImagesResponse", + "ColorInfo", + "CropHint", + "CropHintsAnnotation", + "CropHintsParams", + "DominantColorsAnnotation", + "EntityAnnotation", + "FaceAnnotation", + "Feature", "GcsDestination", + "GcsSource", + "Image", + "ImageAnnotationContext", + "ImageContext", + "ImageProperties", + "ImageSource", + "InputConfig", + "LatLongRect", + "LocationInfo", "OperationMetadata", + "OutputConfig", + "Property", + "SafeSearchAnnotation", + "TextDetectionParams", + "WebDetectionParams", "Likelihood", + "Block", + "Page", + "Paragraph", + "Symbol", + "TextAnnotation", + "Word", + "WebDetection", ) diff --git a/google/cloud/vision_v1p3beta1/services/image_annotator/async_client.py b/google/cloud/vision_v1p3beta1/services/image_annotator/async_client.py index 1ca98853..59137286 100644 --- a/google/cloud/vision_v1p3beta1/services/image_annotator/async_client.py +++ b/google/cloud/vision_v1p3beta1/services/image_annotator/async_client.py @@ -83,8 +83,36 @@ class ImageAnnotatorAsyncClient: ImageAnnotatorClient.parse_common_location_path ) - from_service_account_info = ImageAnnotatorClient.from_service_account_info - from_service_account_file = ImageAnnotatorClient.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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_info.__func__(ImageAnnotatorAsyncClient, 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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_file.__func__(ImageAnnotatorAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -213,6 +241,7 @@ async def batch_annotate_images( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -295,6 +324,7 @@ async def async_batch_annotate_files( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/vision_v1p3beta1/services/image_annotator/transports/base.py b/google/cloud/vision_v1p3beta1/services/image_annotator/transports/base.py index f5955bab..10e41bcc 100644 --- a/google/cloud/vision_v1p3beta1/services/image_annotator/transports/base.py +++ b/google/cloud/vision_v1p3beta1/services/image_annotator/transports/base.py @@ -72,10 +72,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. @@ -83,6 +83,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: @@ -92,20 +95,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 = { @@ -118,6 +118,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -129,6 +130,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc.py b/google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc.py index 4c12c285..a4913ae6 100644 --- a/google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc.py +++ b/google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc.py @@ -111,7 +111,10 @@ 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) @@ -119,70 +122,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -190,18 +173,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( @@ -215,7 +188,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/vision_v1p3beta1/services/image_annotator/transports/grpc_asyncio.py b/google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc_asyncio.py index d502a506..97a40b99 100644 --- a/google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc_asyncio.py +++ b/google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc_asyncio.py @@ -66,7 +66,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 @@ -144,10 +144,10 @@ def __init__( 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: @@ -156,7 +156,10 @@ 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) @@ -164,70 +167,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -235,18 +218,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/vision_v1p3beta1/services/product_search/async_client.py b/google/cloud/vision_v1p3beta1/services/product_search/async_client.py index 6a7c3022..f644391c 100644 --- a/google/cloud/vision_v1p3beta1/services/product_search/async_client.py +++ b/google/cloud/vision_v1p3beta1/services/product_search/async_client.py @@ -108,8 +108,36 @@ class ProductSearchAsyncClient: ProductSearchClient.parse_common_location_path ) - from_service_account_info = ProductSearchClient.from_service_account_info - from_service_account_file = ProductSearchClient.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: + ProductSearchAsyncClient: The constructed client. + """ + return ProductSearchClient.from_service_account_info.__func__(ProductSearchAsyncClient, 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: + ProductSearchAsyncClient: The constructed client. + """ + return ProductSearchClient.from_service_account_file.__func__(ProductSearchAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -266,6 +294,7 @@ async def create_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -356,6 +385,7 @@ async def list_product_sets( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -452,6 +482,7 @@ async def get_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -554,6 +585,7 @@ async def update_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -641,6 +673,7 @@ async def delete_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -749,6 +782,7 @@ async def create_product( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -839,6 +873,7 @@ async def list_products( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -930,6 +965,7 @@ async def get_product( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1036,6 +1072,7 @@ async def update_product( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1123,6 +1160,7 @@ async def delete_product( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1249,6 +1287,7 @@ async def create_reference_image( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1339,6 +1378,7 @@ async def delete_reference_image( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1430,6 +1470,7 @@ async def list_reference_images( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1525,6 +1566,7 @@ async def get_reference_image( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1622,6 +1664,7 @@ async def add_product_to_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1715,6 +1758,7 @@ async def remove_product_from_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1808,6 +1852,7 @@ async def list_products_in_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1925,6 +1970,7 @@ async def import_product_sets( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/vision_v1p3beta1/services/product_search/transports/base.py b/google/cloud/vision_v1p3beta1/services/product_search/transports/base.py index 2b219f8b..f9ba4746 100644 --- a/google/cloud/vision_v1p3beta1/services/product_search/transports/base.py +++ b/google/cloud/vision_v1p3beta1/services/product_search/transports/base.py @@ -73,10 +73,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. @@ -84,6 +84,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: @@ -93,20 +96,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 = { @@ -117,6 +117,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -130,6 +131,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -143,6 +145,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -154,6 +157,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -167,6 +171,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -178,6 +183,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -191,6 +197,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -204,6 +211,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -215,6 +223,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -228,6 +237,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -239,6 +249,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -252,6 +263,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -265,6 +277,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -278,6 +291,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -289,6 +303,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -300,6 +315,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -313,6 +329,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -324,6 +341,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/vision_v1p3beta1/services/product_search/transports/grpc.py b/google/cloud/vision_v1p3beta1/services/product_search/transports/grpc.py index b2fc91ee..5844bad9 100644 --- a/google/cloud/vision_v1p3beta1/services/product_search/transports/grpc.py +++ b/google/cloud/vision_v1p3beta1/services/product_search/transports/grpc.py @@ -128,7 +128,10 @@ 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) @@ -136,70 +139,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -207,18 +190,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( @@ -232,7 +205,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/vision_v1p3beta1/services/product_search/transports/grpc_asyncio.py b/google/cloud/vision_v1p3beta1/services/product_search/transports/grpc_asyncio.py index 082a5a4a..326e71c7 100644 --- a/google/cloud/vision_v1p3beta1/services/product_search/transports/grpc_asyncio.py +++ b/google/cloud/vision_v1p3beta1/services/product_search/transports/grpc_asyncio.py @@ -83,7 +83,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 @@ -161,10 +161,10 @@ def __init__( 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: @@ -173,7 +173,10 @@ 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) @@ -181,70 +184,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -252,18 +235,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/vision_v1p3beta1/types/__init__.py b/google/cloud/vision_v1p3beta1/types/__init__.py index 2378e089..927cc5e0 100644 --- a/google/cloud/vision_v1p3beta1/types/__init__.py +++ b/google/cloud/vision_v1p3beta1/types/__init__.py @@ -16,175 +16,175 @@ # from .geometry import ( - Vertex, - NormalizedVertex, BoundingPoly, NormalizedBoundingPoly, + NormalizedVertex, Position, + Vertex, +) +from .image_annotator import ( + AnnotateFileResponse, + AnnotateImageRequest, + AnnotateImageResponse, + AsyncAnnotateFileRequest, + AsyncAnnotateFileResponse, + AsyncBatchAnnotateFilesRequest, + AsyncBatchAnnotateFilesResponse, + BatchAnnotateImagesRequest, + BatchAnnotateImagesResponse, + ColorInfo, + CropHint, + CropHintsAnnotation, + CropHintsParams, + DominantColorsAnnotation, + EntityAnnotation, + FaceAnnotation, + Feature, + GcsDestination, + GcsSource, + Image, + ImageAnnotationContext, + ImageContext, + ImageProperties, + ImageSource, + InputConfig, + LatLongRect, + LocalizedObjectAnnotation, + LocationInfo, + OperationMetadata, + OutputConfig, + Property, + SafeSearchAnnotation, + TextDetectionParams, + WebDetectionParams, + Likelihood, +) +from .product_search import ( + ProductSearchParams, + ProductSearchResults, + ProductSearchCategory, + ProductSearchResultsView, ) from .product_search_service import ( - Product, - ProductSet, - ReferenceImage, + AddProductToProductSetRequest, + BatchOperationMetadata, CreateProductRequest, - ListProductsRequest, - ListProductsResponse, - GetProductRequest, - UpdateProductRequest, - DeleteProductRequest, CreateProductSetRequest, - ListProductSetsRequest, - ListProductSetsResponse, - GetProductSetRequest, - UpdateProductSetRequest, - DeleteProductSetRequest, CreateReferenceImageRequest, - ListReferenceImagesRequest, - ListReferenceImagesResponse, - GetReferenceImageRequest, + DeleteProductRequest, + DeleteProductSetRequest, DeleteReferenceImageRequest, - AddProductToProductSetRequest, - RemoveProductFromProductSetRequest, - ListProductsInProductSetRequest, - ListProductsInProductSetResponse, + GetProductRequest, + GetProductSetRequest, + GetReferenceImageRequest, ImportProductSetsGcsSource, ImportProductSetsInputConfig, ImportProductSetsRequest, ImportProductSetsResponse, - BatchOperationMetadata, -) -from .product_search import ( - ProductSearchParams, - ProductSearchResults, - ProductSearchCategory, - ProductSearchResultsView, + ListProductSetsRequest, + ListProductSetsResponse, + ListProductsInProductSetRequest, + ListProductsInProductSetResponse, + ListProductsRequest, + ListProductsResponse, + ListReferenceImagesRequest, + ListReferenceImagesResponse, + Product, + ProductSet, + ReferenceImage, + RemoveProductFromProductSetRequest, + UpdateProductRequest, + UpdateProductSetRequest, ) from .text_annotation import ( - TextAnnotation, - Page, Block, + Page, Paragraph, - Word, Symbol, + TextAnnotation, + Word, ) from .web_detection import WebDetection -from .image_annotator import ( - Feature, - ImageSource, - Image, - FaceAnnotation, - LocationInfo, - Property, - EntityAnnotation, - LocalizedObjectAnnotation, - SafeSearchAnnotation, - LatLongRect, - ColorInfo, - DominantColorsAnnotation, - ImageProperties, - CropHint, - CropHintsAnnotation, - CropHintsParams, - WebDetectionParams, - TextDetectionParams, - ImageContext, - AnnotateImageRequest, - ImageAnnotationContext, - AnnotateImageResponse, - AnnotateFileResponse, - BatchAnnotateImagesRequest, - BatchAnnotateImagesResponse, - AsyncAnnotateFileRequest, - AsyncAnnotateFileResponse, - AsyncBatchAnnotateFilesRequest, - AsyncBatchAnnotateFilesResponse, - InputConfig, - OutputConfig, - GcsSource, - GcsDestination, - OperationMetadata, - Likelihood, -) __all__ = ( - "Vertex", - "NormalizedVertex", "BoundingPoly", "NormalizedBoundingPoly", + "NormalizedVertex", "Position", - "Product", - "ProductSet", - "ReferenceImage", + "Vertex", + "AnnotateFileResponse", + "AnnotateImageRequest", + "AnnotateImageResponse", + "AsyncAnnotateFileRequest", + "AsyncAnnotateFileResponse", + "AsyncBatchAnnotateFilesRequest", + "AsyncBatchAnnotateFilesResponse", + "BatchAnnotateImagesRequest", + "BatchAnnotateImagesResponse", + "ColorInfo", + "CropHint", + "CropHintsAnnotation", + "CropHintsParams", + "DominantColorsAnnotation", + "EntityAnnotation", + "FaceAnnotation", + "Feature", + "GcsDestination", + "GcsSource", + "Image", + "ImageAnnotationContext", + "ImageContext", + "ImageProperties", + "ImageSource", + "InputConfig", + "LatLongRect", + "LocalizedObjectAnnotation", + "LocationInfo", + "OperationMetadata", + "OutputConfig", + "Property", + "SafeSearchAnnotation", + "TextDetectionParams", + "WebDetectionParams", + "Likelihood", + "ProductSearchParams", + "ProductSearchResults", + "ProductSearchCategory", + "ProductSearchResultsView", + "AddProductToProductSetRequest", + "BatchOperationMetadata", "CreateProductRequest", - "ListProductsRequest", - "ListProductsResponse", - "GetProductRequest", - "UpdateProductRequest", - "DeleteProductRequest", "CreateProductSetRequest", - "ListProductSetsRequest", - "ListProductSetsResponse", - "GetProductSetRequest", - "UpdateProductSetRequest", - "DeleteProductSetRequest", "CreateReferenceImageRequest", - "ListReferenceImagesRequest", - "ListReferenceImagesResponse", - "GetReferenceImageRequest", + "DeleteProductRequest", + "DeleteProductSetRequest", "DeleteReferenceImageRequest", - "AddProductToProductSetRequest", - "RemoveProductFromProductSetRequest", - "ListProductsInProductSetRequest", - "ListProductsInProductSetResponse", + "GetProductRequest", + "GetProductSetRequest", + "GetReferenceImageRequest", "ImportProductSetsGcsSource", "ImportProductSetsInputConfig", "ImportProductSetsRequest", "ImportProductSetsResponse", - "BatchOperationMetadata", - "ProductSearchParams", - "ProductSearchResults", - "ProductSearchCategory", - "ProductSearchResultsView", - "TextAnnotation", - "Page", + "ListProductSetsRequest", + "ListProductSetsResponse", + "ListProductsInProductSetRequest", + "ListProductsInProductSetResponse", + "ListProductsRequest", + "ListProductsResponse", + "ListReferenceImagesRequest", + "ListReferenceImagesResponse", + "Product", + "ProductSet", + "ReferenceImage", + "RemoveProductFromProductSetRequest", + "UpdateProductRequest", + "UpdateProductSetRequest", "Block", + "Page", "Paragraph", - "Word", "Symbol", + "TextAnnotation", + "Word", "WebDetection", - "Feature", - "ImageSource", - "Image", - "FaceAnnotation", - "LocationInfo", - "Property", - "EntityAnnotation", - "LocalizedObjectAnnotation", - "SafeSearchAnnotation", - "LatLongRect", - "ColorInfo", - "DominantColorsAnnotation", - "ImageProperties", - "CropHint", - "CropHintsAnnotation", - "CropHintsParams", - "WebDetectionParams", - "TextDetectionParams", - "ImageContext", - "AnnotateImageRequest", - "ImageAnnotationContext", - "AnnotateImageResponse", - "AnnotateFileResponse", - "BatchAnnotateImagesRequest", - "BatchAnnotateImagesResponse", - "AsyncAnnotateFileRequest", - "AsyncAnnotateFileResponse", - "AsyncBatchAnnotateFilesRequest", - "AsyncBatchAnnotateFilesResponse", - "InputConfig", - "OutputConfig", - "GcsSource", - "GcsDestination", - "OperationMetadata", - "Likelihood", ) diff --git a/google/cloud/vision_v1p4beta1/__init__.py b/google/cloud/vision_v1p4beta1/__init__.py index 890dd009..c2b932ed 100644 --- a/google/cloud/vision_v1p4beta1/__init__.py +++ b/google/cloud/vision_v1p4beta1/__init__.py @@ -158,7 +158,6 @@ class ImageAnnotatorClient(VisionHelpers, IacImageAnnotatorClient): "GetReferenceImageRequest", "Image", "ImageAnnotationContext", - "ImageAnnotatorClient", "ImageContext", "ImageProperties", "ImageSource", @@ -186,6 +185,7 @@ class ImageAnnotatorClient(VisionHelpers, IacImageAnnotatorClient): "Paragraph", "Position", "Product", + "ProductSearchClient", "ProductSearchParams", "ProductSearchResults", "ProductSet", @@ -204,5 +204,5 @@ class ImageAnnotatorClient(VisionHelpers, IacImageAnnotatorClient): "WebDetection", "WebDetectionParams", "Word", - "ProductSearchClient", + "ImageAnnotatorClient", ) diff --git a/google/cloud/vision_v1p4beta1/services/image_annotator/async_client.py b/google/cloud/vision_v1p4beta1/services/image_annotator/async_client.py index 1a9f75e6..44907205 100644 --- a/google/cloud/vision_v1p4beta1/services/image_annotator/async_client.py +++ b/google/cloud/vision_v1p4beta1/services/image_annotator/async_client.py @@ -83,8 +83,36 @@ class ImageAnnotatorAsyncClient: ImageAnnotatorClient.parse_common_location_path ) - from_service_account_info = ImageAnnotatorClient.from_service_account_info - from_service_account_file = ImageAnnotatorClient.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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_info.__func__(ImageAnnotatorAsyncClient, 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: + ImageAnnotatorAsyncClient: The constructed client. + """ + return ImageAnnotatorClient.from_service_account_file.__func__(ImageAnnotatorAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -211,6 +239,7 @@ async def batch_annotate_images( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -291,6 +320,7 @@ async def batch_annotate_files( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -389,6 +419,7 @@ async def async_batch_annotate_images( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -479,6 +510,7 @@ async def async_batch_annotate_files( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/vision_v1p4beta1/services/image_annotator/transports/base.py b/google/cloud/vision_v1p4beta1/services/image_annotator/transports/base.py index 7b72bb0c..00cbd367 100644 --- a/google/cloud/vision_v1p4beta1/services/image_annotator/transports/base.py +++ b/google/cloud/vision_v1p4beta1/services/image_annotator/transports/base.py @@ -72,10 +72,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. @@ -83,6 +83,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: @@ -92,20 +95,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 = { @@ -116,6 +116,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -127,6 +128,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -138,6 +140,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -149,6 +152,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc.py b/google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc.py index e4918610..e31b0cf1 100644 --- a/google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc.py +++ b/google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc.py @@ -111,7 +111,10 @@ 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) @@ -119,70 +122,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -190,18 +173,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( @@ -215,7 +188,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/vision_v1p4beta1/services/image_annotator/transports/grpc_asyncio.py b/google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc_asyncio.py index 3e26363e..2febab6d 100644 --- a/google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc_asyncio.py +++ b/google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc_asyncio.py @@ -66,7 +66,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 @@ -144,10 +144,10 @@ def __init__( 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: @@ -156,7 +156,10 @@ 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) @@ -164,70 +167,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -235,18 +218,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/vision_v1p4beta1/services/product_search/async_client.py b/google/cloud/vision_v1p4beta1/services/product_search/async_client.py index 41e45889..f6e10a3c 100644 --- a/google/cloud/vision_v1p4beta1/services/product_search/async_client.py +++ b/google/cloud/vision_v1p4beta1/services/product_search/async_client.py @@ -109,8 +109,36 @@ class ProductSearchAsyncClient: ProductSearchClient.parse_common_location_path ) - from_service_account_info = ProductSearchClient.from_service_account_info - from_service_account_file = ProductSearchClient.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: + ProductSearchAsyncClient: The constructed client. + """ + return ProductSearchClient.from_service_account_info.__func__(ProductSearchAsyncClient, 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: + ProductSearchAsyncClient: The constructed client. + """ + return ProductSearchClient.from_service_account_file.__func__(ProductSearchAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -267,6 +295,7 @@ async def create_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -357,6 +386,7 @@ async def list_product_sets( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -453,6 +483,7 @@ async def get_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -555,6 +586,7 @@ async def update_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -637,6 +669,7 @@ async def delete_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -745,6 +778,7 @@ async def create_product( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -835,6 +869,7 @@ async def list_products( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -926,6 +961,7 @@ async def get_product( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1032,6 +1068,7 @@ async def update_product( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1116,6 +1153,7 @@ async def delete_product( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1242,6 +1280,7 @@ async def create_reference_image( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1327,6 +1366,7 @@ async def delete_reference_image( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1418,6 +1458,7 @@ async def list_reference_images( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1513,6 +1554,7 @@ async def get_reference_image( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1610,6 +1652,7 @@ async def add_product_to_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1698,6 +1741,7 @@ async def remove_product_from_product_set( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1791,6 +1835,7 @@ async def list_products_in_product_set( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -1908,6 +1953,7 @@ async def import_product_sets( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/vision_v1p4beta1/services/product_search/transports/base.py b/google/cloud/vision_v1p4beta1/services/product_search/transports/base.py index 3d3d71bd..8a2f9f2a 100644 --- a/google/cloud/vision_v1p4beta1/services/product_search/transports/base.py +++ b/google/cloud/vision_v1p4beta1/services/product_search/transports/base.py @@ -73,10 +73,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. @@ -84,6 +84,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: @@ -93,20 +96,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 = { @@ -117,6 +117,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -130,6 +131,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -143,6 +145,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -154,6 +157,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -167,6 +171,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -178,6 +183,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -191,6 +197,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -204,6 +211,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -215,6 +223,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -228,6 +237,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -239,6 +249,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -252,6 +263,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -265,6 +277,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -278,6 +291,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -289,6 +303,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -300,6 +315,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -313,6 +329,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -324,6 +341,7 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type(), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/vision_v1p4beta1/services/product_search/transports/grpc.py b/google/cloud/vision_v1p4beta1/services/product_search/transports/grpc.py index cded719d..ef133008 100644 --- a/google/cloud/vision_v1p4beta1/services/product_search/transports/grpc.py +++ b/google/cloud/vision_v1p4beta1/services/product_search/transports/grpc.py @@ -128,7 +128,10 @@ 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) @@ -136,70 +139,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -207,18 +190,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( @@ -232,7 +205,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/vision_v1p4beta1/services/product_search/transports/grpc_asyncio.py b/google/cloud/vision_v1p4beta1/services/product_search/transports/grpc_asyncio.py index 3edf5094..04bc1521 100644 --- a/google/cloud/vision_v1p4beta1/services/product_search/transports/grpc_asyncio.py +++ b/google/cloud/vision_v1p4beta1/services/product_search/transports/grpc_asyncio.py @@ -83,7 +83,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 @@ -161,10 +161,10 @@ def __init__( 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: @@ -173,7 +173,10 @@ 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) @@ -181,70 +184,50 @@ def __init__( 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: - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) - - 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 - # 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 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 - ) + else: + 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 + ) - 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 - ) + # 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, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -252,18 +235,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/vision_v1p4beta1/types/__init__.py b/google/cloud/vision_v1p4beta1/types/__init__.py index d1f39653..fd5dd48d 100644 --- a/google/cloud/vision_v1p4beta1/types/__init__.py +++ b/google/cloud/vision_v1p4beta1/types/__init__.py @@ -15,192 +15,192 @@ # limitations under the License. # +from .face import ( + Celebrity, + FaceRecognitionParams, + FaceRecognitionResult, +) from .geometry import ( - Vertex, - NormalizedVertex, BoundingPoly, + NormalizedVertex, Position, + Vertex, ) -from .face import ( - FaceRecognitionParams, - Celebrity, - FaceRecognitionResult, +from .image_annotator import ( + AnnotateFileRequest, + AnnotateFileResponse, + AnnotateImageRequest, + AnnotateImageResponse, + AsyncAnnotateFileRequest, + AsyncAnnotateFileResponse, + AsyncBatchAnnotateFilesRequest, + AsyncBatchAnnotateFilesResponse, + AsyncBatchAnnotateImagesRequest, + AsyncBatchAnnotateImagesResponse, + BatchAnnotateFilesRequest, + BatchAnnotateFilesResponse, + BatchAnnotateImagesRequest, + BatchAnnotateImagesResponse, + ColorInfo, + CropHint, + CropHintsAnnotation, + CropHintsParams, + DominantColorsAnnotation, + EntityAnnotation, + FaceAnnotation, + Feature, + GcsDestination, + GcsSource, + Image, + ImageAnnotationContext, + ImageContext, + ImageProperties, + ImageSource, + InputConfig, + LatLongRect, + LocalizedObjectAnnotation, + LocationInfo, + OperationMetadata, + OutputConfig, + Property, + SafeSearchAnnotation, + TextDetectionParams, + WebDetectionParams, + Likelihood, +) +from .product_search import ( + ProductSearchParams, + ProductSearchResults, ) from .product_search_service import ( - Product, - ProductSet, - ReferenceImage, + AddProductToProductSetRequest, + BatchOperationMetadata, CreateProductRequest, - ListProductsRequest, - ListProductsResponse, - GetProductRequest, - UpdateProductRequest, - DeleteProductRequest, CreateProductSetRequest, - ListProductSetsRequest, - ListProductSetsResponse, - GetProductSetRequest, - UpdateProductSetRequest, - DeleteProductSetRequest, CreateReferenceImageRequest, - ListReferenceImagesRequest, - ListReferenceImagesResponse, - GetReferenceImageRequest, + DeleteProductRequest, + DeleteProductSetRequest, DeleteReferenceImageRequest, - AddProductToProductSetRequest, - RemoveProductFromProductSetRequest, - ListProductsInProductSetRequest, - ListProductsInProductSetResponse, + GetProductRequest, + GetProductSetRequest, + GetReferenceImageRequest, ImportProductSetsGcsSource, ImportProductSetsInputConfig, ImportProductSetsRequest, ImportProductSetsResponse, - BatchOperationMetadata, + ListProductSetsRequest, + ListProductSetsResponse, + ListProductsInProductSetRequest, + ListProductsInProductSetResponse, + ListProductsRequest, + ListProductsResponse, + ListReferenceImagesRequest, + ListReferenceImagesResponse, + Product, + ProductSet, ProductSetPurgeConfig, PurgeProductsRequest, -) -from .product_search import ( - ProductSearchParams, - ProductSearchResults, + ReferenceImage, + RemoveProductFromProductSetRequest, + UpdateProductRequest, + UpdateProductSetRequest, ) from .text_annotation import ( - TextAnnotation, - Page, Block, + Page, Paragraph, - Word, Symbol, + TextAnnotation, + Word, ) from .web_detection import WebDetection -from .image_annotator import ( - Feature, - ImageSource, - Image, - FaceAnnotation, - LocationInfo, - Property, - EntityAnnotation, - LocalizedObjectAnnotation, - SafeSearchAnnotation, - LatLongRect, - ColorInfo, - DominantColorsAnnotation, - ImageProperties, - CropHint, - CropHintsAnnotation, - CropHintsParams, - WebDetectionParams, - TextDetectionParams, - ImageContext, - AnnotateImageRequest, - ImageAnnotationContext, - AnnotateImageResponse, - BatchAnnotateImagesRequest, - BatchAnnotateImagesResponse, - AnnotateFileRequest, - AnnotateFileResponse, - BatchAnnotateFilesRequest, - BatchAnnotateFilesResponse, - AsyncAnnotateFileRequest, - AsyncAnnotateFileResponse, - AsyncBatchAnnotateImagesRequest, - AsyncBatchAnnotateImagesResponse, - AsyncBatchAnnotateFilesRequest, - AsyncBatchAnnotateFilesResponse, - InputConfig, - OutputConfig, - GcsSource, - GcsDestination, - OperationMetadata, - Likelihood, -) __all__ = ( - "Vertex", - "NormalizedVertex", - "BoundingPoly", - "Position", - "FaceRecognitionParams", "Celebrity", + "FaceRecognitionParams", "FaceRecognitionResult", - "Product", - "ProductSet", - "ReferenceImage", + "BoundingPoly", + "NormalizedVertex", + "Position", + "Vertex", + "AnnotateFileRequest", + "AnnotateFileResponse", + "AnnotateImageRequest", + "AnnotateImageResponse", + "AsyncAnnotateFileRequest", + "AsyncAnnotateFileResponse", + "AsyncBatchAnnotateFilesRequest", + "AsyncBatchAnnotateFilesResponse", + "AsyncBatchAnnotateImagesRequest", + "AsyncBatchAnnotateImagesResponse", + "BatchAnnotateFilesRequest", + "BatchAnnotateFilesResponse", + "BatchAnnotateImagesRequest", + "BatchAnnotateImagesResponse", + "ColorInfo", + "CropHint", + "CropHintsAnnotation", + "CropHintsParams", + "DominantColorsAnnotation", + "EntityAnnotation", + "FaceAnnotation", + "Feature", + "GcsDestination", + "GcsSource", + "Image", + "ImageAnnotationContext", + "ImageContext", + "ImageProperties", + "ImageSource", + "InputConfig", + "LatLongRect", + "LocalizedObjectAnnotation", + "LocationInfo", + "OperationMetadata", + "OutputConfig", + "Property", + "SafeSearchAnnotation", + "TextDetectionParams", + "WebDetectionParams", + "Likelihood", + "ProductSearchParams", + "ProductSearchResults", + "AddProductToProductSetRequest", + "BatchOperationMetadata", "CreateProductRequest", - "ListProductsRequest", - "ListProductsResponse", - "GetProductRequest", - "UpdateProductRequest", - "DeleteProductRequest", "CreateProductSetRequest", - "ListProductSetsRequest", - "ListProductSetsResponse", - "GetProductSetRequest", - "UpdateProductSetRequest", - "DeleteProductSetRequest", "CreateReferenceImageRequest", - "ListReferenceImagesRequest", - "ListReferenceImagesResponse", - "GetReferenceImageRequest", + "DeleteProductRequest", + "DeleteProductSetRequest", "DeleteReferenceImageRequest", - "AddProductToProductSetRequest", - "RemoveProductFromProductSetRequest", - "ListProductsInProductSetRequest", - "ListProductsInProductSetResponse", + "GetProductRequest", + "GetProductSetRequest", + "GetReferenceImageRequest", "ImportProductSetsGcsSource", "ImportProductSetsInputConfig", "ImportProductSetsRequest", "ImportProductSetsResponse", - "BatchOperationMetadata", + "ListProductSetsRequest", + "ListProductSetsResponse", + "ListProductsInProductSetRequest", + "ListProductsInProductSetResponse", + "ListProductsRequest", + "ListProductsResponse", + "ListReferenceImagesRequest", + "ListReferenceImagesResponse", + "Product", + "ProductSet", "ProductSetPurgeConfig", "PurgeProductsRequest", - "ProductSearchParams", - "ProductSearchResults", - "TextAnnotation", - "Page", + "ReferenceImage", + "RemoveProductFromProductSetRequest", + "UpdateProductRequest", + "UpdateProductSetRequest", "Block", + "Page", "Paragraph", - "Word", "Symbol", + "TextAnnotation", + "Word", "WebDetection", - "Feature", - "ImageSource", - "Image", - "FaceAnnotation", - "LocationInfo", - "Property", - "EntityAnnotation", - "LocalizedObjectAnnotation", - "SafeSearchAnnotation", - "LatLongRect", - "ColorInfo", - "DominantColorsAnnotation", - "ImageProperties", - "CropHint", - "CropHintsAnnotation", - "CropHintsParams", - "WebDetectionParams", - "TextDetectionParams", - "ImageContext", - "AnnotateImageRequest", - "ImageAnnotationContext", - "AnnotateImageResponse", - "BatchAnnotateImagesRequest", - "BatchAnnotateImagesResponse", - "AnnotateFileRequest", - "AnnotateFileResponse", - "BatchAnnotateFilesRequest", - "BatchAnnotateFilesResponse", - "AsyncAnnotateFileRequest", - "AsyncAnnotateFileResponse", - "AsyncBatchAnnotateImagesRequest", - "AsyncBatchAnnotateImagesResponse", - "AsyncBatchAnnotateFilesRequest", - "AsyncBatchAnnotateFilesResponse", - "InputConfig", - "OutputConfig", - "GcsSource", - "GcsDestination", - "OperationMetadata", - "Likelihood", ) diff --git a/noxfile.py b/noxfile.py index 7aa317d8..2bcbfa85 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,14 +149,33 @@ def system(session): # Install all test dependencies, then install this package into the # virtualenv's dist-packages. - session.install("mock", "pytest", "google-cloud-testutils", "google-cloud-storage") - session.install("-e", ".") + session.install( + "mock", + "pytest", + "google-cloud-testutils", + "google-cloud-storage", + "-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) @@ -152,7 +186,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") diff --git a/renovate.json b/renovate.json index 4fa94931..f08bc22c 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 8ce7fb1f..cbffcbc2 100644 --- a/setup.py +++ b/setup.py @@ -23,10 +23,11 @@ release_status = "Development Status :: 5 - Production/Stable" dependencies = [ "google-api-core[grpc] >= 1.22.2, < 2.0.0dev", - "proto-plus >= 1.4.0", - "libcst >= 0.2.5", + "proto-plus >= 1.15.0", ] +extras = {"libcst": "libcst >= 0.2.5"} + package_root = os.path.abspath(os.path.dirname(__file__)) readme_filename = os.path.join(package_root, "README.rst") @@ -68,6 +69,7 @@ packages=packages, namespace_packages=namespaces, install_requires=dependencies, + extras_require=extras, python_requires=">=3.6", scripts=[ "scripts/fixup_vision_v1_keywords.py", diff --git a/synth.metadata b/synth.metadata index 58abef80..52c05252 100644 --- a/synth.metadata +++ b/synth.metadata @@ -3,30 +3,30 @@ { "git": { "name": ".", - "remote": "https://github.com/googleapis/python-vision.git", - "sha": "b992a295c3f1634518d8b38bc12052b66c03c1dc" + "remote": "git@github.com:googleapis/python-vision", + "sha": "2c430e75215ed7c49407a38478dbff680847b696" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "e28aa8570dc86136fe677202c976f4ee00d77f61", - "internalRef": "356624136" + "sha": "c539b9b08b3366ee00c0ec1950f4df711552a269", + "internalRef": "365759522" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4679e7e415221f03ff2a71e3ffad75b9ec41d87e" + "sha": "572ef8f70edd9041f5bcfa71511aed6aecfc2098" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4679e7e415221f03ff2a71e3ffad75b9ec41d87e" + "sha": "572ef8f70edd9041f5bcfa71511aed6aecfc2098" } } ], @@ -76,244 +76,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/vision_v1/image_annotator.rst", - "docs/vision_v1/product_search.rst", - "docs/vision_v1/services.rst", - "docs/vision_v1/types.rst", - "docs/vision_v1p2beta1/image_annotator.rst", - "docs/vision_v1p2beta1/services.rst", - "docs/vision_v1p2beta1/types.rst", - "docs/vision_v1p3beta1/image_annotator.rst", - "docs/vision_v1p3beta1/product_search.rst", - "docs/vision_v1p3beta1/services.rst", - "docs/vision_v1p3beta1/types.rst", - "docs/vision_v1p4beta1/image_annotator.rst", - "docs/vision_v1p4beta1/product_search.rst", - "docs/vision_v1p4beta1/services.rst", - "docs/vision_v1p4beta1/types.rst", - "google/cloud/vision/__init__.py", - "google/cloud/vision/py.typed", - "google/cloud/vision_v1/__init__.py", - "google/cloud/vision_v1/proto/geometry.proto", - "google/cloud/vision_v1/proto/image_annotator.proto", - "google/cloud/vision_v1/proto/product_search.proto", - "google/cloud/vision_v1/proto/product_search_service.proto", - "google/cloud/vision_v1/proto/text_annotation.proto", - "google/cloud/vision_v1/proto/web_detection.proto", - "google/cloud/vision_v1/py.typed", - "google/cloud/vision_v1/services/__init__.py", - "google/cloud/vision_v1/services/image_annotator/__init__.py", - "google/cloud/vision_v1/services/image_annotator/async_client.py", - "google/cloud/vision_v1/services/image_annotator/client.py", - "google/cloud/vision_v1/services/image_annotator/transports/__init__.py", - "google/cloud/vision_v1/services/image_annotator/transports/base.py", - "google/cloud/vision_v1/services/image_annotator/transports/grpc.py", - "google/cloud/vision_v1/services/image_annotator/transports/grpc_asyncio.py", - "google/cloud/vision_v1/services/product_search/__init__.py", - "google/cloud/vision_v1/services/product_search/async_client.py", - "google/cloud/vision_v1/services/product_search/client.py", - "google/cloud/vision_v1/services/product_search/pagers.py", - "google/cloud/vision_v1/services/product_search/transports/__init__.py", - "google/cloud/vision_v1/services/product_search/transports/base.py", - "google/cloud/vision_v1/services/product_search/transports/grpc.py", - "google/cloud/vision_v1/services/product_search/transports/grpc_asyncio.py", - "google/cloud/vision_v1/types/__init__.py", - "google/cloud/vision_v1/types/geometry.py", - "google/cloud/vision_v1/types/image_annotator.py", - "google/cloud/vision_v1/types/product_search.py", - "google/cloud/vision_v1/types/product_search_service.py", - "google/cloud/vision_v1/types/text_annotation.py", - "google/cloud/vision_v1/types/web_detection.py", - "google/cloud/vision_v1p1beta1/__init__.py", - "google/cloud/vision_v1p1beta1/proto/geometry.proto", - "google/cloud/vision_v1p1beta1/proto/image_annotator.proto", - "google/cloud/vision_v1p1beta1/proto/text_annotation.proto", - "google/cloud/vision_v1p1beta1/proto/web_detection.proto", - "google/cloud/vision_v1p1beta1/py.typed", - "google/cloud/vision_v1p1beta1/services/__init__.py", - "google/cloud/vision_v1p1beta1/services/image_annotator/__init__.py", - "google/cloud/vision_v1p1beta1/services/image_annotator/async_client.py", - "google/cloud/vision_v1p1beta1/services/image_annotator/client.py", - "google/cloud/vision_v1p1beta1/services/image_annotator/transports/__init__.py", - "google/cloud/vision_v1p1beta1/services/image_annotator/transports/base.py", - "google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc.py", - "google/cloud/vision_v1p1beta1/services/image_annotator/transports/grpc_asyncio.py", - "google/cloud/vision_v1p1beta1/types/__init__.py", - "google/cloud/vision_v1p1beta1/types/geometry.py", - "google/cloud/vision_v1p1beta1/types/image_annotator.py", - "google/cloud/vision_v1p1beta1/types/text_annotation.py", - "google/cloud/vision_v1p1beta1/types/web_detection.py", - "google/cloud/vision_v1p2beta1/__init__.py", - "google/cloud/vision_v1p2beta1/proto/geometry.proto", - "google/cloud/vision_v1p2beta1/proto/image_annotator.proto", - "google/cloud/vision_v1p2beta1/proto/text_annotation.proto", - "google/cloud/vision_v1p2beta1/proto/web_detection.proto", - "google/cloud/vision_v1p2beta1/py.typed", - "google/cloud/vision_v1p2beta1/services/__init__.py", - "google/cloud/vision_v1p2beta1/services/image_annotator/__init__.py", - "google/cloud/vision_v1p2beta1/services/image_annotator/async_client.py", - "google/cloud/vision_v1p2beta1/services/image_annotator/client.py", - "google/cloud/vision_v1p2beta1/services/image_annotator/transports/__init__.py", - "google/cloud/vision_v1p2beta1/services/image_annotator/transports/base.py", - "google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc.py", - "google/cloud/vision_v1p2beta1/services/image_annotator/transports/grpc_asyncio.py", - "google/cloud/vision_v1p2beta1/types/__init__.py", - "google/cloud/vision_v1p2beta1/types/geometry.py", - "google/cloud/vision_v1p2beta1/types/image_annotator.py", - "google/cloud/vision_v1p2beta1/types/text_annotation.py", - "google/cloud/vision_v1p2beta1/types/web_detection.py", - "google/cloud/vision_v1p3beta1/__init__.py", - "google/cloud/vision_v1p3beta1/proto/geometry.proto", - "google/cloud/vision_v1p3beta1/proto/image_annotator.proto", - "google/cloud/vision_v1p3beta1/proto/product_search.proto", - "google/cloud/vision_v1p3beta1/proto/product_search_service.proto", - "google/cloud/vision_v1p3beta1/proto/text_annotation.proto", - "google/cloud/vision_v1p3beta1/proto/web_detection.proto", - "google/cloud/vision_v1p3beta1/py.typed", - "google/cloud/vision_v1p3beta1/services/__init__.py", - "google/cloud/vision_v1p3beta1/services/image_annotator/__init__.py", - "google/cloud/vision_v1p3beta1/services/image_annotator/async_client.py", - "google/cloud/vision_v1p3beta1/services/image_annotator/client.py", - "google/cloud/vision_v1p3beta1/services/image_annotator/transports/__init__.py", - "google/cloud/vision_v1p3beta1/services/image_annotator/transports/base.py", - "google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc.py", - "google/cloud/vision_v1p3beta1/services/image_annotator/transports/grpc_asyncio.py", - "google/cloud/vision_v1p3beta1/services/product_search/__init__.py", - "google/cloud/vision_v1p3beta1/services/product_search/async_client.py", - "google/cloud/vision_v1p3beta1/services/product_search/client.py", - "google/cloud/vision_v1p3beta1/services/product_search/pagers.py", - "google/cloud/vision_v1p3beta1/services/product_search/transports/__init__.py", - "google/cloud/vision_v1p3beta1/services/product_search/transports/base.py", - "google/cloud/vision_v1p3beta1/services/product_search/transports/grpc.py", - "google/cloud/vision_v1p3beta1/services/product_search/transports/grpc_asyncio.py", - "google/cloud/vision_v1p3beta1/types/__init__.py", - "google/cloud/vision_v1p3beta1/types/geometry.py", - "google/cloud/vision_v1p3beta1/types/image_annotator.py", - "google/cloud/vision_v1p3beta1/types/product_search.py", - "google/cloud/vision_v1p3beta1/types/product_search_service.py", - "google/cloud/vision_v1p3beta1/types/text_annotation.py", - "google/cloud/vision_v1p3beta1/types/web_detection.py", - "google/cloud/vision_v1p4beta1/__init__.py", - "google/cloud/vision_v1p4beta1/proto/face.proto", - "google/cloud/vision_v1p4beta1/proto/geometry.proto", - "google/cloud/vision_v1p4beta1/proto/image_annotator.proto", - "google/cloud/vision_v1p4beta1/proto/product_search.proto", - "google/cloud/vision_v1p4beta1/proto/product_search_service.proto", - "google/cloud/vision_v1p4beta1/proto/text_annotation.proto", - "google/cloud/vision_v1p4beta1/proto/web_detection.proto", - "google/cloud/vision_v1p4beta1/py.typed", - "google/cloud/vision_v1p4beta1/services/__init__.py", - "google/cloud/vision_v1p4beta1/services/image_annotator/__init__.py", - "google/cloud/vision_v1p4beta1/services/image_annotator/async_client.py", - "google/cloud/vision_v1p4beta1/services/image_annotator/client.py", - "google/cloud/vision_v1p4beta1/services/image_annotator/transports/__init__.py", - "google/cloud/vision_v1p4beta1/services/image_annotator/transports/base.py", - "google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc.py", - "google/cloud/vision_v1p4beta1/services/image_annotator/transports/grpc_asyncio.py", - "google/cloud/vision_v1p4beta1/services/product_search/__init__.py", - "google/cloud/vision_v1p4beta1/services/product_search/async_client.py", - "google/cloud/vision_v1p4beta1/services/product_search/client.py", - "google/cloud/vision_v1p4beta1/services/product_search/pagers.py", - "google/cloud/vision_v1p4beta1/services/product_search/transports/__init__.py", - "google/cloud/vision_v1p4beta1/services/product_search/transports/base.py", - "google/cloud/vision_v1p4beta1/services/product_search/transports/grpc.py", - "google/cloud/vision_v1p4beta1/services/product_search/transports/grpc_asyncio.py", - "google/cloud/vision_v1p4beta1/types/__init__.py", - "google/cloud/vision_v1p4beta1/types/face.py", - "google/cloud/vision_v1p4beta1/types/geometry.py", - "google/cloud/vision_v1p4beta1/types/image_annotator.py", - "google/cloud/vision_v1p4beta1/types/product_search.py", - "google/cloud/vision_v1p4beta1/types/product_search_service.py", - "google/cloud/vision_v1p4beta1/types/text_annotation.py", - "google/cloud/vision_v1p4beta1/types/web_detection.py", - "noxfile.py", - "renovate.json", - "samples/AUTHORING_GUIDE.md", - "samples/CONTRIBUTING.md", - "samples/snippets/crop_hints/noxfile.py", - "samples/snippets/detect/noxfile.py", - "samples/snippets/document_text/noxfile.py", - "samples/snippets/face_detection/noxfile.py", - "samples/snippets/product_search/noxfile.py", - "samples/snippets/quickstart/noxfile.py", - "samples/snippets/web/noxfile.py", - "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/vision_v1/__init__.py", - "tests/unit/gapic/vision_v1/test_image_annotator.py", - "tests/unit/gapic/vision_v1/test_product_search.py", - "tests/unit/gapic/vision_v1p1beta1/__init__.py", - "tests/unit/gapic/vision_v1p1beta1/test_image_annotator.py", - "tests/unit/gapic/vision_v1p2beta1/__init__.py", - "tests/unit/gapic/vision_v1p2beta1/test_image_annotator.py", - "tests/unit/gapic/vision_v1p3beta1/__init__.py", - "tests/unit/gapic/vision_v1p3beta1/test_image_annotator.py", - "tests/unit/gapic/vision_v1p3beta1/test_product_search.py", - "tests/unit/gapic/vision_v1p4beta1/__init__.py", - "tests/unit/gapic/vision_v1p4beta1/test_image_annotator.py", - "tests/unit/gapic/vision_v1p4beta1/test_product_search.py" ] } \ No newline at end of file diff --git a/synth.py b/synth.py index 7ced8afa..6153313e 100644 --- a/synth.py +++ b/synth.py @@ -33,7 +33,7 @@ bazel_target=f"//google/cloud/vision/{version}:vision-{version}-py", include_protos=True ) - + s.move(library / f"google/cloud/vision_{version}/proto") s.move(library / f"google/cloud/vision_{version}/services") s.move(library / f"google/cloud/vision_{version}/types") @@ -117,7 +117,7 @@ templated_files = common.py_library( samples=True, microgenerator=True, - cov_level=99, + cov_level=98, system_test_external_dependencies=["google-cloud-storage"] ) s.move(templated_files, excludes=[".coveragerc"]) # microgenerator has a good .coveragerc file diff --git a/testing/constraints-3.10.txt b/testing/constraints-3.10.txt new file mode 100644 index 00000000..e69de29b diff --git a/testing/constraints-3.11.txt b/testing/constraints-3.11.txt new file mode 100644 index 00000000..e69de29b diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt new file mode 100644 index 00000000..cc205f2a --- /dev/null +++ b/testing/constraints-3.6.txt @@ -0,0 +1,9 @@ +# This constraints file is used to check that lower bounds +# are correct in setup.py +# List *all* library dependencies and extras in this file. +# Pin the version to the lower bound. +# +# 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.2 +proto-plus==1.15.0 diff --git a/testing/constraints-3.7.txt b/testing/constraints-3.7.txt new file mode 100644 index 00000000..e69de29b diff --git a/testing/constraints-3.8.txt b/testing/constraints-3.8.txt new file mode 100644 index 00000000..e69de29b diff --git a/testing/constraints-3.9.txt b/testing/constraints-3.9.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/gapic/vision_v1/__init__.py b/tests/unit/gapic/vision_v1/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/vision_v1/__init__.py +++ b/tests/unit/gapic/vision_v1/__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/vision_v1/test_image_annotator.py b/tests/unit/gapic/vision_v1/test_image_annotator.py index a14cf483..b1537280 100644 --- a/tests/unit/gapic/vision_v1/test_image_annotator.py +++ b/tests/unit/gapic/vision_v1/test_image_annotator.py @@ -90,15 +90,19 @@ def test__get_default_mtls_endpoint(): ) -def test_image_annotator_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [ImageAnnotatorClient, ImageAnnotatorAsyncClient,] +) +def test_image_annotator_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 = ImageAnnotatorClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "vision.googleapis.com:443" @@ -114,9 +118,11 @@ def test_image_annotator_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 == "vision.googleapis.com:443" @@ -477,6 +483,24 @@ def test_batch_annotate_images_from_dict(): test_batch_annotate_images(request_type=dict) +def test_batch_annotate_images_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_annotate_images), "__call__" + ) as call: + client.batch_annotate_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.BatchAnnotateImagesRequest() + + @pytest.mark.asyncio async def test_batch_annotate_images_async( transport: str = "grpc_asyncio", @@ -652,6 +676,24 @@ def test_batch_annotate_files_from_dict(): test_batch_annotate_files(request_type=dict) +def test_batch_annotate_files_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_annotate_files), "__call__" + ) as call: + client.batch_annotate_files() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.BatchAnnotateFilesRequest() + + @pytest.mark.asyncio async def test_batch_annotate_files_async( transport: str = "grpc_asyncio", @@ -839,6 +881,24 @@ def test_async_batch_annotate_images_from_dict(): test_async_batch_annotate_images(request_type=dict) +def test_async_batch_annotate_images_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.async_batch_annotate_images), "__call__" + ) as call: + client.async_batch_annotate_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.AsyncBatchAnnotateImagesRequest() + + @pytest.mark.asyncio async def test_async_batch_annotate_images_async( transport: str = "grpc_asyncio", @@ -1033,6 +1093,24 @@ def test_async_batch_annotate_files_from_dict(): test_async_batch_annotate_files(request_type=dict) +def test_async_batch_annotate_files_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.async_batch_annotate_files), "__call__" + ) as call: + client.async_batch_annotate_files() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.AsyncBatchAnnotateFilesRequest() + + @pytest.mark.asyncio async def test_async_batch_annotate_files_async( transport: str = "grpc_asyncio", diff --git a/tests/unit/gapic/vision_v1/test_product_search.py b/tests/unit/gapic/vision_v1/test_product_search.py index 2081be13..10fc690e 100644 --- a/tests/unit/gapic/vision_v1/test_product_search.py +++ b/tests/unit/gapic/vision_v1/test_product_search.py @@ -93,15 +93,19 @@ def test__get_default_mtls_endpoint(): ) -def test_product_search_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [ProductSearchClient, ProductSearchAsyncClient,] +) +def test_product_search_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 = ProductSearchClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "vision.googleapis.com:443" @@ -117,9 +121,11 @@ def test_product_search_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 == "vision.googleapis.com:443" @@ -486,6 +492,24 @@ def test_create_product_set_from_dict(): test_create_product_set(request_type=dict) +def test_create_product_set_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 = ProductSearchClient( + 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_product_set), "__call__" + ) as call: + client.create_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateProductSetRequest() + + @pytest.mark.asyncio async def test_create_product_set_async( transport: str = "grpc_asyncio", @@ -722,6 +746,24 @@ def test_list_product_sets_from_dict(): test_list_product_sets(request_type=dict) +def test_list_product_sets_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 = ProductSearchClient( + 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_product_sets), "__call__" + ) as call: + client.list_product_sets() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductSetsRequest() + + @pytest.mark.asyncio async def test_list_product_sets_async( transport: str = "grpc_asyncio", @@ -1100,6 +1142,22 @@ def test_get_product_set_from_dict(): test_get_product_set(request_type=dict) +def test_get_product_set_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 = ProductSearchClient( + 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_product_set), "__call__") as call: + client.get_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetProductSetRequest() + + @pytest.mark.asyncio async def test_get_product_set_async( transport: str = "grpc_asyncio", @@ -1302,6 +1360,24 @@ def test_update_product_set_from_dict(): test_update_product_set(request_type=dict) +def test_update_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_product_set), "__call__" + ) as call: + client.update_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.UpdateProductSetRequest() + + @pytest.mark.asyncio async def test_update_product_set_async( transport: str = "grpc_asyncio", @@ -1529,6 +1605,24 @@ def test_delete_product_set_from_dict(): test_delete_product_set(request_type=dict) +def test_delete_product_set_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 = ProductSearchClient( + 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_product_set), "__call__" + ) as call: + client.delete_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteProductSetRequest() + + @pytest.mark.asyncio async def test_delete_product_set_async( transport: str = "grpc_asyncio", @@ -1734,6 +1828,22 @@ def test_create_product_from_dict(): test_create_product(request_type=dict) +def test_create_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.create_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateProductRequest() + + @pytest.mark.asyncio async def test_create_product_async( transport: str = "grpc_asyncio", @@ -1961,6 +2071,22 @@ def test_list_products_from_dict(): test_list_products(request_type=dict) +def test_list_products_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 = ProductSearchClient( + 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_products), "__call__") as call: + client.list_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductsRequest() + + @pytest.mark.asyncio async def test_list_products_async( transport: str = "grpc_asyncio", @@ -2324,6 +2450,22 @@ def test_get_product_from_dict(): test_get_product(request_type=dict) +def test_get_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.get_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetProductRequest() + + @pytest.mark.asyncio async def test_get_product_async( transport: str = "grpc_asyncio", @@ -2538,6 +2680,22 @@ def test_update_product_from_dict(): test_update_product(request_type=dict) +def test_update_product_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_product), "__call__") as call: + client.update_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.UpdateProductRequest() + + @pytest.mark.asyncio async def test_update_product_async( transport: str = "grpc_asyncio", @@ -2756,6 +2914,22 @@ def test_delete_product_from_dict(): test_delete_product(request_type=dict) +def test_delete_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.delete_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteProductRequest() + + @pytest.mark.asyncio async def test_delete_product_async( transport: str = "grpc_asyncio", @@ -2947,6 +3121,24 @@ def test_create_reference_image_from_dict(): test_create_reference_image(request_type=dict) +def test_create_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.create_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateReferenceImageRequest() + + @pytest.mark.asyncio async def test_create_reference_image_async( transport: str = "grpc_asyncio", @@ -3177,6 +3369,24 @@ def test_delete_reference_image_from_dict(): test_delete_reference_image(request_type=dict) +def test_delete_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.delete_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteReferenceImageRequest() + + @pytest.mark.asyncio async def test_delete_reference_image_async( transport: str = "grpc_asyncio", @@ -3378,6 +3588,24 @@ def test_list_reference_images_from_dict(): test_list_reference_images(request_type=dict) +def test_list_reference_images_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 = ProductSearchClient( + 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_reference_images), "__call__" + ) as call: + client.list_reference_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListReferenceImagesRequest() + + @pytest.mark.asyncio async def test_list_reference_images_async( transport: str = "grpc_asyncio", @@ -3765,6 +3993,24 @@ def test_get_reference_image_from_dict(): test_get_reference_image(request_type=dict) +def test_get_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.get_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetReferenceImageRequest() + + @pytest.mark.asyncio async def test_get_reference_image_async( transport: str = "grpc_asyncio", @@ -3969,6 +4215,24 @@ def test_add_product_to_product_set_from_dict(): test_add_product_to_product_set(request_type=dict) +def test_add_product_to_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.add_product_to_product_set), "__call__" + ) as call: + client.add_product_to_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.AddProductToProductSetRequest() + + @pytest.mark.asyncio async def test_add_product_to_product_set_async( transport: str = "grpc_asyncio", @@ -4175,6 +4439,24 @@ def test_remove_product_from_product_set_from_dict(): test_remove_product_from_product_set(request_type=dict) +def test_remove_product_from_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.remove_product_from_product_set), "__call__" + ) as call: + client.remove_product_from_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.RemoveProductFromProductSetRequest() + + @pytest.mark.asyncio async def test_remove_product_from_product_set_async( transport: str = "grpc_asyncio", @@ -4386,6 +4668,24 @@ def test_list_products_in_product_set_from_dict(): test_list_products_in_product_set(request_type=dict) +def test_list_products_in_product_set_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 = ProductSearchClient( + 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_products_in_product_set), "__call__" + ) as call: + client.list_products_in_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductsInProductSetRequest() + + @pytest.mark.asyncio async def test_list_products_in_product_set_async( transport: str = "grpc_asyncio", @@ -4758,6 +5058,24 @@ def test_import_product_sets_from_dict(): test_import_product_sets(request_type=dict) +def test_import_product_sets_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.import_product_sets), "__call__" + ) as call: + client.import_product_sets() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ImportProductSetsRequest() + + @pytest.mark.asyncio async def test_import_product_sets_async( transport: str = "grpc_asyncio", @@ -4997,6 +5315,22 @@ def test_purge_products_from_dict(): test_purge_products(request_type=dict) +def test_purge_products_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.purge_products), "__call__") as call: + client.purge_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.PurgeProductsRequest() + + @pytest.mark.asyncio async def test_purge_products_async( transport: str = "grpc_asyncio", diff --git a/tests/unit/gapic/vision_v1p1beta1/__init__.py b/tests/unit/gapic/vision_v1p1beta1/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/vision_v1p1beta1/__init__.py +++ b/tests/unit/gapic/vision_v1p1beta1/__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/vision_v1p1beta1/test_image_annotator.py b/tests/unit/gapic/vision_v1p1beta1/test_image_annotator.py index d121bd2b..8f0d08ea 100644 --- a/tests/unit/gapic/vision_v1p1beta1/test_image_annotator.py +++ b/tests/unit/gapic/vision_v1p1beta1/test_image_annotator.py @@ -86,15 +86,19 @@ def test__get_default_mtls_endpoint(): ) -def test_image_annotator_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [ImageAnnotatorClient, ImageAnnotatorAsyncClient,] +) +def test_image_annotator_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 = ImageAnnotatorClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "vision.googleapis.com:443" @@ -110,9 +114,11 @@ def test_image_annotator_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 == "vision.googleapis.com:443" @@ -473,6 +479,24 @@ def test_batch_annotate_images_from_dict(): test_batch_annotate_images(request_type=dict) +def test_batch_annotate_images_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_annotate_images), "__call__" + ) as call: + client.batch_annotate_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.BatchAnnotateImagesRequest() + + @pytest.mark.asyncio async def test_batch_annotate_images_async( transport: str = "grpc_asyncio", diff --git a/tests/unit/gapic/vision_v1p2beta1/__init__.py b/tests/unit/gapic/vision_v1p2beta1/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/vision_v1p2beta1/__init__.py +++ b/tests/unit/gapic/vision_v1p2beta1/__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/vision_v1p2beta1/test_image_annotator.py b/tests/unit/gapic/vision_v1p2beta1/test_image_annotator.py index b3a8b01b..67edd39f 100644 --- a/tests/unit/gapic/vision_v1p2beta1/test_image_annotator.py +++ b/tests/unit/gapic/vision_v1p2beta1/test_image_annotator.py @@ -90,15 +90,19 @@ def test__get_default_mtls_endpoint(): ) -def test_image_annotator_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [ImageAnnotatorClient, ImageAnnotatorAsyncClient,] +) +def test_image_annotator_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 = ImageAnnotatorClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "vision.googleapis.com:443" @@ -114,9 +118,11 @@ def test_image_annotator_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 == "vision.googleapis.com:443" @@ -477,6 +483,24 @@ def test_batch_annotate_images_from_dict(): test_batch_annotate_images(request_type=dict) +def test_batch_annotate_images_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_annotate_images), "__call__" + ) as call: + client.batch_annotate_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.BatchAnnotateImagesRequest() + + @pytest.mark.asyncio async def test_batch_annotate_images_async( transport: str = "grpc_asyncio", @@ -651,6 +675,24 @@ def test_async_batch_annotate_files_from_dict(): test_async_batch_annotate_files(request_type=dict) +def test_async_batch_annotate_files_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.async_batch_annotate_files), "__call__" + ) as call: + client.async_batch_annotate_files() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.AsyncBatchAnnotateFilesRequest() + + @pytest.mark.asyncio async def test_async_batch_annotate_files_async( transport: str = "grpc_asyncio", diff --git a/tests/unit/gapic/vision_v1p3beta1/__init__.py b/tests/unit/gapic/vision_v1p3beta1/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/vision_v1p3beta1/__init__.py +++ b/tests/unit/gapic/vision_v1p3beta1/__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/vision_v1p3beta1/test_image_annotator.py b/tests/unit/gapic/vision_v1p3beta1/test_image_annotator.py index 522d9cdf..acf7e0d0 100644 --- a/tests/unit/gapic/vision_v1p3beta1/test_image_annotator.py +++ b/tests/unit/gapic/vision_v1p3beta1/test_image_annotator.py @@ -92,15 +92,19 @@ def test__get_default_mtls_endpoint(): ) -def test_image_annotator_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [ImageAnnotatorClient, ImageAnnotatorAsyncClient,] +) +def test_image_annotator_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 = ImageAnnotatorClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "vision.googleapis.com:443" @@ -116,9 +120,11 @@ def test_image_annotator_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 == "vision.googleapis.com:443" @@ -479,6 +485,24 @@ def test_batch_annotate_images_from_dict(): test_batch_annotate_images(request_type=dict) +def test_batch_annotate_images_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_annotate_images), "__call__" + ) as call: + client.batch_annotate_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.BatchAnnotateImagesRequest() + + @pytest.mark.asyncio async def test_batch_annotate_images_async( transport: str = "grpc_asyncio", @@ -653,6 +677,24 @@ def test_async_batch_annotate_files_from_dict(): test_async_batch_annotate_files(request_type=dict) +def test_async_batch_annotate_files_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.async_batch_annotate_files), "__call__" + ) as call: + client.async_batch_annotate_files() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.AsyncBatchAnnotateFilesRequest() + + @pytest.mark.asyncio async def test_async_batch_annotate_files_async( transport: str = "grpc_asyncio", diff --git a/tests/unit/gapic/vision_v1p3beta1/test_product_search.py b/tests/unit/gapic/vision_v1p3beta1/test_product_search.py index a6f4a49a..56180fce 100644 --- a/tests/unit/gapic/vision_v1p3beta1/test_product_search.py +++ b/tests/unit/gapic/vision_v1p3beta1/test_product_search.py @@ -95,15 +95,19 @@ def test__get_default_mtls_endpoint(): ) -def test_product_search_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [ProductSearchClient, ProductSearchAsyncClient,] +) +def test_product_search_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 = ProductSearchClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "vision.googleapis.com:443" @@ -119,9 +123,11 @@ def test_product_search_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 == "vision.googleapis.com:443" @@ -488,6 +494,24 @@ def test_create_product_set_from_dict(): test_create_product_set(request_type=dict) +def test_create_product_set_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 = ProductSearchClient( + 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_product_set), "__call__" + ) as call: + client.create_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateProductSetRequest() + + @pytest.mark.asyncio async def test_create_product_set_async( transport: str = "grpc_asyncio", @@ -724,6 +748,24 @@ def test_list_product_sets_from_dict(): test_list_product_sets(request_type=dict) +def test_list_product_sets_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 = ProductSearchClient( + 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_product_sets), "__call__" + ) as call: + client.list_product_sets() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductSetsRequest() + + @pytest.mark.asyncio async def test_list_product_sets_async( transport: str = "grpc_asyncio", @@ -1102,6 +1144,22 @@ def test_get_product_set_from_dict(): test_get_product_set(request_type=dict) +def test_get_product_set_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 = ProductSearchClient( + 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_product_set), "__call__") as call: + client.get_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetProductSetRequest() + + @pytest.mark.asyncio async def test_get_product_set_async( transport: str = "grpc_asyncio", @@ -1304,6 +1362,24 @@ def test_update_product_set_from_dict(): test_update_product_set(request_type=dict) +def test_update_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_product_set), "__call__" + ) as call: + client.update_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.UpdateProductSetRequest() + + @pytest.mark.asyncio async def test_update_product_set_async( transport: str = "grpc_asyncio", @@ -1531,6 +1607,24 @@ def test_delete_product_set_from_dict(): test_delete_product_set(request_type=dict) +def test_delete_product_set_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 = ProductSearchClient( + 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_product_set), "__call__" + ) as call: + client.delete_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteProductSetRequest() + + @pytest.mark.asyncio async def test_delete_product_set_async( transport: str = "grpc_asyncio", @@ -1736,6 +1830,22 @@ def test_create_product_from_dict(): test_create_product(request_type=dict) +def test_create_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.create_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateProductRequest() + + @pytest.mark.asyncio async def test_create_product_async( transport: str = "grpc_asyncio", @@ -1963,6 +2073,22 @@ def test_list_products_from_dict(): test_list_products(request_type=dict) +def test_list_products_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 = ProductSearchClient( + 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_products), "__call__") as call: + client.list_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductsRequest() + + @pytest.mark.asyncio async def test_list_products_async( transport: str = "grpc_asyncio", @@ -2326,6 +2452,22 @@ def test_get_product_from_dict(): test_get_product(request_type=dict) +def test_get_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.get_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetProductRequest() + + @pytest.mark.asyncio async def test_get_product_async( transport: str = "grpc_asyncio", @@ -2540,6 +2682,22 @@ def test_update_product_from_dict(): test_update_product(request_type=dict) +def test_update_product_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_product), "__call__") as call: + client.update_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.UpdateProductRequest() + + @pytest.mark.asyncio async def test_update_product_async( transport: str = "grpc_asyncio", @@ -2758,6 +2916,22 @@ def test_delete_product_from_dict(): test_delete_product(request_type=dict) +def test_delete_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.delete_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteProductRequest() + + @pytest.mark.asyncio async def test_delete_product_async( transport: str = "grpc_asyncio", @@ -2949,6 +3123,24 @@ def test_create_reference_image_from_dict(): test_create_reference_image(request_type=dict) +def test_create_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.create_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateReferenceImageRequest() + + @pytest.mark.asyncio async def test_create_reference_image_async( transport: str = "grpc_asyncio", @@ -3179,6 +3371,24 @@ def test_delete_reference_image_from_dict(): test_delete_reference_image(request_type=dict) +def test_delete_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.delete_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteReferenceImageRequest() + + @pytest.mark.asyncio async def test_delete_reference_image_async( transport: str = "grpc_asyncio", @@ -3380,6 +3590,24 @@ def test_list_reference_images_from_dict(): test_list_reference_images(request_type=dict) +def test_list_reference_images_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 = ProductSearchClient( + 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_reference_images), "__call__" + ) as call: + client.list_reference_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListReferenceImagesRequest() + + @pytest.mark.asyncio async def test_list_reference_images_async( transport: str = "grpc_asyncio", @@ -3767,6 +3995,24 @@ def test_get_reference_image_from_dict(): test_get_reference_image(request_type=dict) +def test_get_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.get_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetReferenceImageRequest() + + @pytest.mark.asyncio async def test_get_reference_image_async( transport: str = "grpc_asyncio", @@ -3971,6 +4217,24 @@ def test_add_product_to_product_set_from_dict(): test_add_product_to_product_set(request_type=dict) +def test_add_product_to_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.add_product_to_product_set), "__call__" + ) as call: + client.add_product_to_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.AddProductToProductSetRequest() + + @pytest.mark.asyncio async def test_add_product_to_product_set_async( transport: str = "grpc_asyncio", @@ -4177,6 +4441,24 @@ def test_remove_product_from_product_set_from_dict(): test_remove_product_from_product_set(request_type=dict) +def test_remove_product_from_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.remove_product_from_product_set), "__call__" + ) as call: + client.remove_product_from_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.RemoveProductFromProductSetRequest() + + @pytest.mark.asyncio async def test_remove_product_from_product_set_async( transport: str = "grpc_asyncio", @@ -4388,6 +4670,24 @@ def test_list_products_in_product_set_from_dict(): test_list_products_in_product_set(request_type=dict) +def test_list_products_in_product_set_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 = ProductSearchClient( + 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_products_in_product_set), "__call__" + ) as call: + client.list_products_in_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductsInProductSetRequest() + + @pytest.mark.asyncio async def test_list_products_in_product_set_async( transport: str = "grpc_asyncio", @@ -4760,6 +5060,24 @@ def test_import_product_sets_from_dict(): test_import_product_sets(request_type=dict) +def test_import_product_sets_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.import_product_sets), "__call__" + ) as call: + client.import_product_sets() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ImportProductSetsRequest() + + @pytest.mark.asyncio async def test_import_product_sets_async( transport: str = "grpc_asyncio", diff --git a/tests/unit/gapic/vision_v1p4beta1/__init__.py b/tests/unit/gapic/vision_v1p4beta1/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/vision_v1p4beta1/__init__.py +++ b/tests/unit/gapic/vision_v1p4beta1/__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/vision_v1p4beta1/test_image_annotator.py b/tests/unit/gapic/vision_v1p4beta1/test_image_annotator.py index 0582f419..4fda801f 100644 --- a/tests/unit/gapic/vision_v1p4beta1/test_image_annotator.py +++ b/tests/unit/gapic/vision_v1p4beta1/test_image_annotator.py @@ -93,15 +93,19 @@ def test__get_default_mtls_endpoint(): ) -def test_image_annotator_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [ImageAnnotatorClient, ImageAnnotatorAsyncClient,] +) +def test_image_annotator_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 = ImageAnnotatorClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "vision.googleapis.com:443" @@ -117,9 +121,11 @@ def test_image_annotator_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 == "vision.googleapis.com:443" @@ -480,6 +486,24 @@ def test_batch_annotate_images_from_dict(): test_batch_annotate_images(request_type=dict) +def test_batch_annotate_images_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_annotate_images), "__call__" + ) as call: + client.batch_annotate_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.BatchAnnotateImagesRequest() + + @pytest.mark.asyncio async def test_batch_annotate_images_async( transport: str = "grpc_asyncio", @@ -655,6 +679,24 @@ def test_batch_annotate_files_from_dict(): test_batch_annotate_files(request_type=dict) +def test_batch_annotate_files_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_annotate_files), "__call__" + ) as call: + client.batch_annotate_files() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.BatchAnnotateFilesRequest() + + @pytest.mark.asyncio async def test_batch_annotate_files_async( transport: str = "grpc_asyncio", @@ -842,6 +884,24 @@ def test_async_batch_annotate_images_from_dict(): test_async_batch_annotate_images(request_type=dict) +def test_async_batch_annotate_images_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.async_batch_annotate_images), "__call__" + ) as call: + client.async_batch_annotate_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.AsyncBatchAnnotateImagesRequest() + + @pytest.mark.asyncio async def test_async_batch_annotate_images_async( transport: str = "grpc_asyncio", @@ -1036,6 +1096,24 @@ def test_async_batch_annotate_files_from_dict(): test_async_batch_annotate_files(request_type=dict) +def test_async_batch_annotate_files_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 = ImageAnnotatorClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.async_batch_annotate_files), "__call__" + ) as call: + client.async_batch_annotate_files() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == image_annotator.AsyncBatchAnnotateFilesRequest() + + @pytest.mark.asyncio async def test_async_batch_annotate_files_async( transport: str = "grpc_asyncio", diff --git a/tests/unit/gapic/vision_v1p4beta1/test_product_search.py b/tests/unit/gapic/vision_v1p4beta1/test_product_search.py index 0b4abd53..b8418d77 100644 --- a/tests/unit/gapic/vision_v1p4beta1/test_product_search.py +++ b/tests/unit/gapic/vision_v1p4beta1/test_product_search.py @@ -95,15 +95,19 @@ def test__get_default_mtls_endpoint(): ) -def test_product_search_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [ProductSearchClient, ProductSearchAsyncClient,] +) +def test_product_search_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 = ProductSearchClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "vision.googleapis.com:443" @@ -119,9 +123,11 @@ def test_product_search_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 == "vision.googleapis.com:443" @@ -488,6 +494,24 @@ def test_create_product_set_from_dict(): test_create_product_set(request_type=dict) +def test_create_product_set_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 = ProductSearchClient( + 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_product_set), "__call__" + ) as call: + client.create_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateProductSetRequest() + + @pytest.mark.asyncio async def test_create_product_set_async( transport: str = "grpc_asyncio", @@ -724,6 +748,24 @@ def test_list_product_sets_from_dict(): test_list_product_sets(request_type=dict) +def test_list_product_sets_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 = ProductSearchClient( + 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_product_sets), "__call__" + ) as call: + client.list_product_sets() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductSetsRequest() + + @pytest.mark.asyncio async def test_list_product_sets_async( transport: str = "grpc_asyncio", @@ -1102,6 +1144,22 @@ def test_get_product_set_from_dict(): test_get_product_set(request_type=dict) +def test_get_product_set_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 = ProductSearchClient( + 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_product_set), "__call__") as call: + client.get_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetProductSetRequest() + + @pytest.mark.asyncio async def test_get_product_set_async( transport: str = "grpc_asyncio", @@ -1304,6 +1362,24 @@ def test_update_product_set_from_dict(): test_update_product_set(request_type=dict) +def test_update_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_product_set), "__call__" + ) as call: + client.update_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.UpdateProductSetRequest() + + @pytest.mark.asyncio async def test_update_product_set_async( transport: str = "grpc_asyncio", @@ -1531,6 +1607,24 @@ def test_delete_product_set_from_dict(): test_delete_product_set(request_type=dict) +def test_delete_product_set_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 = ProductSearchClient( + 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_product_set), "__call__" + ) as call: + client.delete_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteProductSetRequest() + + @pytest.mark.asyncio async def test_delete_product_set_async( transport: str = "grpc_asyncio", @@ -1736,6 +1830,22 @@ def test_create_product_from_dict(): test_create_product(request_type=dict) +def test_create_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.create_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateProductRequest() + + @pytest.mark.asyncio async def test_create_product_async( transport: str = "grpc_asyncio", @@ -1963,6 +2073,22 @@ def test_list_products_from_dict(): test_list_products(request_type=dict) +def test_list_products_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 = ProductSearchClient( + 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_products), "__call__") as call: + client.list_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductsRequest() + + @pytest.mark.asyncio async def test_list_products_async( transport: str = "grpc_asyncio", @@ -2326,6 +2452,22 @@ def test_get_product_from_dict(): test_get_product(request_type=dict) +def test_get_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.get_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetProductRequest() + + @pytest.mark.asyncio async def test_get_product_async( transport: str = "grpc_asyncio", @@ -2540,6 +2682,22 @@ def test_update_product_from_dict(): test_update_product(request_type=dict) +def test_update_product_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_product), "__call__") as call: + client.update_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.UpdateProductRequest() + + @pytest.mark.asyncio async def test_update_product_async( transport: str = "grpc_asyncio", @@ -2758,6 +2916,22 @@ def test_delete_product_from_dict(): test_delete_product(request_type=dict) +def test_delete_product_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 = ProductSearchClient( + 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_product), "__call__") as call: + client.delete_product() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteProductRequest() + + @pytest.mark.asyncio async def test_delete_product_async( transport: str = "grpc_asyncio", @@ -2949,6 +3123,24 @@ def test_create_reference_image_from_dict(): test_create_reference_image(request_type=dict) +def test_create_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.create_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.CreateReferenceImageRequest() + + @pytest.mark.asyncio async def test_create_reference_image_async( transport: str = "grpc_asyncio", @@ -3179,6 +3371,24 @@ def test_delete_reference_image_from_dict(): test_delete_reference_image(request_type=dict) +def test_delete_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.delete_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.DeleteReferenceImageRequest() + + @pytest.mark.asyncio async def test_delete_reference_image_async( transport: str = "grpc_asyncio", @@ -3380,6 +3590,24 @@ def test_list_reference_images_from_dict(): test_list_reference_images(request_type=dict) +def test_list_reference_images_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 = ProductSearchClient( + 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_reference_images), "__call__" + ) as call: + client.list_reference_images() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListReferenceImagesRequest() + + @pytest.mark.asyncio async def test_list_reference_images_async( transport: str = "grpc_asyncio", @@ -3767,6 +3995,24 @@ def test_get_reference_image_from_dict(): test_get_reference_image(request_type=dict) +def test_get_reference_image_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 = ProductSearchClient( + 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_reference_image), "__call__" + ) as call: + client.get_reference_image() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.GetReferenceImageRequest() + + @pytest.mark.asyncio async def test_get_reference_image_async( transport: str = "grpc_asyncio", @@ -3971,6 +4217,24 @@ def test_add_product_to_product_set_from_dict(): test_add_product_to_product_set(request_type=dict) +def test_add_product_to_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.add_product_to_product_set), "__call__" + ) as call: + client.add_product_to_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.AddProductToProductSetRequest() + + @pytest.mark.asyncio async def test_add_product_to_product_set_async( transport: str = "grpc_asyncio", @@ -4177,6 +4441,24 @@ def test_remove_product_from_product_set_from_dict(): test_remove_product_from_product_set(request_type=dict) +def test_remove_product_from_product_set_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.remove_product_from_product_set), "__call__" + ) as call: + client.remove_product_from_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.RemoveProductFromProductSetRequest() + + @pytest.mark.asyncio async def test_remove_product_from_product_set_async( transport: str = "grpc_asyncio", @@ -4388,6 +4670,24 @@ def test_list_products_in_product_set_from_dict(): test_list_products_in_product_set(request_type=dict) +def test_list_products_in_product_set_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 = ProductSearchClient( + 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_products_in_product_set), "__call__" + ) as call: + client.list_products_in_product_set() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ListProductsInProductSetRequest() + + @pytest.mark.asyncio async def test_list_products_in_product_set_async( transport: str = "grpc_asyncio", @@ -4760,6 +5060,24 @@ def test_import_product_sets_from_dict(): test_import_product_sets(request_type=dict) +def test_import_product_sets_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.import_product_sets), "__call__" + ) as call: + client.import_product_sets() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.ImportProductSetsRequest() + + @pytest.mark.asyncio async def test_import_product_sets_async( transport: str = "grpc_asyncio", @@ -4999,6 +5317,22 @@ def test_purge_products_from_dict(): test_purge_products(request_type=dict) +def test_purge_products_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 = ProductSearchClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.purge_products), "__call__") as call: + client.purge_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == product_search_service.PurgeProductsRequest() + + @pytest.mark.asyncio async def test_purge_products_async( transport: str = "grpc_asyncio",