diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml new file mode 100644 index 00000000..d49860b3 --- /dev/null +++ b/.github/.OwlBot.lock.yaml @@ -0,0 +1,4 @@ +docker: + digest: sha256:457583330eec64daa02aeb7a72a04d33e7be2428f646671ce4045dcbc0191b1e + image: gcr.io/repo-automation-bots/owlbot-python:latest + diff --git a/.github/.OwlBot.yaml b/.github/.OwlBot.yaml new file mode 100644 index 00000000..1c1dbd28 --- /dev/null +++ b/.github/.OwlBot.yaml @@ -0,0 +1,26 @@ +# 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 +# +# 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. + +docker: + image: gcr.io/repo-automation-bots/owlbot-python:latest + +deep-remove-regex: + - /owl-bot-staging + +deep-copy-regex: + - source: /google/devtools/cloudtrace/(v.*)/.*-py/(.*) + dest: /owl-bot-staging/$1/$2 + +begin-after-commit-hash: 6acf4a0a797f1082027985c55c4b14b60f673dd7 + diff --git a/.github/header-checker-lint.yml b/.github/header-checker-lint.yml index fc281c05..6fe78aa7 100644 --- a/.github/header-checker-lint.yml +++ b/.github/header-checker-lint.yml @@ -1,6 +1,6 @@ {"allowedCopyrightHolders": ["Google LLC"], "allowedLicenses": ["Apache-2.0", "MIT", "BSD-3"], - "ignoreFiles": ["**/requirements.txt", "**/requirements-test.txt"], + "ignoreFiles": ["**/requirements.txt", "**/requirements-test.txt", "**/__init__.py", "samples/**/constraints.txt", "samples/**/constraints-test.txt"], "sourceFileExtensions": [ "ts", "js", diff --git a/.kokoro/release.sh b/.kokoro/release.sh index 4d483e58..fb26d039 100755 --- a/.kokoro/release.sh +++ b/.kokoro/release.sh @@ -26,7 +26,7 @@ python3 -m pip install --upgrade twine wheel setuptools export PYTHONUNBUFFERED=1 # Move into the package, build the distribution and upload. -TWINE_PASSWORD=$(cat "${KOKORO_KEYSTORE_DIR}/73713_google_cloud_pypi_password") +TWINE_PASSWORD=$(cat "${KOKORO_GFILE_DIR}/secret_manager/google-cloud-pypi-token") cd github/python-trace python3 setup.py sdist bdist_wheel -twine upload --username gcloudpypi --password "${TWINE_PASSWORD}" dist/* +twine upload --username __token__ --password "${TWINE_PASSWORD}" dist/* diff --git a/.kokoro/release/common.cfg b/.kokoro/release/common.cfg index f1e287cb..abb72e4b 100644 --- a/.kokoro/release/common.cfg +++ b/.kokoro/release/common.cfg @@ -23,18 +23,8 @@ env_vars: { value: "github/python-trace/.kokoro/release.sh" } -# Fetch PyPI password -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "google_cloud_pypi_password" - } - } -} - # Tokens needed to report release status back to GitHub env_vars: { key: "SECRET_MANAGER_KEYS" - value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem" -} \ No newline at end of file + value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem,google-cloud-pypi-token" +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 32302e48..1bbd7878 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,17 @@ +# 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 +# +# 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. +# # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: @@ -12,6 +26,6 @@ repos: hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.0 + rev: 3.9.1 hooks: - id: flake8 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index dd8c5248..de8d1d22 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -160,21 +160,7 @@ Running System Tests auth settings and change some configuration in your project to run all the tests. -- System tests will be run against an actual project and - so you'll need to provide some environment variables to facilitate - authentication to your project: - - - ``GOOGLE_APPLICATION_CREDENTIALS``: The path to a JSON key file; - Such a file can be downloaded directly from the developer's console by clicking - "Generate new JSON key". See private key - `docs `__ - for more details. - -- Once you have downloaded your json keys, set the environment variable - ``GOOGLE_APPLICATION_CREDENTIALS`` to the absolute path of the json file:: - - $ export GOOGLE_APPLICATION_CREDENTIALS="/Users//path/to/app_credentials.json" - +- System tests will be run against an actual project. You should use local credentials from gcloud when possible. See `Best practices for application authentication `__. Some tests require a service account. For those tests see `Authenticating as a service account `__. ************* Test Coverage diff --git a/docs/_static/custom.css b/docs/_static/custom.css index bcd37bbd..b0a29546 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -1,9 +1,20 @@ div#python2-eol { border-color: red; border-width: medium; -} +} /* Ensure minimum width for 'Parameters' / 'Returns' column */ dl.field-list > dt { min-width: 100px } + +/* Insert space between methods for readability */ +dl.method { + padding-top: 10px; + padding-bottom: 10px +} + +/* Insert empty space between classes */ +dl.class { + padding-bottom: 50px +} diff --git a/docs/conf.py b/docs/conf.py index 9f3c1dd4..2f2c6c73 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,17 @@ # -*- coding: utf-8 -*- +# 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 +# +# 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. # # google-cloud-trace documentation build configuration file # diff --git a/docs/trace_v1/trace_service.rst b/docs/trace_v1/trace_service.rst index 14bcf291..af4cd4fc 100644 --- a/docs/trace_v1/trace_service.rst +++ b/docs/trace_v1/trace_service.rst @@ -5,7 +5,6 @@ TraceService :members: :inherited-members: - .. automodule:: google.cloud.trace_v1.services.trace_service.pagers :members: :inherited-members: diff --git a/google/cloud/trace/__init__.py b/google/cloud/trace/__init__.py index cf1a5c18..67332818 100644 --- a/google/cloud/trace/__init__.py +++ b/google/cloud/trace/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,10 +14,11 @@ # limitations under the License. # +from google.cloud.trace_v2.services.trace_service.client import TraceServiceClient from google.cloud.trace_v2.services.trace_service.async_client import ( TraceServiceAsyncClient, ) -from google.cloud.trace_v2.services.trace_service.client import TraceServiceClient + from google.cloud.trace_v2.types.trace import AttributeValue from google.cloud.trace_v2.types.trace import Module from google.cloud.trace_v2.types.trace import Span @@ -27,12 +27,12 @@ from google.cloud.trace_v2.types.tracing import BatchWriteSpansRequest __all__ = ( + "TraceServiceClient", + "TraceServiceAsyncClient", "AttributeValue", - "BatchWriteSpansRequest", "Module", "Span", "StackTrace", - "TraceServiceAsyncClient", - "TraceServiceClient", "TruncatableString", + "BatchWriteSpansRequest", ) diff --git a/google/cloud/trace_v1/__init__.py b/google/cloud/trace_v1/__init__.py index ff19d939..a42adf14 100644 --- a/google/cloud/trace_v1/__init__.py +++ b/google/cloud/trace_v1/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,22 +15,24 @@ # from .services.trace_service import TraceServiceClient +from .services.trace_service import TraceServiceAsyncClient + from .types.trace import GetTraceRequest from .types.trace import ListTracesRequest from .types.trace import ListTracesResponse from .types.trace import PatchTracesRequest from .types.trace import Trace -from .types.trace import TraceSpan from .types.trace import Traces - +from .types.trace import TraceSpan __all__ = ( + "TraceServiceAsyncClient", "GetTraceRequest", "ListTracesRequest", "ListTracesResponse", "PatchTracesRequest", "Trace", + "TraceServiceClient", "TraceSpan", "Traces", - "TraceServiceClient", ) diff --git a/google/cloud/trace_v1/gapic_metadata.json b/google/cloud/trace_v1/gapic_metadata.json new file mode 100644 index 00000000..49a3ad40 --- /dev/null +++ b/google/cloud/trace_v1/gapic_metadata.json @@ -0,0 +1,53 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.trace_v1", + "protoPackage": "google.devtools.cloudtrace.v1", + "schema": "1.0", + "services": { + "TraceService": { + "clients": { + "grpc": { + "libraryClient": "TraceServiceClient", + "rpcs": { + "GetTrace": { + "methods": [ + "get_trace" + ] + }, + "ListTraces": { + "methods": [ + "list_traces" + ] + }, + "PatchTraces": { + "methods": [ + "patch_traces" + ] + } + } + }, + "grpc-async": { + "libraryClient": "TraceServiceAsyncClient", + "rpcs": { + "GetTrace": { + "methods": [ + "get_trace" + ] + }, + "ListTraces": { + "methods": [ + "list_traces" + ] + }, + "PatchTraces": { + "methods": [ + "patch_traces" + ] + } + } + } + } + } + } +} diff --git a/google/cloud/trace_v1/services/__init__.py b/google/cloud/trace_v1/services/__init__.py index 42ffdf2b..4de65971 100644 --- a/google/cloud/trace_v1/services/__init__.py +++ b/google/cloud/trace_v1/services/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/google/cloud/trace_v1/services/trace_service/__init__.py b/google/cloud/trace_v1/services/trace_service/__init__.py index e06e796c..e3ea53d0 100644 --- a/google/cloud/trace_v1/services/trace_service/__init__.py +++ b/google/cloud/trace_v1/services/trace_service/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .client import TraceServiceClient from .async_client import TraceServiceAsyncClient diff --git a/google/cloud/trace_v1/services/trace_service/async_client.py b/google/cloud/trace_v1/services/trace_service/async_client.py index 64869c98..7004e379 100644 --- a/google/cloud/trace_v1/services/trace_service/async_client.py +++ b/google/cloud/trace_v1/services/trace_service/async_client.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict import functools import re @@ -22,15 +20,14 @@ import pkg_resources import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore from google.cloud.trace_v1.services.trace_service import pagers from google.cloud.trace_v1.types import trace - from .transports.base import TraceServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import TraceServiceGrpcAsyncIOTransport from .client import TraceServiceClient @@ -56,20 +53,16 @@ class TraceServiceAsyncClient: parse_common_billing_account_path = staticmethod( TraceServiceClient.parse_common_billing_account_path ) - common_folder_path = staticmethod(TraceServiceClient.common_folder_path) parse_common_folder_path = staticmethod(TraceServiceClient.parse_common_folder_path) - common_organization_path = staticmethod(TraceServiceClient.common_organization_path) parse_common_organization_path = staticmethod( TraceServiceClient.parse_common_organization_path ) - common_project_path = staticmethod(TraceServiceClient.common_project_path) parse_common_project_path = staticmethod( TraceServiceClient.parse_common_project_path ) - common_location_path = staticmethod(TraceServiceClient.common_location_path) parse_common_location_path = staticmethod( TraceServiceClient.parse_common_location_path @@ -77,7 +70,8 @@ class TraceServiceAsyncClient: @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials info. + """Creates an instance of this client using the provided credentials + info. Args: info (dict): The service account private key info. @@ -92,7 +86,7 @@ def from_service_account_info(cls, info: dict, *args, **kwargs): @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials - file. + file. Args: filename (str): The path to the service account private key json @@ -109,7 +103,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> TraceServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: TraceServiceTransport: The transport used by the client instance. @@ -123,12 +117,12 @@ def transport(self) -> TraceServiceTransport: def __init__( self, *, - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, transport: Union[str, TraceServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the trace service client. + """Instantiates the trace service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -160,7 +154,6 @@ def __init__( google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport creation failed for any reason. """ - self._client = TraceServiceClient( credentials=credentials, transport=transport, @@ -192,7 +185,6 @@ async def list_traces( This corresponds to the ``project_id`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -221,7 +213,6 @@ async def list_traces( # If we have keyword arguments corresponding to fields on the # request, apply these. - if project_id is not None: request.project_id = project_id @@ -234,7 +225,8 @@ async def list_traces( maximum=1.0, multiplier=1.2, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=45.0, ), @@ -282,7 +274,6 @@ async def get_trace( This corresponds to the ``trace_id`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -312,7 +303,6 @@ async def get_trace( # If we have keyword arguments corresponding to fields on the # request, apply these. - if project_id is not None: request.project_id = project_id if trace_id is not None: @@ -327,7 +317,8 @@ async def get_trace( maximum=1.0, multiplier=1.2, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=45.0, ), @@ -375,7 +366,6 @@ async def patch_traces( This corresponds to the ``traces`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -396,7 +386,6 @@ async def patch_traces( # If we have keyword arguments corresponding to fields on the # request, apply these. - if project_id is not None: request.project_id = project_id if traces is not None: @@ -411,7 +400,8 @@ async def patch_traces( maximum=1.0, multiplier=1.2, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=45.0, ), diff --git a/google/cloud/trace_v1/services/trace_service/client.py b/google/cloud/trace_v1/services/trace_service/client.py index 6e182a33..810df79a 100644 --- a/google/cloud/trace_v1/services/trace_service/client.py +++ b/google/cloud/trace_v1/services/trace_service/client.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict from distutils import util import os @@ -23,10 +21,10 @@ import pkg_resources from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore @@ -34,7 +32,6 @@ from google.cloud.trace_v1.services.trace_service import pagers from google.cloud.trace_v1.types import trace - from .transports.base import TraceServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import TraceServiceGrpcTransport from .transports.grpc_asyncio import TraceServiceGrpcAsyncIOTransport @@ -53,7 +50,7 @@ class TraceServiceClientMeta(type): _transport_registry["grpc_asyncio"] = TraceServiceGrpcAsyncIOTransport def get_transport_class(cls, label: str = None,) -> Type[TraceServiceTransport]: - """Return an appropriate transport class. + """Returns an appropriate transport class. Args: label: The name of the desired transport. If none is @@ -82,7 +79,8 @@ class TraceServiceClient(metaclass=TraceServiceClientMeta): @staticmethod def _get_default_mtls_endpoint(api_endpoint): - """Convert api endpoint to mTLS endpoint. + """Converts api endpoint to mTLS endpoint. + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. Args: @@ -116,7 +114,8 @@ def _get_default_mtls_endpoint(api_endpoint): @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials info. + """Creates an instance of this client using the provided credentials + info. Args: info (dict): The service account private key info. @@ -133,7 +132,7 @@ def from_service_account_info(cls, info: dict, *args, **kwargs): @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials - file. + file. Args: filename (str): The path to the service account private key json @@ -152,16 +151,17 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> TraceServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: - TraceServiceTransport: The transport used by the client instance. + TraceServiceTransport: The transport used by the client + instance. """ return self._transport @staticmethod def common_billing_account_path(billing_account: str,) -> str: - """Return a fully-qualified billing_account string.""" + """Returns a fully-qualified billing_account string.""" return "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -174,7 +174,7 @@ def parse_common_billing_account_path(path: str) -> Dict[str, str]: @staticmethod def common_folder_path(folder: str,) -> str: - """Return a fully-qualified folder string.""" + """Returns a fully-qualified folder string.""" return "folders/{folder}".format(folder=folder,) @staticmethod @@ -185,7 +185,7 @@ def parse_common_folder_path(path: str) -> Dict[str, str]: @staticmethod def common_organization_path(organization: str,) -> str: - """Return a fully-qualified organization string.""" + """Returns a fully-qualified organization string.""" return "organizations/{organization}".format(organization=organization,) @staticmethod @@ -196,7 +196,7 @@ def parse_common_organization_path(path: str) -> Dict[str, str]: @staticmethod def common_project_path(project: str,) -> str: - """Return a fully-qualified project string.""" + """Returns a fully-qualified project string.""" return "projects/{project}".format(project=project,) @staticmethod @@ -207,7 +207,7 @@ def parse_common_project_path(path: str) -> Dict[str, str]: @staticmethod def common_location_path(project: str, location: str,) -> str: - """Return a fully-qualified location string.""" + """Returns a fully-qualified location string.""" return "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -221,12 +221,12 @@ def parse_common_location_path(path: str) -> Dict[str, str]: def __init__( self, *, - credentials: Optional[credentials.Credentials] = None, + credentials: Optional[ga_credentials.Credentials] = None, transport: Union[str, TraceServiceTransport, None] = None, client_options: Optional[client_options_lib.ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the trace service client. + """Instantiates the trace service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -281,9 +281,10 @@ def __init__( client_cert_source_func = client_options.client_cert_source else: is_mtls = mtls.has_default_client_cert_source() - client_cert_source_func = ( - mtls.default_client_cert_source() if is_mtls else None - ) + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -295,12 +296,14 @@ def __init__( elif use_mtls_env == "always": api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT - ) + if is_mtls: + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = self.DEFAULT_ENDPOINT else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" ) # Save or instantiate the transport. @@ -315,8 +318,8 @@ def __init__( ) if client_options.scopes: raise ValueError( - "When providing a transport instance, " - "provide its scopes directly." + "When providing a transport instance, provide its scopes " + "directly." ) self._transport = transport else: @@ -355,7 +358,6 @@ def list_traces( This corresponds to the ``project_id`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -386,10 +388,8 @@ def list_traces( # there are no flattened fields. if not isinstance(request, trace.ListTracesRequest): request = trace.ListTracesRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if project_id is not None: request.project_id = project_id @@ -437,7 +437,6 @@ def get_trace( This corresponds to the ``trace_id`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -469,10 +468,8 @@ def get_trace( # there are no flattened fields. if not isinstance(request, trace.GetTraceRequest): request = trace.GetTraceRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if project_id is not None: request.project_id = project_id if trace_id is not None: @@ -522,7 +519,6 @@ def patch_traces( This corresponds to the ``traces`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -545,10 +541,8 @@ def patch_traces( # there are no flattened fields. if not isinstance(request, trace.PatchTracesRequest): request = trace.PatchTracesRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if project_id is not None: request.project_id = project_id if traces is not None: diff --git a/google/cloud/trace_v1/services/trace_service/pagers.py b/google/cloud/trace_v1/services/trace_service/pagers.py index ad600632..87ebec37 100644 --- a/google/cloud/trace_v1/services/trace_service/pagers.py +++ b/google/cloud/trace_v1/services/trace_service/pagers.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from typing import ( Any, AsyncIterable, @@ -117,7 +115,7 @@ def __init__( *, metadata: Sequence[Tuple[str, str]] = () ): - """Instantiate the pager. + """Instantiates the pager. Args: method (Callable): The method that was originally called, and diff --git a/google/cloud/trace_v1/services/trace_service/transports/__init__.py b/google/cloud/trace_v1/services/trace_service/transports/__init__.py index b860866b..952e4b26 100644 --- a/google/cloud/trace_v1/services/trace_service/transports/__init__.py +++ b/google/cloud/trace_v1/services/trace_service/transports/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict from typing import Dict, Type diff --git a/google/cloud/trace_v1/services/trace_service/transports/base.py b/google/cloud/trace_v1/services/trace_service/transports/base.py index 5557e905..74e5a610 100644 --- a/google/cloud/trace_v1/services/trace_service/transports/base.py +++ b/google/cloud/trace_v1/services/trace_service/transports/base.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,20 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import abc -import typing +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union +import packaging.version import pkg_resources -from google import auth # type: ignore -from google.api_core import exceptions # type: ignore +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.cloud.trace_v1.types import trace -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( @@ -36,6 +35,17 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() +try: + # google.auth.__version__ was added in 1.26.0 + _GOOGLE_AUTH_VERSION = google.auth.__version__ +except AttributeError: + try: # try pkg_resources if it is available + _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version + except pkg_resources.DistributionNotFound: # pragma: NO COVER + _GOOGLE_AUTH_VERSION = None + +_API_CORE_VERSION = google.api_core.__version__ + class TraceServiceTransport(abc.ABC): """Abstract transport class for TraceService.""" @@ -46,21 +56,24 @@ class TraceServiceTransport(abc.ABC): "https://www.googleapis.com/auth/trace.readonly", ) + DEFAULT_HOST: str = "cloudtrace.googleapis.com" + def __init__( self, *, - host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, - credentials_file: typing.Optional[str] = None, - scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, - quota_project_id: typing.Optional[str] = None, + host: str = DEFAULT_HOST, + credentials: ga_credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -69,7 +82,7 @@ def __init__( credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. This argument is mutually exclusive with credentials. - scope (Optional[Sequence[str]]): A list of scopes. + scopes (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): @@ -83,29 +96,76 @@ def __init__( host += ":443" self._host = host + scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + # 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: - raise exceptions.DuplicateCredentialArgs( + raise core_exceptions.DuplicateCredentialArgs( "'credentials_file' and 'credentials' are mutually exclusive" ) if credentials_file is not None: - credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=self._scopes, quota_project_id=quota_project_id + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id ) elif credentials is None: - credentials, _ = auth.default( - scopes=self._scopes, quota_project_id=quota_project_id + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials + # TODO(busunkim): These two class methods are in the base transport + # to avoid duplicating code across the transport classes. These functions + # should be deleted once the minimum required versions of google-api-core + # and google-auth are increased. + + # TODO: Remove this function once google-auth >= 1.25.0 is required + @classmethod + def _get_scopes_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Optional[Sequence[str]]]: + """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" + + scopes_kwargs = {} + + if _GOOGLE_AUTH_VERSION and ( + packaging.version.parse(_GOOGLE_AUTH_VERSION) + >= packaging.version.parse("1.25.0") + ): + scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} + else: + scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} + + return scopes_kwargs + + # TODO: Remove this function once google-api-core >= 1.26.0 is required + @classmethod + def _get_self_signed_jwt_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Union[Optional[Sequence[str]], str]]: + """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" + + self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} + + if _API_CORE_VERSION and ( + packaging.version.parse(_API_CORE_VERSION) + >= packaging.version.parse("1.26.0") + ): + self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES + self_signed_jwt_kwargs["scopes"] = scopes + self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST + else: + self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES + + return self_signed_jwt_kwargs + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -116,7 +176,8 @@ def _prep_wrapped_messages(self, client_info): maximum=1.0, multiplier=1.2, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=45.0, ), @@ -130,7 +191,8 @@ def _prep_wrapped_messages(self, client_info): maximum=1.0, multiplier=1.2, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=45.0, ), @@ -144,7 +206,8 @@ def _prep_wrapped_messages(self, client_info): maximum=1.0, multiplier=1.2, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=45.0, ), @@ -156,29 +219,23 @@ def _prep_wrapped_messages(self, client_info): @property def list_traces( self, - ) -> typing.Callable[ + ) -> Callable[ [trace.ListTracesRequest], - typing.Union[ - trace.ListTracesResponse, typing.Awaitable[trace.ListTracesResponse] - ], + Union[trace.ListTracesResponse, Awaitable[trace.ListTracesResponse]], ]: raise NotImplementedError() @property def get_trace( self, - ) -> typing.Callable[ - [trace.GetTraceRequest], - typing.Union[trace.Trace, typing.Awaitable[trace.Trace]], - ]: + ) -> Callable[[trace.GetTraceRequest], Union[trace.Trace, Awaitable[trace.Trace]]]: raise NotImplementedError() @property def patch_traces( self, - ) -> typing.Callable[ - [trace.PatchTracesRequest], - typing.Union[empty.Empty, typing.Awaitable[empty.Empty]], + ) -> Callable[ + [trace.PatchTracesRequest], Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]] ]: raise NotImplementedError() diff --git a/google/cloud/trace_v1/services/trace_service/transports/grpc.py b/google/cloud/trace_v1/services/trace_service/transports/grpc.py index f6c1a2dd..df75239d 100644 --- a/google/cloud/trace_v1/services/trace_service/transports/grpc.py +++ b/google/cloud/trace_v1/services/trace_service/transports/grpc.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,21 +13,19 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import warnings -from typing import Callable, Dict, Optional, Sequence, Tuple +from typing import Callable, Dict, Optional, Sequence, Tuple, Union from google.api_core import grpc_helpers # type: ignore from google.api_core import gapic_v1 # type: ignore -from google import auth # type: ignore -from google.auth import credentials # type: ignore +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore import grpc # type: ignore from google.cloud.trace_v1.types import trace -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore from .base import TraceServiceTransport, DEFAULT_CLIENT_INFO @@ -56,7 +53,7 @@ def __init__( self, *, host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Sequence[str] = None, channel: grpc.Channel = None, @@ -70,7 +67,8 @@ def __init__( """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -180,7 +178,7 @@ def __init__( def create_channel( cls, host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, @@ -211,13 +209,15 @@ def create_channel( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ - scopes = scopes or cls.AUTH_SCOPES + + self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) + return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, - scopes=scopes, quota_project_id=quota_project_id, + **self_signed_jwt_kwargs, **kwargs, ) @@ -279,7 +279,7 @@ def get_trace(self) -> Callable[[trace.GetTraceRequest], trace.Trace]: return self._stubs["get_trace"] @property - def patch_traces(self) -> Callable[[trace.PatchTracesRequest], empty.Empty]: + def patch_traces(self) -> Callable[[trace.PatchTracesRequest], empty_pb2.Empty]: r"""Return a callable for the patch traces method over gRPC. Sends new traces to Stackdriver Trace or updates @@ -304,7 +304,7 @@ def patch_traces(self) -> Callable[[trace.PatchTracesRequest], empty.Empty]: self._stubs["patch_traces"] = self.grpc_channel.unary_unary( "/google.devtools.cloudtrace.v1.TraceService/PatchTraces", request_serializer=trace.PatchTracesRequest.serialize, - response_deserializer=empty.Empty.FromString, + response_deserializer=empty_pb2.Empty.FromString, ) return self._stubs["patch_traces"] diff --git a/google/cloud/trace_v1/services/trace_service/transports/grpc_asyncio.py b/google/cloud/trace_v1/services/trace_service/transports/grpc_asyncio.py index 48963ead..6bc025e8 100644 --- a/google/cloud/trace_v1/services/trace_service/transports/grpc_asyncio.py +++ b/google/cloud/trace_v1/services/trace_service/transports/grpc_asyncio.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,22 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import warnings -from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore -from google import auth # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore +import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore from google.cloud.trace_v1.types import trace -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore from .base import TraceServiceTransport, DEFAULT_CLIENT_INFO from .grpc import TraceServiceGrpcTransport @@ -59,7 +56,7 @@ class TraceServiceGrpcAsyncIOTransport(TraceServiceTransport): def create_channel( cls, host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, @@ -86,13 +83,15 @@ def create_channel( Returns: aio.Channel: A gRPC AsyncIO channel object. """ - scopes = scopes or cls.AUTH_SCOPES + + self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) + return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, - scopes=scopes, quota_project_id=quota_project_id, + **self_signed_jwt_kwargs, **kwargs, ) @@ -100,7 +99,7 @@ def __init__( self, *, host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, channel: aio.Channel = None, @@ -114,7 +113,8 @@ def __init__( """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -172,7 +172,6 @@ def __init__( # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - else: if api_mtls_endpoint: host = api_mtls_endpoint @@ -285,7 +284,7 @@ def get_trace(self) -> Callable[[trace.GetTraceRequest], Awaitable[trace.Trace]] @property def patch_traces( self, - ) -> Callable[[trace.PatchTracesRequest], Awaitable[empty.Empty]]: + ) -> Callable[[trace.PatchTracesRequest], Awaitable[empty_pb2.Empty]]: r"""Return a callable for the patch traces method over gRPC. Sends new traces to Stackdriver Trace or updates @@ -310,7 +309,7 @@ def patch_traces( self._stubs["patch_traces"] = self.grpc_channel.unary_unary( "/google.devtools.cloudtrace.v1.TraceService/PatchTraces", request_serializer=trace.PatchTracesRequest.serialize, - response_deserializer=empty.Empty.FromString, + response_deserializer=empty_pb2.Empty.FromString, ) return self._stubs["patch_traces"] diff --git a/google/cloud/trace_v1/types/__init__.py b/google/cloud/trace_v1/types/__init__.py index 540e3e00..9bba2883 100644 --- a/google/cloud/trace_v1/types/__init__.py +++ b/google/cloud/trace_v1/types/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .trace import ( GetTraceRequest, ListTracesRequest, diff --git a/google/cloud/trace_v1/types/trace.py b/google/cloud/trace_v1/types/trace.py index 3e75d906..a9e232eb 100644 --- a/google/cloud/trace_v1/types/trace.py +++ b/google/cloud/trace_v1/types/trace.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,11 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - -from google.protobuf import timestamp_pb2 as timestamp # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore __protobuf__ = proto.module( @@ -52,16 +49,13 @@ class Trace(proto.Message): Collection of spans in the trace. """ - project_id = proto.Field(proto.STRING, number=1) - - trace_id = proto.Field(proto.STRING, number=2) - + project_id = proto.Field(proto.STRING, number=1,) + trace_id = proto.Field(proto.STRING, number=2,) spans = proto.RepeatedField(proto.MESSAGE, number=3, message="TraceSpan",) class Traces(proto.Message): r"""List of new or updated traces. - Attributes: traces (Sequence[google.cloud.trace_v1.types.Trace]): List of traces. @@ -153,19 +147,13 @@ class SpanKind(proto.Enum): RPC_SERVER = 1 RPC_CLIENT = 2 - span_id = proto.Field(proto.FIXED64, number=1) - + span_id = proto.Field(proto.FIXED64, number=1,) kind = proto.Field(proto.ENUM, number=2, enum=SpanKind,) - - name = proto.Field(proto.STRING, number=3) - - start_time = proto.Field(proto.MESSAGE, number=4, message=timestamp.Timestamp,) - - end_time = proto.Field(proto.MESSAGE, number=5, message=timestamp.Timestamp,) - - parent_span_id = proto.Field(proto.FIXED64, number=6) - - labels = proto.MapField(proto.STRING, proto.STRING, number=7) + name = proto.Field(proto.STRING, number=3,) + start_time = proto.Field(proto.MESSAGE, number=4, message=timestamp_pb2.Timestamp,) + end_time = proto.Field(proto.MESSAGE, number=5, message=timestamp_pb2.Timestamp,) + parent_span_id = proto.Field(proto.FIXED64, number=6,) + labels = proto.MapField(proto.STRING, proto.STRING, number=7,) class ListTracesRequest(proto.Message): @@ -254,26 +242,18 @@ class ViewType(proto.Enum): ROOTSPAN = 2 COMPLETE = 3 - project_id = proto.Field(proto.STRING, number=1) - + project_id = proto.Field(proto.STRING, number=1,) view = proto.Field(proto.ENUM, number=2, enum=ViewType,) - - page_size = proto.Field(proto.INT32, number=3) - - page_token = proto.Field(proto.STRING, number=4) - - start_time = proto.Field(proto.MESSAGE, number=5, message=timestamp.Timestamp,) - - end_time = proto.Field(proto.MESSAGE, number=6, message=timestamp.Timestamp,) - - filter = proto.Field(proto.STRING, number=7) - - order_by = proto.Field(proto.STRING, number=8) + page_size = proto.Field(proto.INT32, number=3,) + page_token = proto.Field(proto.STRING, number=4,) + start_time = proto.Field(proto.MESSAGE, number=5, message=timestamp_pb2.Timestamp,) + end_time = proto.Field(proto.MESSAGE, number=6, message=timestamp_pb2.Timestamp,) + filter = proto.Field(proto.STRING, number=7,) + order_by = proto.Field(proto.STRING, number=8,) class ListTracesResponse(proto.Message): r"""The response message for the ``ListTraces`` method. - Attributes: traces (Sequence[google.cloud.trace_v1.types.Trace]): List of trace records as specified by the @@ -290,13 +270,11 @@ def raw_page(self): return self traces = proto.RepeatedField(proto.MESSAGE, number=1, message="Trace",) - - next_page_token = proto.Field(proto.STRING, number=2) + next_page_token = proto.Field(proto.STRING, number=2,) class GetTraceRequest(proto.Message): r"""The request message for the ``GetTrace`` method. - Attributes: project_id (str): Required. ID of the Cloud project where the @@ -305,14 +283,12 @@ class GetTraceRequest(proto.Message): Required. ID of the trace to return. """ - project_id = proto.Field(proto.STRING, number=1) - - trace_id = proto.Field(proto.STRING, number=2) + project_id = proto.Field(proto.STRING, number=1,) + trace_id = proto.Field(proto.STRING, number=2,) class PatchTracesRequest(proto.Message): r"""The request message for the ``PatchTraces`` method. - Attributes: project_id (str): Required. ID of the Cloud project where the @@ -321,8 +297,7 @@ class PatchTracesRequest(proto.Message): Required. The body of the message. """ - project_id = proto.Field(proto.STRING, number=1) - + project_id = proto.Field(proto.STRING, number=1,) traces = proto.Field(proto.MESSAGE, number=2, message="Traces",) diff --git a/google/cloud/trace_v2/__init__.py b/google/cloud/trace_v2/__init__.py index 518583ba..126e6b56 100644 --- a/google/cloud/trace_v2/__init__.py +++ b/google/cloud/trace_v2/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +15,8 @@ # from .services.trace_service import TraceServiceClient +from .services.trace_service import TraceServiceAsyncClient + from .types.trace import AttributeValue from .types.trace import Module from .types.trace import Span @@ -23,13 +24,13 @@ from .types.trace import TruncatableString from .types.tracing import BatchWriteSpansRequest - __all__ = ( + "TraceServiceAsyncClient", "AttributeValue", "BatchWriteSpansRequest", "Module", "Span", "StackTrace", - "TruncatableString", "TraceServiceClient", + "TruncatableString", ) diff --git a/google/cloud/trace_v2/gapic_metadata.json b/google/cloud/trace_v2/gapic_metadata.json new file mode 100644 index 00000000..9b43f8b7 --- /dev/null +++ b/google/cloud/trace_v2/gapic_metadata.json @@ -0,0 +1,43 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.trace_v2", + "protoPackage": "google.devtools.cloudtrace.v2", + "schema": "1.0", + "services": { + "TraceService": { + "clients": { + "grpc": { + "libraryClient": "TraceServiceClient", + "rpcs": { + "BatchWriteSpans": { + "methods": [ + "batch_write_spans" + ] + }, + "CreateSpan": { + "methods": [ + "create_span" + ] + } + } + }, + "grpc-async": { + "libraryClient": "TraceServiceAsyncClient", + "rpcs": { + "BatchWriteSpans": { + "methods": [ + "batch_write_spans" + ] + }, + "CreateSpan": { + "methods": [ + "create_span" + ] + } + } + } + } + } + } +} diff --git a/google/cloud/trace_v2/services/__init__.py b/google/cloud/trace_v2/services/__init__.py index 42ffdf2b..4de65971 100644 --- a/google/cloud/trace_v2/services/__init__.py +++ b/google/cloud/trace_v2/services/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/google/cloud/trace_v2/services/trace_service/__init__.py b/google/cloud/trace_v2/services/trace_service/__init__.py index e06e796c..e3ea53d0 100644 --- a/google/cloud/trace_v2/services/trace_service/__init__.py +++ b/google/cloud/trace_v2/services/trace_service/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .client import TraceServiceClient from .async_client import TraceServiceAsyncClient diff --git a/google/cloud/trace_v2/services/trace_service/async_client.py b/google/cloud/trace_v2/services/trace_service/async_client.py index 16df441a..b9b377c6 100644 --- a/google/cloud/trace_v2/services/trace_service/async_client.py +++ b/google/cloud/trace_v2/services/trace_service/async_client.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict import functools import re @@ -22,18 +20,17 @@ import pkg_resources import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore from google.cloud.trace_v2.types import trace from google.cloud.trace_v2.types import tracing -from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from google.protobuf import wrappers_pb2 as wrappers # type: ignore -from google.rpc import status_pb2 as status # type: ignore - +from google.protobuf import timestamp_pb2 # type: ignore +from google.protobuf import wrappers_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore from .transports.base import TraceServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import TraceServiceGrpcAsyncIOTransport from .client import TraceServiceClient @@ -55,27 +52,22 @@ class TraceServiceAsyncClient: span_path = staticmethod(TraceServiceClient.span_path) parse_span_path = staticmethod(TraceServiceClient.parse_span_path) - common_billing_account_path = staticmethod( TraceServiceClient.common_billing_account_path ) parse_common_billing_account_path = staticmethod( TraceServiceClient.parse_common_billing_account_path ) - common_folder_path = staticmethod(TraceServiceClient.common_folder_path) parse_common_folder_path = staticmethod(TraceServiceClient.parse_common_folder_path) - common_organization_path = staticmethod(TraceServiceClient.common_organization_path) parse_common_organization_path = staticmethod( TraceServiceClient.parse_common_organization_path ) - common_project_path = staticmethod(TraceServiceClient.common_project_path) parse_common_project_path = staticmethod( TraceServiceClient.parse_common_project_path ) - common_location_path = staticmethod(TraceServiceClient.common_location_path) parse_common_location_path = staticmethod( TraceServiceClient.parse_common_location_path @@ -83,7 +75,8 @@ class TraceServiceAsyncClient: @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials info. + """Creates an instance of this client using the provided credentials + info. Args: info (dict): The service account private key info. @@ -98,7 +91,7 @@ def from_service_account_info(cls, info: dict, *args, **kwargs): @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials - file. + file. Args: filename (str): The path to the service account private key json @@ -115,7 +108,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> TraceServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: TraceServiceTransport: The transport used by the client instance. @@ -129,12 +122,12 @@ def transport(self) -> TraceServiceTransport: def __init__( self, *, - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, transport: Union[str, TraceServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the trace service client. + """Instantiates the trace service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -166,7 +159,6 @@ def __init__( google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport creation failed for any reason. """ - self._client = TraceServiceClient( credentials=credentials, transport=transport, @@ -206,7 +198,6 @@ async def batch_write_spans( This corresponds to the ``spans`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -227,10 +218,8 @@ async def batch_write_spans( # If we have keyword arguments corresponding to fields on the # request, apply these. - if name is not None: request.name = name - if spans: request.spans.extend(spans) @@ -273,7 +262,6 @@ async def create_span( spans, or none at all. Spans do not need to be contiguous—there may be gaps or overlaps between spans in a trace. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -295,7 +283,6 @@ async def create_span( """ # Create or coerce a protobuf request object. - request = trace.Span(request) # Wrap the RPC method; this adds retry and timeout information, @@ -307,7 +294,8 @@ async def create_span( maximum=1.0, multiplier=1.2, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=120.0, ), diff --git a/google/cloud/trace_v2/services/trace_service/client.py b/google/cloud/trace_v2/services/trace_service/client.py index 19758f21..4dcf60aa 100644 --- a/google/cloud/trace_v2/services/trace_service/client.py +++ b/google/cloud/trace_v2/services/trace_service/client.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict from distutils import util import os @@ -23,10 +21,10 @@ import pkg_resources from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore @@ -34,10 +32,9 @@ from google.cloud.trace_v2.types import trace from google.cloud.trace_v2.types import tracing -from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from google.protobuf import wrappers_pb2 as wrappers # type: ignore -from google.rpc import status_pb2 as status # type: ignore - +from google.protobuf import timestamp_pb2 # type: ignore +from google.protobuf import wrappers_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore from .transports.base import TraceServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import TraceServiceGrpcTransport from .transports.grpc_asyncio import TraceServiceGrpcAsyncIOTransport @@ -56,7 +53,7 @@ class TraceServiceClientMeta(type): _transport_registry["grpc_asyncio"] = TraceServiceGrpcAsyncIOTransport def get_transport_class(cls, label: str = None,) -> Type[TraceServiceTransport]: - """Return an appropriate transport class. + """Returns an appropriate transport class. Args: label: The name of the desired transport. If none is @@ -85,7 +82,8 @@ class TraceServiceClient(metaclass=TraceServiceClientMeta): @staticmethod def _get_default_mtls_endpoint(api_endpoint): - """Convert api endpoint to mTLS endpoint. + """Converts api endpoint to mTLS endpoint. + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. Args: @@ -119,7 +117,8 @@ def _get_default_mtls_endpoint(api_endpoint): @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials info. + """Creates an instance of this client using the provided credentials + info. Args: info (dict): The service account private key info. @@ -136,7 +135,7 @@ def from_service_account_info(cls, info: dict, *args, **kwargs): @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials - file. + file. Args: filename (str): The path to the service account private key json @@ -155,23 +154,24 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> TraceServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: - TraceServiceTransport: The transport used by the client instance. + TraceServiceTransport: The transport used by the client + instance. """ return self._transport @staticmethod def span_path(project: str, trace: str, span: str,) -> str: - """Return a fully-qualified span string.""" + """Returns a fully-qualified span string.""" return "projects/{project}/traces/{trace}/spans/{span}".format( project=project, trace=trace, span=span, ) @staticmethod def parse_span_path(path: str) -> Dict[str, str]: - """Parse a span path into its component segments.""" + """Parses a span path into its component segments.""" m = re.match( r"^projects/(?P.+?)/traces/(?P.+?)/spans/(?P.+?)$", path, @@ -180,7 +180,7 @@ def parse_span_path(path: str) -> Dict[str, str]: @staticmethod def common_billing_account_path(billing_account: str,) -> str: - """Return a fully-qualified billing_account string.""" + """Returns a fully-qualified billing_account string.""" return "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -193,7 +193,7 @@ def parse_common_billing_account_path(path: str) -> Dict[str, str]: @staticmethod def common_folder_path(folder: str,) -> str: - """Return a fully-qualified folder string.""" + """Returns a fully-qualified folder string.""" return "folders/{folder}".format(folder=folder,) @staticmethod @@ -204,7 +204,7 @@ def parse_common_folder_path(path: str) -> Dict[str, str]: @staticmethod def common_organization_path(organization: str,) -> str: - """Return a fully-qualified organization string.""" + """Returns a fully-qualified organization string.""" return "organizations/{organization}".format(organization=organization,) @staticmethod @@ -215,7 +215,7 @@ def parse_common_organization_path(path: str) -> Dict[str, str]: @staticmethod def common_project_path(project: str,) -> str: - """Return a fully-qualified project string.""" + """Returns a fully-qualified project string.""" return "projects/{project}".format(project=project,) @staticmethod @@ -226,7 +226,7 @@ def parse_common_project_path(path: str) -> Dict[str, str]: @staticmethod def common_location_path(project: str, location: str,) -> str: - """Return a fully-qualified location string.""" + """Returns a fully-qualified location string.""" return "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -240,12 +240,12 @@ def parse_common_location_path(path: str) -> Dict[str, str]: def __init__( self, *, - credentials: Optional[credentials.Credentials] = None, + credentials: Optional[ga_credentials.Credentials] = None, transport: Union[str, TraceServiceTransport, None] = None, client_options: Optional[client_options_lib.ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the trace service client. + """Instantiates the trace service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -300,9 +300,10 @@ def __init__( client_cert_source_func = client_options.client_cert_source else: is_mtls = mtls.has_default_client_cert_source() - client_cert_source_func = ( - mtls.default_client_cert_source() if is_mtls else None - ) + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -314,12 +315,14 @@ def __init__( elif use_mtls_env == "always": api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT - ) + if is_mtls: + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = self.DEFAULT_ENDPOINT else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" ) # Save or instantiate the transport. @@ -334,8 +337,8 @@ def __init__( ) if client_options.scopes: raise ValueError( - "When providing a transport instance, " - "provide its scopes directly." + "When providing a transport instance, provide its scopes " + "directly." ) self._transport = transport else: @@ -382,7 +385,6 @@ def batch_write_spans( This corresponds to the ``spans`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -405,10 +407,8 @@ def batch_write_spans( # there are no flattened fields. if not isinstance(request, tracing.BatchWriteSpansRequest): request = tracing.BatchWriteSpansRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if name is not None: request.name = name if spans is not None: @@ -449,7 +449,6 @@ def create_span( spans, or none at all. Spans do not need to be contiguous—there may be gaps or overlaps between spans in a trace. - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -471,7 +470,6 @@ def create_span( """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes # in a trace.Span. # There's no risk of modifying the input as we've already verified diff --git a/google/cloud/trace_v2/services/trace_service/transports/__init__.py b/google/cloud/trace_v2/services/trace_service/transports/__init__.py index b860866b..952e4b26 100644 --- a/google/cloud/trace_v2/services/trace_service/transports/__init__.py +++ b/google/cloud/trace_v2/services/trace_service/transports/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from collections import OrderedDict from typing import Dict, Type diff --git a/google/cloud/trace_v2/services/trace_service/transports/base.py b/google/cloud/trace_v2/services/trace_service/transports/base.py index 43951d62..7fe0617c 100644 --- a/google/cloud/trace_v2/services/trace_service/transports/base.py +++ b/google/cloud/trace_v2/services/trace_service/transports/base.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,21 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import abc -import typing +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union +import packaging.version import pkg_resources -from google import auth # type: ignore -from google.api_core import exceptions # type: ignore +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.cloud.trace_v2.types import trace from google.cloud.trace_v2.types import tracing -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( @@ -37,6 +36,17 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() +try: + # google.auth.__version__ was added in 1.26.0 + _GOOGLE_AUTH_VERSION = google.auth.__version__ +except AttributeError: + try: # try pkg_resources if it is available + _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version + except pkg_resources.DistributionNotFound: # pragma: NO COVER + _GOOGLE_AUTH_VERSION = None + +_API_CORE_VERSION = google.api_core.__version__ + class TraceServiceTransport(abc.ABC): """Abstract transport class for TraceService.""" @@ -46,21 +56,24 @@ class TraceServiceTransport(abc.ABC): "https://www.googleapis.com/auth/trace.append", ) + DEFAULT_HOST: str = "cloudtrace.googleapis.com" + def __init__( self, *, - host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, - credentials_file: typing.Optional[str] = None, - scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, - quota_project_id: typing.Optional[str] = None, + host: str = DEFAULT_HOST, + credentials: ga_credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -69,7 +82,7 @@ def __init__( credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. This argument is mutually exclusive with credentials. - scope (Optional[Sequence[str]]): A list of scopes. + scopes (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): @@ -83,29 +96,76 @@ def __init__( host += ":443" self._host = host + scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + # 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: - raise exceptions.DuplicateCredentialArgs( + raise core_exceptions.DuplicateCredentialArgs( "'credentials_file' and 'credentials' are mutually exclusive" ) if credentials_file is not None: - credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=self._scopes, quota_project_id=quota_project_id + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id ) elif credentials is None: - credentials, _ = auth.default( - scopes=self._scopes, quota_project_id=quota_project_id + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials + # TODO(busunkim): These two class methods are in the base transport + # to avoid duplicating code across the transport classes. These functions + # should be deleted once the minimum required versions of google-api-core + # and google-auth are increased. + + # TODO: Remove this function once google-auth >= 1.25.0 is required + @classmethod + def _get_scopes_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Optional[Sequence[str]]]: + """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" + + scopes_kwargs = {} + + if _GOOGLE_AUTH_VERSION and ( + packaging.version.parse(_GOOGLE_AUTH_VERSION) + >= packaging.version.parse("1.25.0") + ): + scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} + else: + scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} + + return scopes_kwargs + + # TODO: Remove this function once google-api-core >= 1.26.0 is required + @classmethod + def _get_self_signed_jwt_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Union[Optional[Sequence[str]], str]]: + """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" + + self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} + + if _API_CORE_VERSION and ( + packaging.version.parse(_API_CORE_VERSION) + >= packaging.version.parse("1.26.0") + ): + self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES + self_signed_jwt_kwargs["scopes"] = scopes + self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST + else: + self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES + + return self_signed_jwt_kwargs + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -119,7 +179,8 @@ def _prep_wrapped_messages(self, client_info): maximum=1.0, multiplier=1.2, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=120.0, ), @@ -131,18 +192,16 @@ def _prep_wrapped_messages(self, client_info): @property def batch_write_spans( self, - ) -> typing.Callable[ + ) -> Callable[ [tracing.BatchWriteSpansRequest], - typing.Union[empty.Empty, typing.Awaitable[empty.Empty]], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], ]: raise NotImplementedError() @property def create_span( self, - ) -> typing.Callable[ - [trace.Span], typing.Union[trace.Span, typing.Awaitable[trace.Span]] - ]: + ) -> Callable[[trace.Span], Union[trace.Span, Awaitable[trace.Span]]]: raise NotImplementedError() diff --git a/google/cloud/trace_v2/services/trace_service/transports/grpc.py b/google/cloud/trace_v2/services/trace_service/transports/grpc.py index 492b9562..5badc0f6 100644 --- a/google/cloud/trace_v2/services/trace_service/transports/grpc.py +++ b/google/cloud/trace_v2/services/trace_service/transports/grpc.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,22 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import warnings -from typing import Callable, Dict, Optional, Sequence, Tuple +from typing import Callable, Dict, Optional, Sequence, Tuple, Union from google.api_core import grpc_helpers # type: ignore from google.api_core import gapic_v1 # type: ignore -from google import auth # type: ignore -from google.auth import credentials # type: ignore +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore import grpc # type: ignore from google.cloud.trace_v2.types import trace from google.cloud.trace_v2.types import tracing -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore from .base import TraceServiceTransport, DEFAULT_CLIENT_INFO @@ -57,7 +54,7 @@ def __init__( self, *, host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Sequence[str] = None, channel: grpc.Channel = None, @@ -71,7 +68,8 @@ def __init__( """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -181,7 +179,7 @@ def __init__( def create_channel( cls, host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, @@ -212,13 +210,15 @@ def create_channel( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ - scopes = scopes or cls.AUTH_SCOPES + + self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) + return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, - scopes=scopes, quota_project_id=quota_project_id, + **self_signed_jwt_kwargs, **kwargs, ) @@ -231,7 +231,7 @@ def grpc_channel(self) -> grpc.Channel: @property def batch_write_spans( self, - ) -> Callable[[tracing.BatchWriteSpansRequest], empty.Empty]: + ) -> Callable[[tracing.BatchWriteSpansRequest], empty_pb2.Empty]: r"""Return a callable for the batch write spans method over gRPC. Sends new spans to new or existing traces. You cannot @@ -251,7 +251,7 @@ def batch_write_spans( self._stubs["batch_write_spans"] = self.grpc_channel.unary_unary( "/google.devtools.cloudtrace.v2.TraceService/BatchWriteSpans", request_serializer=tracing.BatchWriteSpansRequest.serialize, - response_deserializer=empty.Empty.FromString, + response_deserializer=empty_pb2.Empty.FromString, ) return self._stubs["batch_write_spans"] diff --git a/google/cloud/trace_v2/services/trace_service/transports/grpc_asyncio.py b/google/cloud/trace_v2/services/trace_service/transports/grpc_asyncio.py index b19e6cf1..63dfacd1 100644 --- a/google/cloud/trace_v2/services/trace_service/transports/grpc_asyncio.py +++ b/google/cloud/trace_v2/services/trace_service/transports/grpc_asyncio.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,23 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import warnings -from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore -from google import auth # type: ignore -from google.auth import credentials # type: ignore +from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore +import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore from google.cloud.trace_v2.types import trace from google.cloud.trace_v2.types import tracing -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore from .base import TraceServiceTransport, DEFAULT_CLIENT_INFO from .grpc import TraceServiceGrpcTransport @@ -60,7 +57,7 @@ class TraceServiceGrpcAsyncIOTransport(TraceServiceTransport): def create_channel( cls, host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, @@ -87,13 +84,15 @@ def create_channel( Returns: aio.Channel: A gRPC AsyncIO channel object. """ - scopes = scopes or cls.AUTH_SCOPES + + self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) + return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, - scopes=scopes, quota_project_id=quota_project_id, + **self_signed_jwt_kwargs, **kwargs, ) @@ -101,7 +100,7 @@ def __init__( self, *, host: str = "cloudtrace.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, channel: aio.Channel = None, @@ -115,7 +114,8 @@ def __init__( """Instantiate the transport. Args: - host (Optional[str]): The hostname to connect to. + host (Optional[str]): + The hostname to connect to. credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -173,7 +173,6 @@ def __init__( # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - else: if api_mtls_endpoint: host = api_mtls_endpoint @@ -235,7 +234,7 @@ def grpc_channel(self) -> aio.Channel: @property def batch_write_spans( self, - ) -> Callable[[tracing.BatchWriteSpansRequest], Awaitable[empty.Empty]]: + ) -> Callable[[tracing.BatchWriteSpansRequest], Awaitable[empty_pb2.Empty]]: r"""Return a callable for the batch write spans method over gRPC. Sends new spans to new or existing traces. You cannot @@ -255,7 +254,7 @@ def batch_write_spans( self._stubs["batch_write_spans"] = self.grpc_channel.unary_unary( "/google.devtools.cloudtrace.v2.TraceService/BatchWriteSpans", request_serializer=tracing.BatchWriteSpansRequest.serialize, - response_deserializer=empty.Empty.FromString, + response_deserializer=empty_pb2.Empty.FromString, ) return self._stubs["batch_write_spans"] diff --git a/google/cloud/trace_v2/types/__init__.py b/google/cloud/trace_v2/types/__init__.py index 27530d1f..0f28e15e 100644 --- a/google/cloud/trace_v2/types/__init__.py +++ b/google/cloud/trace_v2/types/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .trace import ( AttributeValue, Module, diff --git a/google/cloud/trace_v2/types/trace.py b/google/cloud/trace_v2/types/trace.py index 903d298c..db598507 100644 --- a/google/cloud/trace_v2/types/trace.py +++ b/google/cloud/trace_v2/types/trace.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,13 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - -from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from google.protobuf import wrappers_pb2 as wrappers # type: ignore -from google.rpc import status_pb2 as gr_status # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +from google.protobuf import wrappers_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore __protobuf__ = proto.module( @@ -128,7 +125,6 @@ class SpanKind(proto.Enum): class Attributes(proto.Message): r"""A set of attributes, each in the format ``[KEY]:[VALUE]``. - Attributes: attribute_map (Sequence[google.cloud.trace_v2.types.Span.Attributes.AttributeMapEntry]): The set of attributes. Each attribute's key can be up to 128 @@ -152,12 +148,10 @@ class Attributes(proto.Message): attribute_map = proto.MapField( proto.STRING, proto.MESSAGE, number=1, message="AttributeValue", ) - - dropped_attributes_count = proto.Field(proto.INT32, number=2) + dropped_attributes_count = proto.Field(proto.INT32, number=2,) class TimeEvent(proto.Message): r"""A time-stamped annotation or message event in the Span. - Attributes: time (google.protobuf.timestamp_pb2.Timestamp): The timestamp indicating the time the event @@ -171,7 +165,6 @@ class TimeEvent(proto.Message): class Annotation(proto.Message): r"""Text annotation with a set of attributes. - Attributes: description (google.cloud.trace_v2.types.TruncatableString): A user-supplied message describing the event. @@ -185,14 +178,12 @@ class Annotation(proto.Message): description = proto.Field( proto.MESSAGE, number=1, message="TruncatableString", ) - attributes = proto.Field( proto.MESSAGE, number=2, message="Span.Attributes", ) class MessageEvent(proto.Message): r"""An event describing a message sent/received between Spans. - Attributes: type (google.cloud.trace_v2.types.Span.TimeEvent.MessageEvent.Type): Type of MessageEvent. Indicates whether the @@ -220,19 +211,14 @@ class Type(proto.Enum): type = proto.Field( proto.ENUM, number=1, enum="Span.TimeEvent.MessageEvent.Type", ) + id = proto.Field(proto.INT64, number=2,) + uncompressed_size_bytes = proto.Field(proto.INT64, number=3,) + compressed_size_bytes = proto.Field(proto.INT64, number=4,) - id = proto.Field(proto.INT64, number=2) - - uncompressed_size_bytes = proto.Field(proto.INT64, number=3) - - compressed_size_bytes = proto.Field(proto.INT64, number=4) - - time = proto.Field(proto.MESSAGE, number=1, message=timestamp.Timestamp,) - + time = proto.Field(proto.MESSAGE, number=1, message=timestamp_pb2.Timestamp,) annotation = proto.Field( proto.MESSAGE, number=2, oneof="value", message="Span.TimeEvent.Annotation", ) - message_event = proto.Field( proto.MESSAGE, number=3, @@ -261,10 +247,8 @@ class TimeEvents(proto.Message): time_event = proto.RepeatedField( proto.MESSAGE, number=1, message="Span.TimeEvent", ) - - dropped_annotations_count = proto.Field(proto.INT32, number=2) - - dropped_message_events_count = proto.Field(proto.INT32, number=3) + dropped_annotations_count = proto.Field(proto.INT32, number=2,) + dropped_message_events_count = proto.Field(proto.INT32, number=3,) class Link(proto.Message): r"""A pointer from the current span to another span in the same @@ -294,12 +278,9 @@ class Type(proto.Enum): CHILD_LINKED_SPAN = 1 PARENT_LINKED_SPAN = 2 - trace_id = proto.Field(proto.STRING, number=1) - - span_id = proto.Field(proto.STRING, number=2) - + trace_id = proto.Field(proto.STRING, number=1,) + span_id = proto.Field(proto.STRING, number=2,) type = proto.Field(proto.ENUM, number=3, enum="Span.Link.Type",) - attributes = proto.Field(proto.MESSAGE, number=4, message="Span.Attributes",) class Links(proto.Message): @@ -316,45 +297,30 @@ class Links(proto.Message): """ link = proto.RepeatedField(proto.MESSAGE, number=1, message="Span.Link",) + dropped_links_count = proto.Field(proto.INT32, number=2,) - dropped_links_count = proto.Field(proto.INT32, number=2) - - name = proto.Field(proto.STRING, number=1) - - span_id = proto.Field(proto.STRING, number=2) - - parent_span_id = proto.Field(proto.STRING, number=3) - + name = proto.Field(proto.STRING, number=1,) + span_id = proto.Field(proto.STRING, number=2,) + parent_span_id = proto.Field(proto.STRING, number=3,) display_name = proto.Field(proto.MESSAGE, number=4, message="TruncatableString",) - - start_time = proto.Field(proto.MESSAGE, number=5, message=timestamp.Timestamp,) - - end_time = proto.Field(proto.MESSAGE, number=6, message=timestamp.Timestamp,) - + start_time = proto.Field(proto.MESSAGE, number=5, message=timestamp_pb2.Timestamp,) + end_time = proto.Field(proto.MESSAGE, number=6, message=timestamp_pb2.Timestamp,) attributes = proto.Field(proto.MESSAGE, number=7, message=Attributes,) - stack_trace = proto.Field(proto.MESSAGE, number=8, message="StackTrace",) - time_events = proto.Field(proto.MESSAGE, number=9, message=TimeEvents,) - links = proto.Field(proto.MESSAGE, number=10, message=Links,) - - status = proto.Field(proto.MESSAGE, number=11, message=gr_status.Status,) - + status = proto.Field(proto.MESSAGE, number=11, message=status_pb2.Status,) same_process_as_parent_span = proto.Field( - proto.MESSAGE, number=12, message=wrappers.BoolValue, + proto.MESSAGE, number=12, message=wrappers_pb2.BoolValue, ) - child_span_count = proto.Field( - proto.MESSAGE, number=13, message=wrappers.Int32Value, + proto.MESSAGE, number=13, message=wrappers_pb2.Int32Value, ) - span_kind = proto.Field(proto.ENUM, number=14, enum=SpanKind,) class AttributeValue(proto.Message): r"""The allowed types for [VALUE] in a ``[KEY]:[VALUE]`` attribute. - Attributes: string_value (google.cloud.trace_v2.types.TruncatableString): A string up to 256 bytes long. @@ -367,15 +333,12 @@ class AttributeValue(proto.Message): string_value = proto.Field( proto.MESSAGE, number=1, oneof="value", message="TruncatableString", ) - - int_value = proto.Field(proto.INT64, number=2, oneof="value") - - bool_value = proto.Field(proto.BOOL, number=3, oneof="value") + int_value = proto.Field(proto.INT64, number=2, oneof="value",) + bool_value = proto.Field(proto.BOOL, number=3, oneof="value",) class StackTrace(proto.Message): r"""A call stack appearing in a trace. - Attributes: stack_frames (google.cloud.trace_v2.types.StackTrace.StackFrames): Stack frames in this stack trace. A maximum @@ -394,7 +357,6 @@ class StackTrace(proto.Message): class StackFrame(proto.Message): r"""Represents a single stack frame in a stack trace. - Attributes: function_name (google.cloud.trace_v2.types.TruncatableString): The fully-qualified name that uniquely @@ -425,26 +387,19 @@ class StackFrame(proto.Message): function_name = proto.Field( proto.MESSAGE, number=1, message="TruncatableString", ) - original_function_name = proto.Field( proto.MESSAGE, number=2, message="TruncatableString", ) - file_name = proto.Field(proto.MESSAGE, number=3, message="TruncatableString",) - - line_number = proto.Field(proto.INT64, number=4) - - column_number = proto.Field(proto.INT64, number=5) - + line_number = proto.Field(proto.INT64, number=4,) + column_number = proto.Field(proto.INT64, number=5,) load_module = proto.Field(proto.MESSAGE, number=6, message="Module",) - source_version = proto.Field( proto.MESSAGE, number=7, message="TruncatableString", ) class StackFrames(proto.Message): r"""A collection of stack frames, which can be truncated. - Attributes: frame (Sequence[google.cloud.trace_v2.types.StackTrace.StackFrame]): Stack frames in this call stack. @@ -458,17 +413,14 @@ class StackFrames(proto.Message): frame = proto.RepeatedField( proto.MESSAGE, number=1, message="StackTrace.StackFrame", ) - - dropped_frames_count = proto.Field(proto.INT32, number=2) + dropped_frames_count = proto.Field(proto.INT32, number=2,) stack_frames = proto.Field(proto.MESSAGE, number=1, message=StackFrames,) - - stack_trace_hash_id = proto.Field(proto.INT64, number=2) + stack_trace_hash_id = proto.Field(proto.INT64, number=2,) class Module(proto.Message): r"""Binary module. - Attributes: module (google.cloud.trace_v2.types.TruncatableString): For example: main binary, kernel modules, and @@ -480,7 +432,6 @@ class Module(proto.Message): """ module = proto.Field(proto.MESSAGE, number=1, message="TruncatableString",) - build_id = proto.Field(proto.MESSAGE, number=2, message="TruncatableString",) @@ -505,9 +456,8 @@ class TruncatableString(proto.Message): not shortened. """ - value = proto.Field(proto.STRING, number=1) - - truncated_byte_count = proto.Field(proto.INT32, number=2) + value = proto.Field(proto.STRING, number=1,) + truncated_byte_count = proto.Field(proto.INT32, number=2,) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/trace_v2/types/tracing.py b/google/cloud/trace_v2/types/tracing.py index 57269d35..bead9f56 100644 --- a/google/cloud/trace_v2/types/tracing.py +++ b/google/cloud/trace_v2/types/tracing.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,10 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - from google.cloud.trace_v2.types import trace @@ -28,7 +25,6 @@ class BatchWriteSpansRequest(proto.Message): r"""The request message for the ``BatchWriteSpans`` method. - Attributes: name (str): Required. The name of the project where the spans belong. @@ -39,8 +35,7 @@ class BatchWriteSpansRequest(proto.Message): are undefined. """ - name = proto.Field(proto.STRING, number=1) - + name = proto.Field(proto.STRING, number=1,) spans = proto.RepeatedField(proto.MESSAGE, number=2, message=trace.Span,) diff --git a/noxfile.py b/noxfile.py index 4d37cd3a..70417e8c 100644 --- a/noxfile.py +++ b/noxfile.py @@ -62,16 +62,9 @@ def lint(session): session.run("flake8", "google", "tests") -@nox.session(python="3.6") +@nox.session(python=DEFAULT_PYTHON_VERSION) def blacken(session): - """Run black. - - Format code to uniform standard. - - This currently uses Python 3.6 due to the automated Kokoro run of synthtool. - That run uses an image that doesn't have 3.6 installed. Before updating this - check the state of the `gcp_ubuntu_config` we use for that Kokoro run. - """ + """Run black. Format code to uniform standard.""" session.install(BLACK_VERSION) session.run( "black", *BLACK_PATHS, @@ -131,9 +124,6 @@ def system(session): # Check the value of `RUN_SYSTEM_TESTS` env var. It defaults to true. if os.environ.get("RUN_SYSTEM_TESTS", "true") == "false": session.skip("RUN_SYSTEM_TESTS is set to false, skipping") - # 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") diff --git a/synth.py b/owlbot.py similarity index 64% rename from synth.py rename to owlbot.py index 87ac3b93..3d2d86eb 100644 --- a/synth.py +++ b/owlbot.py @@ -18,30 +18,21 @@ import synthtool as s import synthtool.gcp as gcp -gapic = gcp.GAPICBazel() common = gcp.CommonTemplates() -# ---------------------------------------------------------------------------- -# Generate trace GAPIC layer -# ---------------------------------------------------------------------------- -for version in ["v1", "v2"]: - library = gapic.py_library( - service="trace", - version=version, - bazel_target=f"//google/devtools/cloudtrace/{version}:devtools-cloudtrace-{version}-py", - proto_output_path=f"google/cloud/trace_{version}/proto", - include_protos=True, +default_version = "v2" + +for library in s.get_staging_dirs(default_version): + # Rename field `type_` to `type` in v1 and v2 to avoid breaking change + s.replace( + library / "google/**/types/*.py", + "type_", + "type" ) s.move(library, excludes=["docs/index.rst", "setup.py"]) - -# Rename field `type_` to `type` in v1 and v2 to avoid breaking change -s.replace( - "google/**/types/*.py", - "type_", - "type" -) +s.remove_staging_dirs() # ---------------------------------------------------------------------------- # Add templated files @@ -55,4 +46,4 @@ python.py_samples(skip_readmes=True) s.move(templated_files, excludes=[".coveragerc"]) # microgenerator has a good .coveragerc file -s.shell.run(["nox", "-s", "blacken"], hide_output=False) +s.shell.run(["nox", "-s", "blacken"], hide_output=False) \ No newline at end of file diff --git a/renovate.json b/renovate.json index f08bc22c..c0489556 100644 --- a/renovate.json +++ b/renovate.json @@ -2,5 +2,8 @@ "extends": [ "config:base", ":preserveSemverRanges" ], - "ignorePaths": [".pre-commit-config.yaml"] + "ignorePaths": [".pre-commit-config.yaml"], + "pip_requirements": { + "fileMatch": ["requirements-test.txt", "samples/[\\S/]*constraints.txt", "samples/[\\S/]*constraints-test.txt"] + } } diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index 97bf7da8..956cdf4f 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -172,10 +172,16 @@ def blacken(session: nox.sessions.Session) -> None: def _session_tests(session: nox.sessions.Session, post_install: Callable = None) -> None: """Runs py.test for a particular project.""" if os.path.exists("requirements.txt"): - session.install("-r", "requirements.txt") + if os.path.exists("constraints.txt"): + session.install("-r", "requirements.txt", "-c", "constraints.txt") + else: + session.install("-r", "requirements.txt") if os.path.exists("requirements-test.txt"): - session.install("-r", "requirements-test.txt") + if os.path.exists("constraints-test.txt"): + session.install("-r", "requirements-test.txt", "-c", "constraints-test.txt") + else: + session.install("-r", "requirements-test.txt") if INSTALL_LIBRARY_FROM_SOURCE: session.install("-e", _get_repo_root()) diff --git a/scripts/fixup_trace_v1_keywords.py b/scripts/fixup_trace_v1_keywords.py index 29536f6a..cb502c26 100644 --- a/scripts/fixup_trace_v1_keywords.py +++ b/scripts/fixup_trace_v1_keywords.py @@ -1,6 +1,5 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import argparse import os import libcst as cst @@ -41,10 +39,9 @@ def partition( class traceCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'get_trace': ('project_id', 'trace_id', ), - 'list_traces': ('project_id', 'view', 'page_size', 'page_token', 'start_time', 'end_time', 'filter', 'order_by', ), - 'patch_traces': ('project_id', 'traces', ), - + 'get_trace': ('project_id', 'trace_id', ), + 'list_traces': ('project_id', 'view', 'page_size', 'page_token', 'start_time', 'end_time', 'filter', 'order_by', ), + 'patch_traces': ('project_id', 'traces', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: @@ -75,7 +72,7 @@ def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: value=cst.Dict([ cst.DictElement( cst.SimpleString("'{}'".format(name)), - cst.Element(value=arg.value) +cst.Element(value=arg.value) ) # Note: the args + kwargs looks silly, but keep in mind that # the control parameters had to be stripped out, and that diff --git a/scripts/fixup_trace_v2_keywords.py b/scripts/fixup_trace_v2_keywords.py index ec15f7f3..f506a019 100644 --- a/scripts/fixup_trace_v2_keywords.py +++ b/scripts/fixup_trace_v2_keywords.py @@ -1,6 +1,5 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import argparse import os import libcst as cst @@ -41,9 +39,8 @@ def partition( class traceCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'batch_write_spans': ('name', 'spans', ), - 'create_span': ('name', 'span_id', 'display_name', 'start_time', 'end_time', 'parent_span_id', 'attributes', 'stack_trace', 'time_events', 'links', 'status', 'same_process_as_parent_span', 'child_span_count', 'span_kind', ), - + 'batch_write_spans': ('name', 'spans', ), + 'create_span': ('name', 'span_id', 'display_name', 'start_time', 'end_time', 'parent_span_id', 'attributes', 'stack_trace', 'time_events', 'links', 'status', 'same_process_as_parent_span', 'child_span_count', 'span_kind', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: @@ -74,7 +71,7 @@ def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: value=cst.Dict([ cst.DictElement( cst.SimpleString("'{}'".format(name)), - cst.Element(value=arg.value) +cst.Element(value=arg.value) ) # Note: the args + kwargs looks silly, but keep in mind that # the control parameters had to be stripped out, and that diff --git a/synth.metadata b/synth.metadata deleted file mode 100644 index ef817e01..00000000 --- a/synth.metadata +++ /dev/null @@ -1,45 +0,0 @@ -{ - "sources": [ - { - "git": { - "name": ".", - "remote": "git@github.com:googleapis/python-trace", - "sha": "1806034ea0beded6473de7d0938b92243d653c4f" - } - }, - { - "git": { - "name": "synthtool", - "remote": "https://github.com/googleapis/synthtool.git", - "sha": "ff39353f34a36e7643b86e97724e4027ab466dc6" - } - }, - { - "git": { - "name": "synthtool", - "remote": "https://github.com/googleapis/synthtool.git", - "sha": "ff39353f34a36e7643b86e97724e4027ab466dc6" - } - } - ], - "destinations": [ - { - "client": { - "source": "googleapis", - "apiName": "trace", - "apiVersion": "v1", - "language": "python", - "generator": "bazel" - } - }, - { - "client": { - "source": "googleapis", - "apiName": "trace", - "apiVersion": "v2", - "language": "python", - "generator": "bazel" - } - } - ] -} \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..4de65971 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,15 @@ +# -*- 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/__init__.py b/tests/unit/__init__.py new file mode 100644 index 00000000..4de65971 --- /dev/null +++ b/tests/unit/__init__.py @@ -0,0 +1,15 @@ +# -*- 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/__init__.py b/tests/unit/gapic/__init__.py new file mode 100644 index 00000000..4de65971 --- /dev/null +++ b/tests/unit/gapic/__init__.py @@ -0,0 +1,15 @@ +# -*- 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/trace_v1/__init__.py b/tests/unit/gapic/trace_v1/__init__.py index 42ffdf2b..4de65971 100644 --- a/tests/unit/gapic/trace_v1/__init__.py +++ b/tests/unit/gapic/trace_v1/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/tests/unit/gapic/trace_v1/test_trace_service.py b/tests/unit/gapic/trace_v1/test_trace_service.py index 779623d5..602c1ee4 100644 --- a/tests/unit/gapic/trace_v1/test_trace_service.py +++ b/tests/unit/gapic/trace_v1/test_trace_service.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import os import mock +import packaging.version import grpc from grpc.experimental import aio @@ -24,21 +23,51 @@ import pytest from proto.marshal.rules.dates import DurationRule, TimestampRule -from google import auth + from google.api_core import client_options -from google.api_core import exceptions +from google.api_core import exceptions as core_exceptions from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.auth import credentials +from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.trace_v1.services.trace_service import TraceServiceAsyncClient from google.cloud.trace_v1.services.trace_service import TraceServiceClient from google.cloud.trace_v1.services.trace_service import pagers from google.cloud.trace_v1.services.trace_service import transports +from google.cloud.trace_v1.services.trace_service.transports.base import ( + _API_CORE_VERSION, +) +from google.cloud.trace_v1.services.trace_service.transports.base import ( + _GOOGLE_AUTH_VERSION, +) from google.cloud.trace_v1.types import trace from google.oauth2 import service_account -from google.protobuf import timestamp_pb2 as timestamp # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +import google.auth + + +# TODO(busunkim): Once google-api-core >= 1.26.0 is required: +# - Delete all the api-core and auth "less than" test cases +# - Delete these pytest markers (Make the "greater than or equal to" tests the default). +requires_google_auth_lt_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), + reason="This test requires google-auth < 1.25.0", +) +requires_google_auth_gte_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), + reason="This test requires google-auth >= 1.25.0", +) + +requires_api_core_lt_1_26_0 = pytest.mark.skipif( + packaging.version.parse(_API_CORE_VERSION) >= packaging.version.parse("1.26.0"), + reason="This test requires google-api-core < 1.26.0", +) + +requires_api_core_gte_1_26_0 = pytest.mark.skipif( + packaging.version.parse(_API_CORE_VERSION) < packaging.version.parse("1.26.0"), + reason="This test requires google-api-core >= 1.26.0", +) def client_cert_source_callback(): @@ -84,7 +113,7 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize("client_class", [TraceServiceClient, TraceServiceAsyncClient,]) def test_trace_service_client_from_service_account_info(client_class): - creds = credentials.AnonymousCredentials() + creds = ga_credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_info" ) as factory: @@ -99,7 +128,7 @@ def test_trace_service_client_from_service_account_info(client_class): @pytest.mark.parametrize("client_class", [TraceServiceClient, TraceServiceAsyncClient,]) def test_trace_service_client_from_service_account_file(client_class): - creds = credentials.AnonymousCredentials() + creds = ga_credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_file" ) as factory: @@ -150,7 +179,7 @@ def test_trace_service_client_client_options( ): # Check that if channel is provided we won't create a new one. with mock.patch.object(TraceServiceClient, "get_transport_class") as gtc: - transport = transport_class(credentials=credentials.AnonymousCredentials()) + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) client = client_class(transport=transport) gtc.assert_not_called() @@ -432,7 +461,7 @@ def test_trace_service_client_client_options_from_dict(): def test_list_traces(transport: str = "grpc", request_type=trace.ListTracesRequest): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -445,19 +474,15 @@ def test_list_traces(transport: str = "grpc", request_type=trace.ListTracesReque call.return_value = trace.ListTracesResponse( next_page_token="next_page_token_value", ) - response = client.list_traces(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == trace.ListTracesRequest() # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListTracesPager) - assert response.next_page_token == "next_page_token_value" @@ -469,7 +494,7 @@ def test_list_traces_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 = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -477,7 +502,6 @@ def test_list_traces_empty_call(): client.list_traces() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == trace.ListTracesRequest() @@ -486,7 +510,7 @@ async def test_list_traces_async( transport: str = "grpc_asyncio", request_type=trace.ListTracesRequest ): client = TraceServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -499,18 +523,15 @@ async def test_list_traces_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( trace.ListTracesResponse(next_page_token="next_page_token_value",) ) - response = await client.list_traces(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == trace.ListTracesRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListTracesAsyncPager) - assert response.next_page_token == "next_page_token_value" @@ -520,13 +541,12 @@ async def test_list_traces_async_from_dict(): def test_list_traces_flattened(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_traces), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = trace.ListTracesResponse() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.list_traces(project_id="project_id_value",) @@ -535,12 +555,11 @@ def test_list_traces_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].project_id == "project_id_value" def test_list_traces_flattened_error(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -552,7 +571,7 @@ def test_list_traces_flattened_error(): @pytest.mark.asyncio async def test_list_traces_flattened_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_traces), "__call__") as call: @@ -570,13 +589,12 @@ async def test_list_traces_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].project_id == "project_id_value" @pytest.mark.asyncio async def test_list_traces_flattened_error_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -587,7 +605,7 @@ async def test_list_traces_flattened_error_async(): def test_list_traces_pager(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials,) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_traces), "__call__") as call: @@ -614,7 +632,7 @@ def test_list_traces_pager(): def test_list_traces_pages(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials,) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_traces), "__call__") as call: @@ -636,7 +654,7 @@ def test_list_traces_pages(): @pytest.mark.asyncio async def test_list_traces_async_pager(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -665,7 +683,7 @@ async def test_list_traces_async_pager(): @pytest.mark.asyncio async def test_list_traces_async_pages(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -691,7 +709,7 @@ async def test_list_traces_async_pages(): def test_get_trace(transport: str = "grpc", request_type=trace.GetTraceRequest): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -704,21 +722,16 @@ def test_get_trace(transport: str = "grpc", request_type=trace.GetTraceRequest): call.return_value = trace.Trace( project_id="project_id_value", trace_id="trace_id_value", ) - response = client.get_trace(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == trace.GetTraceRequest() # Establish that the response is the type that we expect. - assert isinstance(response, trace.Trace) - assert response.project_id == "project_id_value" - assert response.trace_id == "trace_id_value" @@ -730,7 +743,7 @@ def test_get_trace_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 = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -738,7 +751,6 @@ def test_get_trace_empty_call(): client.get_trace() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == trace.GetTraceRequest() @@ -747,7 +759,7 @@ async def test_get_trace_async( transport: str = "grpc_asyncio", request_type=trace.GetTraceRequest ): client = TraceServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -760,20 +772,16 @@ async def test_get_trace_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( trace.Trace(project_id="project_id_value", trace_id="trace_id_value",) ) - response = await client.get_trace(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == trace.GetTraceRequest() # Establish that the response is the type that we expect. assert isinstance(response, trace.Trace) - assert response.project_id == "project_id_value" - assert response.trace_id == "trace_id_value" @@ -783,13 +791,12 @@ async def test_get_trace_async_from_dict(): def test_get_trace_flattened(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_trace), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = trace.Trace() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.get_trace( @@ -800,14 +807,12 @@ def test_get_trace_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].project_id == "project_id_value" - assert args[0].trace_id == "trace_id_value" def test_get_trace_flattened_error(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -821,7 +826,7 @@ def test_get_trace_flattened_error(): @pytest.mark.asyncio async def test_get_trace_flattened_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_trace), "__call__") as call: @@ -839,15 +844,13 @@ async def test_get_trace_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].project_id == "project_id_value" - assert args[0].trace_id == "trace_id_value" @pytest.mark.asyncio async def test_get_trace_flattened_error_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -861,7 +864,7 @@ async def test_get_trace_flattened_error_async(): def test_patch_traces(transport: str = "grpc", request_type=trace.PatchTracesRequest): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -872,13 +875,11 @@ def test_patch_traces(transport: str = "grpc", request_type=trace.PatchTracesReq with mock.patch.object(type(client.transport.patch_traces), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = None - response = client.patch_traces(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == trace.PatchTracesRequest() # Establish that the response is the type that we expect. @@ -893,7 +894,7 @@ def test_patch_traces_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 = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -901,7 +902,6 @@ def test_patch_traces_empty_call(): client.patch_traces() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == trace.PatchTracesRequest() @@ -910,7 +910,7 @@ async def test_patch_traces_async( transport: str = "grpc_asyncio", request_type=trace.PatchTracesRequest ): client = TraceServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -921,13 +921,11 @@ async def test_patch_traces_async( with mock.patch.object(type(client.transport.patch_traces), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - response = await client.patch_traces(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == trace.PatchTracesRequest() # Establish that the response is the type that we expect. @@ -940,13 +938,12 @@ async def test_patch_traces_async_from_dict(): def test_patch_traces_flattened(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.patch_traces), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = None - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.patch_traces( @@ -958,16 +955,14 @@ def test_patch_traces_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].project_id == "project_id_value" - assert args[0].traces == trace.Traces( traces=[trace.Trace(project_id="project_id_value")] ) def test_patch_traces_flattened_error(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -981,7 +976,7 @@ def test_patch_traces_flattened_error(): @pytest.mark.asyncio async def test_patch_traces_flattened_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.patch_traces), "__call__") as call: @@ -1000,9 +995,7 @@ async def test_patch_traces_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].project_id == "project_id_value" - assert args[0].traces == trace.Traces( traces=[trace.Trace(project_id="project_id_value")] ) @@ -1010,7 +1003,7 @@ async def test_patch_traces_flattened_async(): @pytest.mark.asyncio async def test_patch_traces_flattened_error_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1025,16 +1018,16 @@ async def test_patch_traces_flattened_error_async(): def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # It is an error to provide a credentials file and a transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = TraceServiceClient( @@ -1044,7 +1037,7 @@ def test_credentials_transport_error(): # It is an error to provide scopes and a transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = TraceServiceClient( @@ -1055,7 +1048,7 @@ def test_credentials_transport_error(): def test_transport_instance(): # A client may be instantiated with a custom transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) client = TraceServiceClient(transport=transport) assert client.transport is transport @@ -1064,13 +1057,13 @@ def test_transport_instance(): def test_transport_get_channel(): # A client may be instantiated with a custom transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel transport = transports.TraceServiceGrpcAsyncIOTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel @@ -1085,23 +1078,23 @@ def test_transport_get_channel(): ) def test_transport_adc(transport_class): # Test default credentials are used if not provided. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport_class() adc.assert_called_once() def test_transport_grpc_default(): # A client should use the gRPC transport by default. - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) assert isinstance(client.transport, transports.TraceServiceGrpcTransport,) def test_trace_service_base_transport_error(): # Passing both a credentials object and credentials_file should raise an error - with pytest.raises(exceptions.DuplicateCredentialArgs): + with pytest.raises(core_exceptions.DuplicateCredentialArgs): transport = transports.TraceServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), credentials_file="credentials.json", ) @@ -1113,7 +1106,7 @@ def test_trace_service_base_transport(): ) as Transport: Transport.return_value = None transport = transports.TraceServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Every method on the transport should just blindly @@ -1128,15 +1121,41 @@ def test_trace_service_base_transport(): getattr(transport, method)(request=object()) +@requires_google_auth_gte_1_25_0 def test_trace_service_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( - auth, "load_credentials_from_file" + google.auth, "load_credentials_from_file", autospec=True ) as load_creds, mock.patch( "google.cloud.trace_v1.services.trace_service.transports.TraceServiceTransport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - load_creds.return_value = (credentials.AnonymousCredentials(), None) + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.TraceServiceTransport( + credentials_file="credentials.json", quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + "https://www.googleapis.com/auth/trace.readonly", + ), + quota_project_id="octopus", + ) + + +@requires_google_auth_lt_1_25_0 +def test_trace_service_base_transport_with_credentials_file_old_google_auth(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.trace_v1.services.trace_service.transports.TraceServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.TraceServiceTransport( credentials_file="credentials.json", quota_project_id="octopus", ) @@ -1153,19 +1172,37 @@ def test_trace_service_base_transport_with_credentials_file(): def test_trace_service_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. - with mock.patch.object(auth, "default") as adc, mock.patch( + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( "google.cloud.trace_v1.services.trace_service.transports.TraceServiceTransport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - adc.return_value = (credentials.AnonymousCredentials(), None) + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.TraceServiceTransport() adc.assert_called_once() +@requires_google_auth_gte_1_25_0 def test_trace_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + TraceServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + "https://www.googleapis.com/auth/trace.readonly", + ), + quota_project_id=None, + ) + + +@requires_google_auth_lt_1_25_0 +def test_trace_service_auth_adc_old_google_auth(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) TraceServiceClient() adc.assert_called_once_with( scopes=( @@ -1177,14 +1214,45 @@ def test_trace_service_auth_adc(): ) -def test_trace_service_transport_auth_adc(): +@pytest.mark.parametrize( + "transport_class", + [ + transports.TraceServiceGrpcTransport, + transports.TraceServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_gte_1_25_0 +def test_trace_service_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) - transports.TraceServiceGrpcTransport( - host="squid.clam.whelk", quota_project_id="octopus" + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + "https://www.googleapis.com/auth/trace.readonly", + ), + quota_project_id="octopus", ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.TraceServiceGrpcTransport, + transports.TraceServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_lt_1_25_0 +def test_trace_service_transport_auth_adc_old_google_auth(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus") adc.assert_called_once_with( scopes=( "https://www.googleapis.com/auth/cloud-platform", @@ -1195,12 +1263,129 @@ def test_trace_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.TraceServiceGrpcTransport, grpc_helpers), + (transports.TraceServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_gte_1_26_0 +def test_trace_service_transport_create_channel(transport_class, grpc_helpers): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "cloudtrace.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + "https://www.googleapis.com/auth/trace.readonly", + ), + scopes=["1", "2"], + default_host="cloudtrace.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.TraceServiceGrpcTransport, grpc_helpers), + (transports.TraceServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_trace_service_transport_create_channel_old_api_core( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus") + + create_channel.assert_called_with( + "cloudtrace.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + "https://www.googleapis.com/auth/trace.readonly", + ), + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.TraceServiceGrpcTransport, grpc_helpers), + (transports.TraceServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_trace_service_transport_create_channel_user_scopes( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "cloudtrace.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=["1", "2"], + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + @pytest.mark.parametrize( "transport_class", [transports.TraceServiceGrpcTransport, transports.TraceServiceGrpcAsyncIOTransport], ) def test_trace_service_grpc_transport_client_cert_source_for_mtls(transport_class): - cred = credentials.AnonymousCredentials() + cred = ga_credentials.AnonymousCredentials() # Check ssl_channel_credentials is used if provided. with mock.patch.object(transport_class, "create_channel") as mock_create_channel: @@ -1243,7 +1428,7 @@ def test_trace_service_grpc_transport_client_cert_source_for_mtls(transport_clas def test_trace_service_host_no_port(): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="cloudtrace.googleapis.com" ), @@ -1253,7 +1438,7 @@ def test_trace_service_host_no_port(): def test_trace_service_host_with_port(): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="cloudtrace.googleapis.com:8000" ), @@ -1304,9 +1489,9 @@ def test_trace_service_transport_channel_mtls_with_client_cert_source(transport_ mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel - cred = credentials.AnonymousCredentials() + cred = ga_credentials.AnonymousCredentials() with pytest.warns(DeprecationWarning): - with mock.patch.object(auth, "default") as adc: + with mock.patch.object(google.auth, "default") as adc: adc.return_value = (cred, None) transport = transport_class( host="squid.clam.whelk", @@ -1387,7 +1572,6 @@ def test_trace_service_transport_channel_mtls_with_adc(transport_class): def test_common_billing_account_path(): billing_account = "squid" - expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -1408,7 +1592,6 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): folder = "whelk" - expected = "folders/{folder}".format(folder=folder,) actual = TraceServiceClient.common_folder_path(folder) assert expected == actual @@ -1427,7 +1610,6 @@ def test_parse_common_folder_path(): def test_common_organization_path(): organization = "oyster" - expected = "organizations/{organization}".format(organization=organization,) actual = TraceServiceClient.common_organization_path(organization) assert expected == actual @@ -1446,7 +1628,6 @@ def test_parse_common_organization_path(): def test_common_project_path(): project = "cuttlefish" - expected = "projects/{project}".format(project=project,) actual = TraceServiceClient.common_project_path(project) assert expected == actual @@ -1466,7 +1647,6 @@ def test_parse_common_project_path(): def test_common_location_path(): project = "winkle" location = "nautilus" - expected = "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -1493,7 +1673,7 @@ def test_client_withDEFAULT_CLIENT_INFO(): transports.TraceServiceTransport, "_prep_wrapped_messages" ) as prep: client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) @@ -1502,6 +1682,6 @@ def test_client_withDEFAULT_CLIENT_INFO(): ) as prep: transport_class = TraceServiceClient.get_transport_class() transport = transport_class( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/trace_v2/__init__.py b/tests/unit/gapic/trace_v2/__init__.py index 42ffdf2b..4de65971 100644 --- a/tests/unit/gapic/trace_v2/__init__.py +++ b/tests/unit/gapic/trace_v2/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/tests/unit/gapic/trace_v2/test_trace_service.py b/tests/unit/gapic/trace_v2/test_trace_service.py index d25e90cc..81e985a6 100644 --- a/tests/unit/gapic/trace_v2/test_trace_service.py +++ b/tests/unit/gapic/trace_v2/test_trace_service.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import os import mock +import packaging.version import grpc from grpc.experimental import aio @@ -24,24 +23,54 @@ import pytest from proto.marshal.rules.dates import DurationRule, TimestampRule -from google import auth + from google.api_core import client_options -from google.api_core import exceptions +from google.api_core import exceptions as core_exceptions from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.auth import credentials +from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.trace_v2.services.trace_service import TraceServiceAsyncClient from google.cloud.trace_v2.services.trace_service import TraceServiceClient from google.cloud.trace_v2.services.trace_service import transports +from google.cloud.trace_v2.services.trace_service.transports.base import ( + _API_CORE_VERSION, +) +from google.cloud.trace_v2.services.trace_service.transports.base import ( + _GOOGLE_AUTH_VERSION, +) from google.cloud.trace_v2.types import trace from google.cloud.trace_v2.types import tracing from google.oauth2 import service_account -from google.protobuf import any_pb2 as gp_any # type: ignore -from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from google.protobuf import wrappers_pb2 as wrappers # type: ignore -from google.rpc import status_pb2 as status # type: ignore +from google.protobuf import any_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +from google.protobuf import wrappers_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +import google.auth + + +# TODO(busunkim): Once google-api-core >= 1.26.0 is required: +# - Delete all the api-core and auth "less than" test cases +# - Delete these pytest markers (Make the "greater than or equal to" tests the default). +requires_google_auth_lt_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), + reason="This test requires google-auth < 1.25.0", +) +requires_google_auth_gte_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), + reason="This test requires google-auth >= 1.25.0", +) + +requires_api_core_lt_1_26_0 = pytest.mark.skipif( + packaging.version.parse(_API_CORE_VERSION) >= packaging.version.parse("1.26.0"), + reason="This test requires google-api-core < 1.26.0", +) + +requires_api_core_gte_1_26_0 = pytest.mark.skipif( + packaging.version.parse(_API_CORE_VERSION) < packaging.version.parse("1.26.0"), + reason="This test requires google-api-core >= 1.26.0", +) def client_cert_source_callback(): @@ -87,7 +116,7 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize("client_class", [TraceServiceClient, TraceServiceAsyncClient,]) def test_trace_service_client_from_service_account_info(client_class): - creds = credentials.AnonymousCredentials() + creds = ga_credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_info" ) as factory: @@ -102,7 +131,7 @@ def test_trace_service_client_from_service_account_info(client_class): @pytest.mark.parametrize("client_class", [TraceServiceClient, TraceServiceAsyncClient,]) def test_trace_service_client_from_service_account_file(client_class): - creds = credentials.AnonymousCredentials() + creds = ga_credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_file" ) as factory: @@ -153,7 +182,7 @@ def test_trace_service_client_client_options( ): # Check that if channel is provided we won't create a new one. with mock.patch.object(TraceServiceClient, "get_transport_class") as gtc: - transport = transport_class(credentials=credentials.AnonymousCredentials()) + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) client = client_class(transport=transport) gtc.assert_not_called() @@ -437,7 +466,7 @@ def test_batch_write_spans( transport: str = "grpc", request_type=tracing.BatchWriteSpansRequest ): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -450,13 +479,11 @@ def test_batch_write_spans( ) as call: # Designate an appropriate return value for the call. call.return_value = None - response = client.batch_write_spans(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == tracing.BatchWriteSpansRequest() # Establish that the response is the type that we expect. @@ -471,7 +498,7 @@ def test_batch_write_spans_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 = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -481,7 +508,6 @@ def test_batch_write_spans_empty_call(): client.batch_write_spans() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == tracing.BatchWriteSpansRequest() @@ -490,7 +516,7 @@ async def test_batch_write_spans_async( transport: str = "grpc_asyncio", request_type=tracing.BatchWriteSpansRequest ): client = TraceServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -503,13 +529,11 @@ async def test_batch_write_spans_async( ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - response = await client.batch_write_spans(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == tracing.BatchWriteSpansRequest() # Establish that the response is the type that we expect. @@ -522,11 +546,12 @@ async def test_batch_write_spans_async_from_dict(): def test_batch_write_spans_field_headers(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. request = tracing.BatchWriteSpansRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. @@ -534,7 +559,6 @@ def test_batch_write_spans_field_headers(): type(client.transport.batch_write_spans), "__call__" ) as call: call.return_value = None - client.batch_write_spans(request) # Establish that the underlying gRPC stub method was called. @@ -549,11 +573,12 @@ def test_batch_write_spans_field_headers(): @pytest.mark.asyncio async def test_batch_write_spans_field_headers_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. request = tracing.BatchWriteSpansRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. @@ -561,7 +586,6 @@ async def test_batch_write_spans_field_headers_async(): type(client.transport.batch_write_spans), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - await client.batch_write_spans(request) # Establish that the underlying gRPC stub method was called. @@ -575,7 +599,7 @@ async def test_batch_write_spans_field_headers_async(): def test_batch_write_spans_flattened(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -583,7 +607,6 @@ def test_batch_write_spans_flattened(): ) as call: # Designate an appropriate return value for the call. call.return_value = None - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.batch_write_spans( @@ -594,14 +617,12 @@ def test_batch_write_spans_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].spans == [trace.Span(name="name_value")] def test_batch_write_spans_flattened_error(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -615,7 +636,7 @@ def test_batch_write_spans_flattened_error(): @pytest.mark.asyncio async def test_batch_write_spans_flattened_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -635,15 +656,13 @@ async def test_batch_write_spans_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].spans == [trace.Span(name="name_value")] @pytest.mark.asyncio async def test_batch_write_spans_flattened_error_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -657,7 +676,7 @@ async def test_batch_write_spans_flattened_error_async(): def test_create_span(transport: str = "grpc", request_type=trace.Span): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -673,25 +692,18 @@ def test_create_span(transport: str = "grpc", request_type=trace.Span): parent_span_id="parent_span_id_value", span_kind=trace.Span.SpanKind.INTERNAL, ) - response = client.create_span(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == trace.Span() # Establish that the response is the type that we expect. - assert isinstance(response, trace.Span) - assert response.name == "name_value" - assert response.span_id == "span_id_value" - assert response.parent_span_id == "parent_span_id_value" - assert response.span_kind == trace.Span.SpanKind.INTERNAL @@ -703,7 +715,7 @@ def test_create_span_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 = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -711,7 +723,6 @@ def test_create_span_empty_call(): client.create_span() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == trace.Span() @@ -720,7 +731,7 @@ async def test_create_span_async( transport: str = "grpc_asyncio", request_type=trace.Span ): client = TraceServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -738,24 +749,18 @@ async def test_create_span_async( span_kind=trace.Span.SpanKind.INTERNAL, ) ) - response = await client.create_span(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == trace.Span() # Establish that the response is the type that we expect. assert isinstance(response, trace.Span) - assert response.name == "name_value" - assert response.span_id == "span_id_value" - assert response.parent_span_id == "parent_span_id_value" - assert response.span_kind == trace.Span.SpanKind.INTERNAL @@ -765,17 +770,17 @@ async def test_create_span_async_from_dict(): def test_create_span_field_headers(): - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. request = trace.Span() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_span), "__call__") as call: call.return_value = trace.Span() - client.create_span(request) # Establish that the underlying gRPC stub method was called. @@ -790,17 +795,17 @@ def test_create_span_field_headers(): @pytest.mark.asyncio async def test_create_span_field_headers_async(): - client = TraceServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. request = trace.Span() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_span), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(trace.Span()) - await client.create_span(request) # Establish that the underlying gRPC stub method was called. @@ -816,16 +821,16 @@ async def test_create_span_field_headers_async(): def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # It is an error to provide a credentials file and a transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = TraceServiceClient( @@ -835,7 +840,7 @@ def test_credentials_transport_error(): # It is an error to provide scopes and a transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = TraceServiceClient( @@ -846,7 +851,7 @@ def test_credentials_transport_error(): def test_transport_instance(): # A client may be instantiated with a custom transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) client = TraceServiceClient(transport=transport) assert client.transport is transport @@ -855,13 +860,13 @@ def test_transport_instance(): def test_transport_get_channel(): # A client may be instantiated with a custom transport instance. transport = transports.TraceServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel transport = transports.TraceServiceGrpcAsyncIOTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel @@ -876,23 +881,23 @@ def test_transport_get_channel(): ) def test_transport_adc(transport_class): # Test default credentials are used if not provided. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport_class() adc.assert_called_once() def test_transport_grpc_default(): # A client should use the gRPC transport by default. - client = TraceServiceClient(credentials=credentials.AnonymousCredentials(),) + client = TraceServiceClient(credentials=ga_credentials.AnonymousCredentials(),) assert isinstance(client.transport, transports.TraceServiceGrpcTransport,) def test_trace_service_base_transport_error(): # Passing both a credentials object and credentials_file should raise an error - with pytest.raises(exceptions.DuplicateCredentialArgs): + with pytest.raises(core_exceptions.DuplicateCredentialArgs): transport = transports.TraceServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), credentials_file="credentials.json", ) @@ -904,7 +909,7 @@ def test_trace_service_base_transport(): ) as Transport: Transport.return_value = None transport = transports.TraceServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Every method on the transport should just blindly @@ -918,15 +923,40 @@ def test_trace_service_base_transport(): getattr(transport, method)(request=object()) +@requires_google_auth_gte_1_25_0 def test_trace_service_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( - auth, "load_credentials_from_file" + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.trace_v2.services.trace_service.transports.TraceServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.TraceServiceTransport( + credentials_file="credentials.json", quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + ), + quota_project_id="octopus", + ) + + +@requires_google_auth_lt_1_25_0 +def test_trace_service_base_transport_with_credentials_file_old_google_auth(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True ) as load_creds, mock.patch( "google.cloud.trace_v2.services.trace_service.transports.TraceServiceTransport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - load_creds.return_value = (credentials.AnonymousCredentials(), None) + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.TraceServiceTransport( credentials_file="credentials.json", quota_project_id="octopus", ) @@ -942,19 +972,36 @@ def test_trace_service_base_transport_with_credentials_file(): def test_trace_service_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. - with mock.patch.object(auth, "default") as adc, mock.patch( + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( "google.cloud.trace_v2.services.trace_service.transports.TraceServiceTransport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - adc.return_value = (credentials.AnonymousCredentials(), None) + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.TraceServiceTransport() adc.assert_called_once() +@requires_google_auth_gte_1_25_0 def test_trace_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + TraceServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + ), + quota_project_id=None, + ) + + +@requires_google_auth_lt_1_25_0 +def test_trace_service_auth_adc_old_google_auth(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) TraceServiceClient() adc.assert_called_once_with( scopes=( @@ -965,14 +1012,44 @@ def test_trace_service_auth_adc(): ) -def test_trace_service_transport_auth_adc(): +@pytest.mark.parametrize( + "transport_class", + [ + transports.TraceServiceGrpcTransport, + transports.TraceServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_gte_1_25_0 +def test_trace_service_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. - with mock.patch.object(auth, "default") as adc: - adc.return_value = (credentials.AnonymousCredentials(), None) - transports.TraceServiceGrpcTransport( - host="squid.clam.whelk", quota_project_id="octopus" + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + ), + quota_project_id="octopus", ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.TraceServiceGrpcTransport, + transports.TraceServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_lt_1_25_0 +def test_trace_service_transport_auth_adc_old_google_auth(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus") adc.assert_called_once_with( scopes=( "https://www.googleapis.com/auth/cloud-platform", @@ -982,12 +1059,127 @@ def test_trace_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.TraceServiceGrpcTransport, grpc_helpers), + (transports.TraceServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_gte_1_26_0 +def test_trace_service_transport_create_channel(transport_class, grpc_helpers): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "cloudtrace.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + ), + scopes=["1", "2"], + default_host="cloudtrace.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.TraceServiceGrpcTransport, grpc_helpers), + (transports.TraceServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_trace_service_transport_create_channel_old_api_core( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus") + + create_channel.assert_called_with( + "cloudtrace.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/trace.append", + ), + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.TraceServiceGrpcTransport, grpc_helpers), + (transports.TraceServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_trace_service_transport_create_channel_user_scopes( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "cloudtrace.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=["1", "2"], + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + @pytest.mark.parametrize( "transport_class", [transports.TraceServiceGrpcTransport, transports.TraceServiceGrpcAsyncIOTransport], ) def test_trace_service_grpc_transport_client_cert_source_for_mtls(transport_class): - cred = credentials.AnonymousCredentials() + cred = ga_credentials.AnonymousCredentials() # Check ssl_channel_credentials is used if provided. with mock.patch.object(transport_class, "create_channel") as mock_create_channel: @@ -1029,7 +1221,7 @@ def test_trace_service_grpc_transport_client_cert_source_for_mtls(transport_clas def test_trace_service_host_no_port(): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="cloudtrace.googleapis.com" ), @@ -1039,7 +1231,7 @@ def test_trace_service_host_no_port(): def test_trace_service_host_with_port(): client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="cloudtrace.googleapis.com:8000" ), @@ -1090,9 +1282,9 @@ def test_trace_service_transport_channel_mtls_with_client_cert_source(transport_ mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel - cred = credentials.AnonymousCredentials() + cred = ga_credentials.AnonymousCredentials() with pytest.warns(DeprecationWarning): - with mock.patch.object(auth, "default") as adc: + with mock.patch.object(google.auth, "default") as adc: adc.return_value = (cred, None) transport = transport_class( host="squid.clam.whelk", @@ -1173,7 +1365,6 @@ def test_span_path(): project = "squid" trace = "clam" span = "whelk" - expected = "projects/{project}/traces/{trace}/spans/{span}".format( project=project, trace=trace, span=span, ) @@ -1196,7 +1387,6 @@ def test_parse_span_path(): def test_common_billing_account_path(): billing_account = "cuttlefish" - expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -1217,7 +1407,6 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): folder = "winkle" - expected = "folders/{folder}".format(folder=folder,) actual = TraceServiceClient.common_folder_path(folder) assert expected == actual @@ -1236,7 +1425,6 @@ def test_parse_common_folder_path(): def test_common_organization_path(): organization = "scallop" - expected = "organizations/{organization}".format(organization=organization,) actual = TraceServiceClient.common_organization_path(organization) assert expected == actual @@ -1255,7 +1443,6 @@ def test_parse_common_organization_path(): def test_common_project_path(): project = "squid" - expected = "projects/{project}".format(project=project,) actual = TraceServiceClient.common_project_path(project) assert expected == actual @@ -1275,7 +1462,6 @@ def test_parse_common_project_path(): def test_common_location_path(): project = "whelk" location = "octopus" - expected = "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -1302,7 +1488,7 @@ def test_client_withDEFAULT_CLIENT_INFO(): transports.TraceServiceTransport, "_prep_wrapped_messages" ) as prep: client = TraceServiceClient( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) @@ -1311,6 +1497,6 @@ def test_client_withDEFAULT_CLIENT_INFO(): ) as prep: transport_class = TraceServiceClient.get_transport_class() transport = transport_class( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info)