From 45110a819c79deea9232e1da4cd2c3714cc02b0a Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 14 May 2021 12:54:06 +0000 Subject: [PATCH] chore: upgrade gapic-generator-python to 0.46.3 (#91) PiperOrigin-RevId: 373649163 Source-Link: https://github.com/googleapis/googleapis/commit/7e1b14e6c7a9ab96d2db7e4a131981f162446d34 Source-Link: https://github.com/googleapis/googleapis-gen/commit/0a3c7d272d697796db75857bac73905c68e498c3 --- docs/budgets_v1/budget_service.rst | 1 - docs/budgets_v1beta1/budget_service.rst | 1 - google/cloud/billing/budgets/__init__.py | 24 +- google/cloud/billing/budgets_v1/__init__.py | 11 +- .../billing/budgets_v1/gapic_metadata.json | 73 +++ .../billing/budgets_v1/services/__init__.py | 1 - .../services/budget_service/__init__.py | 2 - .../services/budget_service/async_client.py | 74 +-- .../services/budget_service/client.py | 104 ++-- .../services/budget_service/pagers.py | 4 +- .../budget_service/transports/__init__.py | 2 - .../budget_service/transports/base.py | 134 +++-- .../budget_service/transports/grpc.py | 28 +- .../budget_service/transports/grpc_asyncio.py | 29 +- .../billing/budgets_v1/types/__init__.py | 6 +- .../billing/budgets_v1/types/budget_model.py | 150 +++-- .../budgets_v1/types/budget_service.py | 34 +- .../cloud/billing/budgets_v1beta1/__init__.py | 11 +- .../budgets_v1beta1/gapic_metadata.json | 73 +++ .../budgets_v1beta1/services/__init__.py | 1 - .../services/budget_service/__init__.py | 2 - .../services/budget_service/async_client.py | 70 +-- .../services/budget_service/client.py | 95 ++-- .../services/budget_service/pagers.py | 4 +- .../budget_service/transports/__init__.py | 2 - .../budget_service/transports/base.py | 134 +++-- .../budget_service/transports/grpc.py | 28 +- .../budget_service/transports/grpc_asyncio.py | 29 +- .../billing/budgets_v1beta1/types/__init__.py | 6 +- .../budgets_v1beta1/types/budget_model.py | 159 ++++-- .../budgets_v1beta1/types/budget_service.py | 34 +- scripts/fixup_budgets_v1_keywords.py | 15 +- scripts/fixup_budgets_v1beta1_keywords.py | 15 +- tests/__init__.py | 15 + tests/unit/__init__.py | 15 + tests/unit/gapic/__init__.py | 15 + tests/unit/gapic/budgets_v1/__init__.py | 1 - .../gapic/budgets_v1/test_budget_service.py | 535 ++++++++++++------ tests/unit/gapic/budgets_v1beta1/__init__.py | 1 - .../budgets_v1beta1/test_budget_service.py | 444 ++++++++++----- 40 files changed, 1530 insertions(+), 852 deletions(-) create mode 100644 google/cloud/billing/budgets_v1/gapic_metadata.json create mode 100644 google/cloud/billing/budgets_v1beta1/gapic_metadata.json create mode 100644 tests/__init__.py create mode 100644 tests/unit/__init__.py create mode 100644 tests/unit/gapic/__init__.py diff --git a/docs/budgets_v1/budget_service.rst b/docs/budgets_v1/budget_service.rst index 487fede..29d54ca 100644 --- a/docs/budgets_v1/budget_service.rst +++ b/docs/budgets_v1/budget_service.rst @@ -5,7 +5,6 @@ BudgetService :members: :inherited-members: - .. automodule:: google.cloud.billing.budgets_v1.services.budget_service.pagers :members: :inherited-members: diff --git a/docs/budgets_v1beta1/budget_service.rst b/docs/budgets_v1beta1/budget_service.rst index fffcb34..100afaf 100644 --- a/docs/budgets_v1beta1/budget_service.rst +++ b/docs/budgets_v1beta1/budget_service.rst @@ -5,7 +5,6 @@ BudgetService :members: :inherited-members: - .. automodule:: google.cloud.billing.budgets_v1beta1.services.budget_service.pagers :members: :inherited-members: diff --git a/google/cloud/billing/budgets/__init__.py b/google/cloud/billing/budgets/__init__.py index e684f5b..c389a8f 100644 --- a/google/cloud/billing/budgets/__init__.py +++ b/google/cloud/billing/budgets/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,18 +14,21 @@ # limitations under the License. # -from google.cloud.billing.budgets_v1.services.budget_service.async_client import ( - BudgetServiceAsyncClient, -) from google.cloud.billing.budgets_v1.services.budget_service.client import ( BudgetServiceClient, ) +from google.cloud.billing.budgets_v1.services.budget_service.async_client import ( + BudgetServiceAsyncClient, +) + from google.cloud.billing.budgets_v1.types.budget_model import Budget from google.cloud.billing.budgets_v1.types.budget_model import BudgetAmount +from google.cloud.billing.budgets_v1.types.budget_model import CustomPeriod from google.cloud.billing.budgets_v1.types.budget_model import Filter from google.cloud.billing.budgets_v1.types.budget_model import LastPeriodAmount from google.cloud.billing.budgets_v1.types.budget_model import NotificationsRule from google.cloud.billing.budgets_v1.types.budget_model import ThresholdRule +from google.cloud.billing.budgets_v1.types.budget_model import CalendarPeriod from google.cloud.billing.budgets_v1.types.budget_service import CreateBudgetRequest from google.cloud.billing.budgets_v1.types.budget_service import DeleteBudgetRequest from google.cloud.billing.budgets_v1.types.budget_service import GetBudgetRequest @@ -35,18 +37,20 @@ from google.cloud.billing.budgets_v1.types.budget_service import UpdateBudgetRequest __all__ = ( + "BudgetServiceClient", + "BudgetServiceAsyncClient", "Budget", "BudgetAmount", - "BudgetServiceAsyncClient", - "BudgetServiceClient", + "CustomPeriod", + "Filter", + "LastPeriodAmount", + "NotificationsRule", + "ThresholdRule", + "CalendarPeriod", "CreateBudgetRequest", "DeleteBudgetRequest", - "Filter", "GetBudgetRequest", - "LastPeriodAmount", "ListBudgetsRequest", "ListBudgetsResponse", - "NotificationsRule", - "ThresholdRule", "UpdateBudgetRequest", ) diff --git a/google/cloud/billing/budgets_v1/__init__.py b/google/cloud/billing/budgets_v1/__init__.py index 92aaeb0..1ae1451 100644 --- a/google/cloud/billing/budgets_v1/__init__.py +++ b/google/cloud/billing/budgets_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,12 +15,16 @@ # from .services.budget_service import BudgetServiceClient +from .services.budget_service import BudgetServiceAsyncClient + from .types.budget_model import Budget from .types.budget_model import BudgetAmount +from .types.budget_model import CustomPeriod from .types.budget_model import Filter from .types.budget_model import LastPeriodAmount from .types.budget_model import NotificationsRule from .types.budget_model import ThresholdRule +from .types.budget_model import CalendarPeriod from .types.budget_service import CreateBudgetRequest from .types.budget_service import DeleteBudgetRequest from .types.budget_service import GetBudgetRequest @@ -29,11 +32,14 @@ from .types.budget_service import ListBudgetsResponse from .types.budget_service import UpdateBudgetRequest - __all__ = ( + "BudgetServiceAsyncClient", "Budget", "BudgetAmount", + "BudgetServiceClient", + "CalendarPeriod", "CreateBudgetRequest", + "CustomPeriod", "DeleteBudgetRequest", "Filter", "GetBudgetRequest", @@ -43,5 +49,4 @@ "NotificationsRule", "ThresholdRule", "UpdateBudgetRequest", - "BudgetServiceClient", ) diff --git a/google/cloud/billing/budgets_v1/gapic_metadata.json b/google/cloud/billing/budgets_v1/gapic_metadata.json new file mode 100644 index 0000000..38bf837 --- /dev/null +++ b/google/cloud/billing/budgets_v1/gapic_metadata.json @@ -0,0 +1,73 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.billing.budgets_v1", + "protoPackage": "google.cloud.billing.budgets.v1", + "schema": "1.0", + "services": { + "BudgetService": { + "clients": { + "grpc": { + "libraryClient": "BudgetServiceClient", + "rpcs": { + "CreateBudget": { + "methods": [ + "create_budget" + ] + }, + "DeleteBudget": { + "methods": [ + "delete_budget" + ] + }, + "GetBudget": { + "methods": [ + "get_budget" + ] + }, + "ListBudgets": { + "methods": [ + "list_budgets" + ] + }, + "UpdateBudget": { + "methods": [ + "update_budget" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BudgetServiceAsyncClient", + "rpcs": { + "CreateBudget": { + "methods": [ + "create_budget" + ] + }, + "DeleteBudget": { + "methods": [ + "delete_budget" + ] + }, + "GetBudget": { + "methods": [ + "get_budget" + ] + }, + "ListBudgets": { + "methods": [ + "list_budgets" + ] + }, + "UpdateBudget": { + "methods": [ + "update_budget" + ] + } + } + } + } + } + } +} diff --git a/google/cloud/billing/budgets_v1/services/__init__.py b/google/cloud/billing/budgets_v1/services/__init__.py index 42ffdf2..4de6597 100644 --- a/google/cloud/billing/budgets_v1/services/__init__.py +++ b/google/cloud/billing/budgets_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/billing/budgets_v1/services/budget_service/__init__.py b/google/cloud/billing/budgets_v1/services/budget_service/__init__.py index 97d50ab..737114a 100644 --- a/google/cloud/billing/budgets_v1/services/budget_service/__init__.py +++ b/google/cloud/billing/budgets_v1/services/budget_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 BudgetServiceClient from .async_client import BudgetServiceAsyncClient diff --git a/google/cloud/billing/budgets_v1/services/budget_service/async_client.py b/google/cloud/billing/budgets_v1/services/budget_service/async_client.py index 365815c..4235193 100644 --- a/google/cloud/billing/budgets_v1/services/budget_service/async_client.py +++ b/google/cloud/billing/budgets_v1/services/budget_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,17 +20,16 @@ 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.billing.budgets_v1.services.budget_service import pagers from google.cloud.billing.budgets_v1.types import budget_model from google.cloud.billing.budgets_v1.types import budget_service -from google.protobuf import field_mask_pb2 as field_mask # type: ignore - +from google.protobuf import field_mask_pb2 # type: ignore from .transports.base import BudgetServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import BudgetServiceGrpcAsyncIOTransport from .client import BudgetServiceClient @@ -51,31 +48,26 @@ class BudgetServiceAsyncClient: budget_path = staticmethod(BudgetServiceClient.budget_path) parse_budget_path = staticmethod(BudgetServiceClient.parse_budget_path) - common_billing_account_path = staticmethod( BudgetServiceClient.common_billing_account_path ) parse_common_billing_account_path = staticmethod( BudgetServiceClient.parse_common_billing_account_path ) - common_folder_path = staticmethod(BudgetServiceClient.common_folder_path) parse_common_folder_path = staticmethod( BudgetServiceClient.parse_common_folder_path ) - common_organization_path = staticmethod( BudgetServiceClient.common_organization_path ) parse_common_organization_path = staticmethod( BudgetServiceClient.parse_common_organization_path ) - common_project_path = staticmethod(BudgetServiceClient.common_project_path) parse_common_project_path = staticmethod( BudgetServiceClient.parse_common_project_path ) - common_location_path = staticmethod(BudgetServiceClient.common_location_path) parse_common_location_path = staticmethod( BudgetServiceClient.parse_common_location_path @@ -83,7 +75,8 @@ class BudgetServiceAsyncClient: @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) -> BudgetServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: BudgetServiceTransport: The transport used by the client instance. @@ -129,12 +122,12 @@ def transport(self) -> BudgetServiceTransport: def __init__( self, *, - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, transport: Union[str, BudgetServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the budget service client. + """Instantiates the budget 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 = BudgetServiceClient( credentials=credentials, transport=transport, @@ -205,7 +197,6 @@ async def create_budget( This corresponds to the ``budget`` 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. @@ -219,10 +210,10 @@ async def create_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. @@ -239,7 +230,6 @@ async def create_budget( # If we have keyword arguments corresponding to fields on the # request, apply these. - if parent is not None: request.parent = parent if budget is not None: @@ -270,7 +260,7 @@ async def update_budget( request: budget_service.UpdateBudgetRequest = None, *, budget: budget_model.Budget = None, - update_mask: field_mask.FieldMask = None, + update_mask: field_mask_pb2.FieldMask = None, retry: retries.Retry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), @@ -303,7 +293,6 @@ async def update_budget( This corresponds to the ``update_mask`` 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. @@ -317,10 +306,10 @@ async def update_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. @@ -337,7 +326,6 @@ async def update_budget( # If we have keyword arguments corresponding to fields on the # request, apply these. - if budget is not None: request.budget = budget if update_mask is not None: @@ -352,7 +340,8 @@ async def update_budget( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -400,7 +389,6 @@ async def get_budget( This corresponds to the ``name`` 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. @@ -414,10 +402,10 @@ async def get_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. @@ -434,7 +422,6 @@ async def get_budget( # If we have keyword arguments corresponding to fields on the # request, apply these. - if name is not None: request.name = name @@ -447,7 +434,8 @@ async def get_budget( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -494,7 +482,6 @@ async def list_budgets( This corresponds to the ``parent`` 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. @@ -523,7 +510,6 @@ async def list_budgets( # If we have keyword arguments corresponding to fields on the # request, apply these. - if parent is not None: request.parent = parent @@ -536,7 +522,8 @@ async def list_budgets( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -585,7 +572,6 @@ async def delete_budget( This corresponds to the ``name`` 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. @@ -606,7 +592,6 @@ async def delete_budget( # If we have keyword arguments corresponding to fields on the # request, apply these. - if name is not None: request.name = name @@ -619,7 +604,8 @@ async def delete_budget( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), diff --git a/google/cloud/billing/budgets_v1/services/budget_service/client.py b/google/cloud/billing/budgets_v1/services/budget_service/client.py index 969fed9..975d9da 100644 --- a/google/cloud/billing/budgets_v1/services/budget_service/client.py +++ b/google/cloud/billing/budgets_v1/services/budget_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 @@ -35,8 +33,7 @@ from google.cloud.billing.budgets_v1.services.budget_service import pagers from google.cloud.billing.budgets_v1.types import budget_model from google.cloud.billing.budgets_v1.types import budget_service -from google.protobuf import field_mask_pb2 as field_mask # type: ignore - +from google.protobuf import field_mask_pb2 # type: ignore from .transports.base import BudgetServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import BudgetServiceGrpcTransport from .transports.grpc_asyncio import BudgetServiceGrpcAsyncIOTransport @@ -55,7 +52,7 @@ class BudgetServiceClientMeta(type): _transport_registry["grpc_asyncio"] = BudgetServiceGrpcAsyncIOTransport def get_transport_class(cls, label: str = None,) -> Type[BudgetServiceTransport]: - """Return an appropriate transport class. + """Returns an appropriate transport class. Args: label: The name of the desired transport. If none is @@ -81,7 +78,8 @@ class BudgetServiceClient(metaclass=BudgetServiceClientMeta): @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: @@ -115,7 +113,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. @@ -132,7 +131,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 @@ -151,23 +150,24 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> BudgetServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: - BudgetServiceTransport: The transport used by the client instance. + BudgetServiceTransport: The transport used by the client + instance. """ return self._transport @staticmethod def budget_path(billing_account: str, budget: str,) -> str: - """Return a fully-qualified budget string.""" + """Returns a fully-qualified budget string.""" return "billingAccounts/{billing_account}/budgets/{budget}".format( billing_account=billing_account, budget=budget, ) @staticmethod def parse_budget_path(path: str) -> Dict[str, str]: - """Parse a budget path into its component segments.""" + """Parses a budget path into its component segments.""" m = re.match( r"^billingAccounts/(?P.+?)/budgets/(?P.+?)$", path ) @@ -175,7 +175,7 @@ def parse_budget_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, ) @@ -188,7 +188,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 @@ -199,7 +199,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 @@ -210,7 +210,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 @@ -221,7 +221,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, ) @@ -235,12 +235,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, BudgetServiceTransport, None] = None, client_options: Optional[client_options_lib.ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the budget service client. + """Instantiates the budget service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -295,9 +295,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: @@ -309,12 +310,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. @@ -329,8 +332,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: @@ -376,7 +379,6 @@ def create_budget( This corresponds to the ``budget`` 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. @@ -390,10 +392,10 @@ def create_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. @@ -412,10 +414,8 @@ def create_budget( # there are no flattened fields. if not isinstance(request, budget_service.CreateBudgetRequest): request = budget_service.CreateBudgetRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if parent is not None: request.parent = parent if budget is not None: @@ -442,7 +442,7 @@ def update_budget( request: budget_service.UpdateBudgetRequest = None, *, budget: budget_model.Budget = None, - update_mask: field_mask.FieldMask = None, + update_mask: field_mask_pb2.FieldMask = None, retry: retries.Retry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), @@ -475,7 +475,6 @@ def update_budget( This corresponds to the ``update_mask`` 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. @@ -489,10 +488,10 @@ def update_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. @@ -511,10 +510,8 @@ def update_budget( # there are no flattened fields. if not isinstance(request, budget_service.UpdateBudgetRequest): request = budget_service.UpdateBudgetRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if budget is not None: request.budget = budget if update_mask is not None: @@ -564,7 +561,6 @@ def get_budget( This corresponds to the ``name`` 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. @@ -578,10 +574,10 @@ def get_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. @@ -600,10 +596,8 @@ def get_budget( # there are no flattened fields. if not isinstance(request, budget_service.GetBudgetRequest): request = budget_service.GetBudgetRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if name is not None: request.name = name @@ -650,7 +644,6 @@ def list_budgets( This corresponds to the ``parent`` 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. @@ -681,10 +674,8 @@ def list_budgets( # there are no flattened fields. if not isinstance(request, budget_service.ListBudgetsRequest): request = budget_service.ListBudgetsRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if parent is not None: request.parent = parent @@ -733,7 +724,6 @@ def delete_budget( This corresponds to the ``name`` 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. @@ -756,10 +746,8 @@ def delete_budget( # there are no flattened fields. if not isinstance(request, budget_service.DeleteBudgetRequest): request = budget_service.DeleteBudgetRequest(request) - # If we have keyword arguments corresponding to fields on the # request, apply these. - if name is not None: request.name = name diff --git a/google/cloud/billing/budgets_v1/services/budget_service/pagers.py b/google/cloud/billing/budgets_v1/services/budget_service/pagers.py index a68f005..7dd43d5 100644 --- a/google/cloud/billing/budgets_v1/services/budget_service/pagers.py +++ b/google/cloud/billing/budgets_v1/services/budget_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, @@ -118,7 +116,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/billing/budgets_v1/services/budget_service/transports/__init__.py b/google/cloud/billing/budgets_v1/services/budget_service/transports/__init__.py index 0ab5ac1..f65a2e4 100644 --- a/google/cloud/billing/budgets_v1/services/budget_service/transports/__init__.py +++ b/google/cloud/billing/budgets_v1/services/budget_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/billing/budgets_v1/services/budget_service/transports/base.py b/google/cloud/billing/budgets_v1/services/budget_service/transports/base.py index 19356cd..c9f9307 100644 --- a/google/cloud/billing/budgets_v1/services/budget_service/transports/base.py +++ b/google/cloud/billing/budgets_v1/services/budget_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.billing.budgets_v1.types import budget_model from google.cloud.billing.budgets_v1.types import budget_service -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( @@ -39,6 +38,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 BudgetServiceTransport(abc.ABC): """Abstract transport class for BudgetService.""" @@ -48,21 +58,24 @@ class BudgetServiceTransport(abc.ABC): "https://www.googleapis.com/auth/cloud-platform", ) + DEFAULT_HOST: str = "billingbudgets.googleapis.com" + def __init__( self, *, - host: str = "billingbudgets.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 @@ -71,7 +84,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): @@ -85,29 +98,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 = { @@ -121,7 +181,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -135,7 +196,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -149,7 +211,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -163,7 +226,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -175,38 +239,38 @@ def _prep_wrapped_messages(self, client_info): @property def create_budget( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.CreateBudgetRequest], - typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + Union[budget_model.Budget, Awaitable[budget_model.Budget]], ]: raise NotImplementedError() @property def update_budget( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.UpdateBudgetRequest], - typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + Union[budget_model.Budget, Awaitable[budget_model.Budget]], ]: raise NotImplementedError() @property def get_budget( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.GetBudgetRequest], - typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + Union[budget_model.Budget, Awaitable[budget_model.Budget]], ]: raise NotImplementedError() @property def list_budgets( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.ListBudgetsRequest], - typing.Union[ + Union[ budget_service.ListBudgetsResponse, - typing.Awaitable[budget_service.ListBudgetsResponse], + Awaitable[budget_service.ListBudgetsResponse], ], ]: raise NotImplementedError() @@ -214,9 +278,9 @@ def list_budgets( @property def delete_budget( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.DeleteBudgetRequest], - typing.Union[empty.Empty, typing.Awaitable[empty.Empty]], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], ]: raise NotImplementedError() diff --git a/google/cloud/billing/budgets_v1/services/budget_service/transports/grpc.py b/google/cloud/billing/budgets_v1/services/budget_service/transports/grpc.py index 6576d62..4f2f143 100644 --- a/google/cloud/billing/budgets_v1/services/budget_service/transports/grpc.py +++ b/google/cloud/billing/budgets_v1/services/budget_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.billing.budgets_v1.types import budget_model from google.cloud.billing.budgets_v1.types import budget_service -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore from .base import BudgetServiceTransport, DEFAULT_CLIENT_INFO @@ -54,7 +51,7 @@ def __init__( self, *, host: str = "billingbudgets.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Sequence[str] = None, channel: grpc.Channel = None, @@ -68,7 +65,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 @@ -178,7 +176,7 @@ def __init__( def create_channel( cls, host: str = "billingbudgets.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, @@ -209,13 +207,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, ) @@ -351,7 +351,7 @@ def list_budgets( @property def delete_budget( self, - ) -> Callable[[budget_service.DeleteBudgetRequest], empty.Empty]: + ) -> Callable[[budget_service.DeleteBudgetRequest], empty_pb2.Empty]: r"""Return a callable for the delete budget method over gRPC. Deletes a budget. Returns successfully if already @@ -371,7 +371,7 @@ def delete_budget( self._stubs["delete_budget"] = self.grpc_channel.unary_unary( "/google.cloud.billing.budgets.v1.BudgetService/DeleteBudget", request_serializer=budget_service.DeleteBudgetRequest.serialize, - response_deserializer=empty.Empty.FromString, + response_deserializer=empty_pb2.Empty.FromString, ) return self._stubs["delete_budget"] diff --git a/google/cloud/billing/budgets_v1/services/budget_service/transports/grpc_asyncio.py b/google/cloud/billing/budgets_v1/services/budget_service/transports/grpc_asyncio.py index 975ddbc..542a31e 100644 --- a/google/cloud/billing/budgets_v1/services/budget_service/transports/grpc_asyncio.py +++ b/google/cloud/billing/budgets_v1/services/budget_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.billing.budgets_v1.types import budget_model from google.cloud.billing.budgets_v1.types import budget_service -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore from .base import BudgetServiceTransport, DEFAULT_CLIENT_INFO from .grpc import BudgetServiceGrpcTransport @@ -57,7 +54,7 @@ class BudgetServiceGrpcAsyncIOTransport(BudgetServiceTransport): def create_channel( cls, host: str = "billingbudgets.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, @@ -84,13 +81,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, ) @@ -98,7 +97,7 @@ def __init__( self, *, host: str = "billingbudgets.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, @@ -112,7 +111,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 @@ -170,7 +170,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 @@ -356,7 +355,7 @@ def list_budgets( @property def delete_budget( self, - ) -> Callable[[budget_service.DeleteBudgetRequest], Awaitable[empty.Empty]]: + ) -> Callable[[budget_service.DeleteBudgetRequest], Awaitable[empty_pb2.Empty]]: r"""Return a callable for the delete budget method over gRPC. Deletes a budget. Returns successfully if already @@ -376,7 +375,7 @@ def delete_budget( self._stubs["delete_budget"] = self.grpc_channel.unary_unary( "/google.cloud.billing.budgets.v1.BudgetService/DeleteBudget", request_serializer=budget_service.DeleteBudgetRequest.serialize, - response_deserializer=empty.Empty.FromString, + response_deserializer=empty_pb2.Empty.FromString, ) return self._stubs["delete_budget"] diff --git a/google/cloud/billing/budgets_v1/types/__init__.py b/google/cloud/billing/budgets_v1/types/__init__.py index 773dccd..25be1b0 100644 --- a/google/cloud/billing/budgets_v1/types/__init__.py +++ b/google/cloud/billing/budgets_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,14 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .budget_model import ( Budget, BudgetAmount, + CustomPeriod, Filter, LastPeriodAmount, NotificationsRule, ThresholdRule, + CalendarPeriod, ) from .budget_service import ( CreateBudgetRequest, @@ -35,10 +35,12 @@ __all__ = ( "Budget", "BudgetAmount", + "CustomPeriod", "Filter", "LastPeriodAmount", "NotificationsRule", "ThresholdRule", + "CalendarPeriod", "CreateBudgetRequest", "DeleteBudgetRequest", "GetBudgetRequest", diff --git a/google/cloud/billing/budgets_v1/types/budget_model.py b/google/cloud/billing/budgets_v1/types/budget_model.py index 16d4562..3239e10 100644 --- a/google/cloud/billing/budgets_v1/types/budget_model.py +++ b/google/cloud/billing/budgets_v1/types/budget_model.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,34 +13,47 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - -from google.protobuf import struct_pb2 as struct # type: ignore -from google.type import money_pb2 as money # type: ignore +from google.protobuf import struct_pb2 # type: ignore +from google.type import date_pb2 # type: ignore +from google.type import money_pb2 # type: ignore __protobuf__ = proto.module( package="google.cloud.billing.budgets.v1", manifest={ + "CalendarPeriod", "Budget", "BudgetAmount", "LastPeriodAmount", "ThresholdRule", "NotificationsRule", "Filter", + "CustomPeriod", }, ) +class CalendarPeriod(proto.Enum): + r"""A ``CalendarPeriod`` represents the abstract concept of a time + period that has a canonical start. Grammatically, "the start of the + current ``CalendarPeriod``". All calendar times begin at 12 AM US + and Canadian Pacific Time (UTC-8). + """ + CALENDAR_PERIOD_UNSPECIFIED = 0 + MONTH = 1 + QUARTER = 2 + YEAR = 3 + + class Budget(proto.Message): r"""A budget is a plan that describes what you expect to spend on Cloud projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all plans are monthly budgets so - the usage period(s) tracked are implied (calendar months of - usage back-to-back). + target spend is met). The budget time period is configurable, + with options such as month (default), quarter, year, or custom + time period. Attributes: name (str): @@ -54,7 +66,9 @@ class Budget(proto.Message): budget_filter (google.cloud.billing.budgets_v1.types.Filter): Optional. Filters that define which resources are used to compute the actual spend against the - budget. + budget amount, such as projects, services, and + the budget's time period, as well as other + filters. amount (google.cloud.billing.budgets_v1.types.BudgetAmount): Required. Budgeted amount. threshold_rules (Sequence[google.cloud.billing.budgets_v1.types.ThresholdRule]): @@ -72,28 +86,21 @@ class Budget(proto.Message): other changes. """ - name = proto.Field(proto.STRING, number=1) - - display_name = proto.Field(proto.STRING, number=2) - + name = proto.Field(proto.STRING, number=1,) + display_name = proto.Field(proto.STRING, number=2,) budget_filter = proto.Field(proto.MESSAGE, number=3, message="Filter",) - amount = proto.Field(proto.MESSAGE, number=4, message="BudgetAmount",) - threshold_rules = proto.RepeatedField( proto.MESSAGE, number=5, message="ThresholdRule", ) - notifications_rule = proto.Field( proto.MESSAGE, number=6, message="NotificationsRule", ) - - etag = proto.Field(proto.STRING, number=7) + etag = proto.Field(proto.STRING, number=7,) class BudgetAmount(proto.Message): r"""The budgeted amount for each usage period. - Attributes: specified_amount (google.type.money_pb2.Money): A specified amount to use as the budget. ``currency_code`` @@ -103,26 +110,32 @@ class BudgetAmount(proto.Message): existing budget. The ``currency_code`` is provided on output. last_period_amount (google.cloud.billing.budgets_v1.types.LastPeriodAmount): - Use the last period's actual spend as the - budget for the present period. + Use the last period's actual spend as the budget for the + present period. LastPeriodAmount can only be set when the + budget's time period is a + [Filter.calendar_period][google.cloud.billing.budgets.v1.Filter.calendar_period]. + It cannot be set in combination with + [Filter.custom_period][google.cloud.billing.budgets.v1.Filter.custom_period]. """ specified_amount = proto.Field( - proto.MESSAGE, number=1, oneof="budget_amount", message=money.Money, + proto.MESSAGE, number=1, oneof="budget_amount", message=money_pb2.Money, ) - last_period_amount = proto.Field( proto.MESSAGE, number=2, oneof="budget_amount", message="LastPeriodAmount", ) class LastPeriodAmount(proto.Message): - r"""Describes a budget amount targeted to last period's spend. - At this time, the amount is automatically 100% of last period's - spend; that is, there are no other options yet. - Future configuration will be described here (for example, - configuring a percentage of last period's spend). - """ + r"""Describes a budget amount targeted to the last + [Filter.calendar_period][google.cloud.billing.budgets.v1.Filter.calendar_period] + spend. At this time, the amount is automatically 100% of the last + calendar period's spend; that is, there are no other options yet. + Future configuration options will be described here (for example, + configuring a percentage of last period's spend). LastPeriodAmount + cannot be set for a budget configured with a + [Filter.custom_period][google.cloud.billing.budgets.v1.Filter.custom_period]. + """ class ThresholdRule(proto.Message): @@ -153,8 +166,7 @@ class Basis(proto.Enum): CURRENT_SPEND = 1 FORECASTED_SPEND = 2 - threshold_percent = proto.Field(proto.DOUBLE, number=1) - + threshold_percent = proto.Field(proto.DOUBLE, number=1,) spend_basis = proto.Field(proto.ENUM, number=2, enum=Basis,) @@ -202,13 +214,10 @@ class NotificationsRule(proto.Message): Account User IAM roles for the target account. """ - pubsub_topic = proto.Field(proto.STRING, number=1) - - schema_version = proto.Field(proto.STRING, number=2) - - monitoring_notification_channels = proto.RepeatedField(proto.STRING, number=3) - - disable_default_iam_recipients = proto.Field(proto.BOOL, number=4) + pubsub_topic = proto.Field(proto.STRING, number=1,) + schema_version = proto.Field(proto.STRING, number=2,) + monitoring_notification_channels = proto.RepeatedField(proto.STRING, number=3,) + disable_default_iam_recipients = proto.Field(proto.BOOL, number=4,) class Filter(proto.Message): @@ -228,13 +237,14 @@ class Filter(proto.Message): [Filter.credit_types_treatment][google.cloud.billing.budgets.v1.Filter.credit_types_treatment] is INCLUDE_SPECIFIED_CREDITS, this is a list of credit types to be subtracted from gross cost to determine the spend for - threshold calculations. + threshold calculations. See `a list of acceptable credit + type + values `__. If [Filter.credit_types_treatment][google.cloud.billing.budgets.v1.Filter.credit_types_treatment] is **not** INCLUDE_SPECIFIED_CREDITS, this field must be - empty. See `a list of acceptable credit type - values `__. + empty. credit_types_treatment (google.cloud.billing.budgets_v1.types.Filter.CreditTypesTreatment): Optional. If not set, default behavior is ``INCLUDE_ALL_CREDITS``. @@ -261,32 +271,68 @@ class Filter(proto.Message): values per entry are not allowed. If omitted, the report will include all labeled and unlabeled usage. + calendar_period (google.cloud.billing.budgets_v1.types.CalendarPeriod): + Optional. Specifies to track usage for + recurring calendar period. For example, assume + that CalendarPeriod.QUARTER is set. The budget + will track usage from April 1 to June 30, when + the current calendar month is April, May, June. + After that, it will track usage from July 1 to + September 30 when the current calendar month is + July, August, September, so on. + custom_period (google.cloud.billing.budgets_v1.types.CustomPeriod): + Optional. Specifies to track usage from any + start date (required) to any end date + (optional). This time period is static, it does + not recur. """ class CreditTypesTreatment(proto.Enum): - r"""Specifies how credits should be treated when determining - spend for threshold calculations. + r"""Specifies how credits are applied when determining the spend for + threshold calculations. Budgets track the total cost minus any + applicable selected credits. `See the documentation for a list of + credit + types `__. """ CREDIT_TYPES_TREATMENT_UNSPECIFIED = 0 INCLUDE_ALL_CREDITS = 1 EXCLUDE_ALL_CREDITS = 2 INCLUDE_SPECIFIED_CREDITS = 3 - projects = proto.RepeatedField(proto.STRING, number=1) - - credit_types = proto.RepeatedField(proto.STRING, number=7) - + projects = proto.RepeatedField(proto.STRING, number=1,) + credit_types = proto.RepeatedField(proto.STRING, number=7,) credit_types_treatment = proto.Field( proto.ENUM, number=4, enum=CreditTypesTreatment, ) + services = proto.RepeatedField(proto.STRING, number=3,) + subaccounts = proto.RepeatedField(proto.STRING, number=5,) + labels = proto.MapField( + proto.STRING, proto.MESSAGE, number=6, message=struct_pb2.ListValue, + ) + calendar_period = proto.Field( + proto.ENUM, number=8, oneof="usage_period", enum="CalendarPeriod", + ) + custom_period = proto.Field( + proto.MESSAGE, number=9, oneof="usage_period", message="CustomPeriod", + ) - services = proto.RepeatedField(proto.STRING, number=3) - subaccounts = proto.RepeatedField(proto.STRING, number=5) +class CustomPeriod(proto.Message): + r"""All date times begin at 12 AM US and Canadian Pacific Time + (UTC-8). - labels = proto.MapField( - proto.STRING, proto.MESSAGE, number=6, message=struct.ListValue, - ) + Attributes: + start_date (google.type.date_pb2.Date): + Required. The start date must be after + January 1, 2017. + end_date (google.type.date_pb2.Date): + Optional. The end date of the time period. Budgets with + elapsed end date won't be processed. If unset, specifies to + track all usage incurred since the start_date. + """ + + start_date = proto.Field(proto.MESSAGE, number=1, message=date_pb2.Date,) + end_date = proto.Field(proto.MESSAGE, number=2, message=date_pb2.Date,) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/billing/budgets_v1/types/budget_service.py b/google/cloud/billing/budgets_v1/types/budget_service.py index 5f1f54c..138511a 100644 --- a/google/cloud/billing/budgets_v1/types/budget_service.py +++ b/google/cloud/billing/budgets_v1/types/budget_service.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,12 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - from google.cloud.billing.budgets_v1.types import budget_model -from google.protobuf import field_mask_pb2 as field_mask # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore __protobuf__ = proto.module( @@ -37,7 +34,6 @@ class CreateBudgetRequest(proto.Message): r"""Request for CreateBudget - Attributes: parent (str): Required. The name of the billing account to create the @@ -47,14 +43,12 @@ class CreateBudgetRequest(proto.Message): Required. Budget to create. """ - parent = proto.Field(proto.STRING, number=1) - + parent = proto.Field(proto.STRING, number=1,) budget = proto.Field(proto.MESSAGE, number=2, message=budget_model.Budget,) class UpdateBudgetRequest(proto.Message): r"""Request for UpdateBudget - Attributes: budget (google.cloud.billing.budgets_v1.types.Budget): Required. The updated budget object. @@ -70,25 +64,24 @@ class UpdateBudgetRequest(proto.Message): """ budget = proto.Field(proto.MESSAGE, number=1, message=budget_model.Budget,) - - update_mask = proto.Field(proto.MESSAGE, number=2, message=field_mask.FieldMask,) + update_mask = proto.Field( + proto.MESSAGE, number=2, message=field_mask_pb2.FieldMask, + ) class GetBudgetRequest(proto.Message): r"""Request for GetBudget - Attributes: name (str): Required. Name of budget to get. Values are of the form ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. """ - name = proto.Field(proto.STRING, number=1) + name = proto.Field(proto.STRING, number=1,) class ListBudgetsRequest(proto.Message): r"""Request for ListBudgets - Attributes: parent (str): Required. Name of billing account to list budgets under. @@ -105,16 +98,13 @@ class ListBudgetsRequest(proto.Message): system should return the next page of data. """ - parent = proto.Field(proto.STRING, number=1) - - page_size = proto.Field(proto.INT32, number=2) - - page_token = proto.Field(proto.STRING, number=3) + parent = proto.Field(proto.STRING, number=1,) + page_size = proto.Field(proto.INT32, number=2,) + page_token = proto.Field(proto.STRING, number=3,) class ListBudgetsResponse(proto.Message): r"""Response for ListBudgets - Attributes: budgets (Sequence[google.cloud.billing.budgets_v1.types.Budget]): List of the budgets owned by the requested @@ -130,13 +120,11 @@ def raw_page(self): return self budgets = proto.RepeatedField(proto.MESSAGE, number=1, message=budget_model.Budget,) - - next_page_token = proto.Field(proto.STRING, number=2) + next_page_token = proto.Field(proto.STRING, number=2,) class DeleteBudgetRequest(proto.Message): r"""Request for DeleteBudget - Attributes: name (str): Required. Name of the budget to delete. Values are of the @@ -144,7 +132,7 @@ class DeleteBudgetRequest(proto.Message): ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. """ - name = proto.Field(proto.STRING, number=1) + name = proto.Field(proto.STRING, number=1,) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/billing/budgets_v1beta1/__init__.py b/google/cloud/billing/budgets_v1beta1/__init__.py index cce38aa..df3f22b 100644 --- a/google/cloud/billing/budgets_v1beta1/__init__.py +++ b/google/cloud/billing/budgets_v1beta1/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,12 +15,16 @@ # from .services.budget_service import BudgetServiceClient +from .services.budget_service import BudgetServiceAsyncClient + from .types.budget_model import AllUpdatesRule from .types.budget_model import Budget from .types.budget_model import BudgetAmount +from .types.budget_model import CustomPeriod from .types.budget_model import Filter from .types.budget_model import LastPeriodAmount from .types.budget_model import ThresholdRule +from .types.budget_model import CalendarPeriod from .types.budget_service import CreateBudgetRequest from .types.budget_service import DeleteBudgetRequest from .types.budget_service import GetBudgetRequest @@ -29,12 +32,15 @@ from .types.budget_service import ListBudgetsResponse from .types.budget_service import UpdateBudgetRequest - __all__ = ( + "BudgetServiceAsyncClient", "AllUpdatesRule", "Budget", "BudgetAmount", + "BudgetServiceClient", + "CalendarPeriod", "CreateBudgetRequest", + "CustomPeriod", "DeleteBudgetRequest", "Filter", "GetBudgetRequest", @@ -43,5 +49,4 @@ "ListBudgetsResponse", "ThresholdRule", "UpdateBudgetRequest", - "BudgetServiceClient", ) diff --git a/google/cloud/billing/budgets_v1beta1/gapic_metadata.json b/google/cloud/billing/budgets_v1beta1/gapic_metadata.json new file mode 100644 index 0000000..b510f92 --- /dev/null +++ b/google/cloud/billing/budgets_v1beta1/gapic_metadata.json @@ -0,0 +1,73 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.billing.budgets_v1beta1", + "protoPackage": "google.cloud.billing.budgets.v1beta1", + "schema": "1.0", + "services": { + "BudgetService": { + "clients": { + "grpc": { + "libraryClient": "BudgetServiceClient", + "rpcs": { + "CreateBudget": { + "methods": [ + "create_budget" + ] + }, + "DeleteBudget": { + "methods": [ + "delete_budget" + ] + }, + "GetBudget": { + "methods": [ + "get_budget" + ] + }, + "ListBudgets": { + "methods": [ + "list_budgets" + ] + }, + "UpdateBudget": { + "methods": [ + "update_budget" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BudgetServiceAsyncClient", + "rpcs": { + "CreateBudget": { + "methods": [ + "create_budget" + ] + }, + "DeleteBudget": { + "methods": [ + "delete_budget" + ] + }, + "GetBudget": { + "methods": [ + "get_budget" + ] + }, + "ListBudgets": { + "methods": [ + "list_budgets" + ] + }, + "UpdateBudget": { + "methods": [ + "update_budget" + ] + } + } + } + } + } + } +} diff --git a/google/cloud/billing/budgets_v1beta1/services/__init__.py b/google/cloud/billing/budgets_v1beta1/services/__init__.py index 42ffdf2..4de6597 100644 --- a/google/cloud/billing/budgets_v1beta1/services/__init__.py +++ b/google/cloud/billing/budgets_v1beta1/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/billing/budgets_v1beta1/services/budget_service/__init__.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/__init__.py index 97d50ab..737114a 100644 --- a/google/cloud/billing/budgets_v1beta1/services/budget_service/__init__.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_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 BudgetServiceClient from .async_client import BudgetServiceAsyncClient diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/async_client.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/async_client.py index 5bf5960..c0cfb5a 100644 --- a/google/cloud/billing/budgets_v1beta1/services/budget_service/async_client.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_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,16 +20,15 @@ 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.billing.budgets_v1beta1.services.budget_service import pagers from google.cloud.billing.budgets_v1beta1.types import budget_model from google.cloud.billing.budgets_v1beta1.types import budget_service - from .transports.base import BudgetServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import BudgetServiceGrpcAsyncIOTransport from .client import BudgetServiceClient @@ -50,31 +47,26 @@ class BudgetServiceAsyncClient: budget_path = staticmethod(BudgetServiceClient.budget_path) parse_budget_path = staticmethod(BudgetServiceClient.parse_budget_path) - common_billing_account_path = staticmethod( BudgetServiceClient.common_billing_account_path ) parse_common_billing_account_path = staticmethod( BudgetServiceClient.parse_common_billing_account_path ) - common_folder_path = staticmethod(BudgetServiceClient.common_folder_path) parse_common_folder_path = staticmethod( BudgetServiceClient.parse_common_folder_path ) - common_organization_path = staticmethod( BudgetServiceClient.common_organization_path ) parse_common_organization_path = staticmethod( BudgetServiceClient.parse_common_organization_path ) - common_project_path = staticmethod(BudgetServiceClient.common_project_path) parse_common_project_path = staticmethod( BudgetServiceClient.parse_common_project_path ) - common_location_path = staticmethod(BudgetServiceClient.common_location_path) parse_common_location_path = staticmethod( BudgetServiceClient.parse_common_location_path @@ -82,7 +74,8 @@ class BudgetServiceAsyncClient: @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. @@ -97,7 +90,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 @@ -114,7 +107,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> BudgetServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: BudgetServiceTransport: The transport used by the client instance. @@ -128,12 +121,12 @@ def transport(self) -> BudgetServiceTransport: def __init__( self, *, - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, transport: Union[str, BudgetServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the budget service client. + """Instantiates the budget service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -165,7 +158,6 @@ def __init__( google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport creation failed for any reason. """ - self._client = BudgetServiceClient( credentials=credentials, transport=transport, @@ -189,7 +181,6 @@ async def create_budget( Args: request (:class:`google.cloud.billing.budgets_v1beta1.types.CreateBudgetRequest`): The request object. Request for CreateBudget - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -203,14 +194,13 @@ async def create_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. - request = budget_service.CreateBudgetRequest(request) # Wrap the RPC method; this adds retry and timeout information, @@ -250,7 +240,6 @@ async def update_budget( Args: request (:class:`google.cloud.billing.budgets_v1beta1.types.UpdateBudgetRequest`): The request object. Request for UpdateBudget - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -264,14 +253,13 @@ async def update_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. - request = budget_service.UpdateBudgetRequest(request) # Wrap the RPC method; this adds retry and timeout information, @@ -283,7 +271,8 @@ async def update_budget( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -323,7 +312,6 @@ async def get_budget( Args: request (:class:`google.cloud.billing.budgets_v1beta1.types.GetBudgetRequest`): The request object. Request for GetBudget - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -337,14 +325,13 @@ async def get_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. - request = budget_service.GetBudgetRequest(request) # Wrap the RPC method; this adds retry and timeout information, @@ -356,7 +343,8 @@ async def get_budget( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -394,7 +382,6 @@ async def list_budgets( Args: request (:class:`google.cloud.billing.budgets_v1beta1.types.ListBudgetsRequest`): The request object. Request for ListBudgets - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -410,7 +397,6 @@ async def list_budgets( """ # Create or coerce a protobuf request object. - request = budget_service.ListBudgetsRequest(request) # Wrap the RPC method; this adds retry and timeout information, @@ -422,7 +408,8 @@ async def list_budgets( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -462,7 +449,6 @@ async def delete_budget( Args: request (:class:`google.cloud.billing.budgets_v1beta1.types.DeleteBudgetRequest`): The request object. Request for DeleteBudget - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -470,7 +456,6 @@ async def delete_budget( sent along with the request as metadata. """ # Create or coerce a protobuf request object. - request = budget_service.DeleteBudgetRequest(request) # Wrap the RPC method; this adds retry and timeout information, @@ -482,7 +467,8 @@ async def delete_budget( maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/client.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/client.py index 12f84b3..c135687 100644 --- a/google/cloud/billing/budgets_v1beta1/services/budget_service/client.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_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 @@ -35,7 +33,6 @@ from google.cloud.billing.budgets_v1beta1.services.budget_service import pagers from google.cloud.billing.budgets_v1beta1.types import budget_model from google.cloud.billing.budgets_v1beta1.types import budget_service - from .transports.base import BudgetServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import BudgetServiceGrpcTransport from .transports.grpc_asyncio import BudgetServiceGrpcAsyncIOTransport @@ -54,7 +51,7 @@ class BudgetServiceClientMeta(type): _transport_registry["grpc_asyncio"] = BudgetServiceGrpcAsyncIOTransport def get_transport_class(cls, label: str = None,) -> Type[BudgetServiceTransport]: - """Return an appropriate transport class. + """Returns an appropriate transport class. Args: label: The name of the desired transport. If none is @@ -80,7 +77,8 @@ class BudgetServiceClient(metaclass=BudgetServiceClientMeta): @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: @@ -114,7 +112,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. @@ -131,7 +130,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 @@ -150,23 +149,24 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): @property def transport(self) -> BudgetServiceTransport: - """Return the transport used by the client instance. + """Returns the transport used by the client instance. Returns: - BudgetServiceTransport: The transport used by the client instance. + BudgetServiceTransport: The transport used by the client + instance. """ return self._transport @staticmethod def budget_path(billing_account: str, budget: str,) -> str: - """Return a fully-qualified budget string.""" + """Returns a fully-qualified budget string.""" return "billingAccounts/{billing_account}/budgets/{budget}".format( billing_account=billing_account, budget=budget, ) @staticmethod def parse_budget_path(path: str) -> Dict[str, str]: - """Parse a budget path into its component segments.""" + """Parses a budget path into its component segments.""" m = re.match( r"^billingAccounts/(?P.+?)/budgets/(?P.+?)$", path ) @@ -174,7 +174,7 @@ def parse_budget_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, ) @@ -187,7 +187,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 @@ -198,7 +198,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 @@ -209,7 +209,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 @@ -220,7 +220,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, ) @@ -234,12 +234,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, BudgetServiceTransport, None] = None, client_options: Optional[client_options_lib.ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiate the budget service client. + """Instantiates the budget service client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -294,9 +294,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: @@ -308,12 +309,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. @@ -328,8 +331,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: @@ -360,7 +363,6 @@ def create_budget( Args: request (google.cloud.billing.budgets_v1beta1.types.CreateBudgetRequest): The request object. Request for CreateBudget - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -374,14 +376,13 @@ def create_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes # in a budget_service.CreateBudgetRequest. # There's no risk of modifying the input as we've already verified @@ -422,7 +423,6 @@ def update_budget( Args: request (google.cloud.billing.budgets_v1beta1.types.UpdateBudgetRequest): The request object. Request for UpdateBudget - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -436,14 +436,13 @@ def update_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes # in a budget_service.UpdateBudgetRequest. # There's no risk of modifying the input as we've already verified @@ -487,7 +486,6 @@ def get_budget( Args: request (google.cloud.billing.budgets_v1beta1.types.GetBudgetRequest): The request object. Request for GetBudget - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -501,14 +499,13 @@ def get_budget( projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all - plans are monthly budgets so the usage - period(s) tracked are implied (calendar - months of usage back-to-back). + target spend is met). The budget time + period is configurable, with options + such as month (default), quarter, year, + or custom time period. """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes # in a budget_service.GetBudgetRequest. # There's no risk of modifying the input as we've already verified @@ -550,7 +547,6 @@ def list_budgets( Args: request (google.cloud.billing.budgets_v1beta1.types.ListBudgetsRequest): The request object. Request for ListBudgets - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -566,7 +562,6 @@ def list_budgets( """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes # in a budget_service.ListBudgetsRequest. # There's no risk of modifying the input as we've already verified @@ -610,7 +605,6 @@ def delete_budget( Args: request (google.cloud.billing.budgets_v1beta1.types.DeleteBudgetRequest): The request object. Request for DeleteBudget - retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -618,7 +612,6 @@ def delete_budget( sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes # in a budget_service.DeleteBudgetRequest. # There's no risk of modifying the input as we've already verified diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/pagers.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/pagers.py index 7551f27..bfa27d9 100644 --- a/google/cloud/billing/budgets_v1beta1/services/budget_service/pagers.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_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, @@ -118,7 +116,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/billing/budgets_v1beta1/services/budget_service/transports/__init__.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/__init__.py index 0ab5ac1..f65a2e4 100644 --- a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/__init__.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_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/billing/budgets_v1beta1/services/budget_service/transports/base.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/base.py index 2b57646..af26665 100644 --- a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/base.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_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.billing.budgets_v1beta1.types import budget_model from google.cloud.billing.budgets_v1beta1.types import budget_service -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( @@ -39,6 +38,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 BudgetServiceTransport(abc.ABC): """Abstract transport class for BudgetService.""" @@ -48,21 +58,24 @@ class BudgetServiceTransport(abc.ABC): "https://www.googleapis.com/auth/cloud-platform", ) + DEFAULT_HOST: str = "billingbudgets.googleapis.com" + def __init__( self, *, - host: str = "billingbudgets.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 @@ -71,7 +84,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): @@ -85,29 +98,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 = { @@ -121,7 +181,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -135,7 +196,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -149,7 +211,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -163,7 +226,8 @@ def _prep_wrapped_messages(self, client_info): maximum=60.0, multiplier=1.3, predicate=retries.if_exception_type( - exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, ), deadline=60.0, ), @@ -175,38 +239,38 @@ def _prep_wrapped_messages(self, client_info): @property def create_budget( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.CreateBudgetRequest], - typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + Union[budget_model.Budget, Awaitable[budget_model.Budget]], ]: raise NotImplementedError() @property def update_budget( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.UpdateBudgetRequest], - typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + Union[budget_model.Budget, Awaitable[budget_model.Budget]], ]: raise NotImplementedError() @property def get_budget( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.GetBudgetRequest], - typing.Union[budget_model.Budget, typing.Awaitable[budget_model.Budget]], + Union[budget_model.Budget, Awaitable[budget_model.Budget]], ]: raise NotImplementedError() @property def list_budgets( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.ListBudgetsRequest], - typing.Union[ + Union[ budget_service.ListBudgetsResponse, - typing.Awaitable[budget_service.ListBudgetsResponse], + Awaitable[budget_service.ListBudgetsResponse], ], ]: raise NotImplementedError() @@ -214,9 +278,9 @@ def list_budgets( @property def delete_budget( self, - ) -> typing.Callable[ + ) -> Callable[ [budget_service.DeleteBudgetRequest], - typing.Union[empty.Empty, typing.Awaitable[empty.Empty]], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], ]: raise NotImplementedError() diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc.py index ed0d197..7464528 100644 --- a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_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.billing.budgets_v1beta1.types import budget_model from google.cloud.billing.budgets_v1beta1.types import budget_service -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore from .base import BudgetServiceTransport, DEFAULT_CLIENT_INFO @@ -54,7 +51,7 @@ def __init__( self, *, host: str = "billingbudgets.googleapis.com", - credentials: credentials.Credentials = None, + credentials: ga_credentials.Credentials = None, credentials_file: str = None, scopes: Sequence[str] = None, channel: grpc.Channel = None, @@ -68,7 +65,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 @@ -178,7 +176,7 @@ def __init__( def create_channel( cls, host: str = "billingbudgets.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, @@ -209,13 +207,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, ) @@ -351,7 +351,7 @@ def list_budgets( @property def delete_budget( self, - ) -> Callable[[budget_service.DeleteBudgetRequest], empty.Empty]: + ) -> Callable[[budget_service.DeleteBudgetRequest], empty_pb2.Empty]: r"""Return a callable for the delete budget method over gRPC. Deletes a budget. Returns successfully if already @@ -371,7 +371,7 @@ def delete_budget( self._stubs["delete_budget"] = self.grpc_channel.unary_unary( "/google.cloud.billing.budgets.v1beta1.BudgetService/DeleteBudget", request_serializer=budget_service.DeleteBudgetRequest.serialize, - response_deserializer=empty.Empty.FromString, + response_deserializer=empty_pb2.Empty.FromString, ) return self._stubs["delete_budget"] diff --git a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc_asyncio.py b/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc_asyncio.py index 484dbc2..e15b051 100644 --- a/google/cloud/billing/budgets_v1beta1/services/budget_service/transports/grpc_asyncio.py +++ b/google/cloud/billing/budgets_v1beta1/services/budget_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.billing.budgets_v1beta1.types import budget_model from google.cloud.billing.budgets_v1beta1.types import budget_service -from google.protobuf import empty_pb2 as empty # type: ignore - +from google.protobuf import empty_pb2 # type: ignore from .base import BudgetServiceTransport, DEFAULT_CLIENT_INFO from .grpc import BudgetServiceGrpcTransport @@ -57,7 +54,7 @@ class BudgetServiceGrpcAsyncIOTransport(BudgetServiceTransport): def create_channel( cls, host: str = "billingbudgets.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, @@ -84,13 +81,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, ) @@ -98,7 +97,7 @@ def __init__( self, *, host: str = "billingbudgets.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, @@ -112,7 +111,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 @@ -170,7 +170,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 @@ -356,7 +355,7 @@ def list_budgets( @property def delete_budget( self, - ) -> Callable[[budget_service.DeleteBudgetRequest], Awaitable[empty.Empty]]: + ) -> Callable[[budget_service.DeleteBudgetRequest], Awaitable[empty_pb2.Empty]]: r"""Return a callable for the delete budget method over gRPC. Deletes a budget. Returns successfully if already @@ -376,7 +375,7 @@ def delete_budget( self._stubs["delete_budget"] = self.grpc_channel.unary_unary( "/google.cloud.billing.budgets.v1beta1.BudgetService/DeleteBudget", request_serializer=budget_service.DeleteBudgetRequest.serialize, - response_deserializer=empty.Empty.FromString, + response_deserializer=empty_pb2.Empty.FromString, ) return self._stubs["delete_budget"] diff --git a/google/cloud/billing/budgets_v1beta1/types/__init__.py b/google/cloud/billing/budgets_v1beta1/types/__init__.py index 56a2e86..aac91d6 100644 --- a/google/cloud/billing/budgets_v1beta1/types/__init__.py +++ b/google/cloud/billing/budgets_v1beta1/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,14 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. # - from .budget_model import ( AllUpdatesRule, Budget, BudgetAmount, + CustomPeriod, Filter, LastPeriodAmount, ThresholdRule, + CalendarPeriod, ) from .budget_service import ( CreateBudgetRequest, @@ -36,9 +36,11 @@ "AllUpdatesRule", "Budget", "BudgetAmount", + "CustomPeriod", "Filter", "LastPeriodAmount", "ThresholdRule", + "CalendarPeriod", "CreateBudgetRequest", "DeleteBudgetRequest", "GetBudgetRequest", diff --git a/google/cloud/billing/budgets_v1beta1/types/budget_model.py b/google/cloud/billing/budgets_v1beta1/types/budget_model.py index 89526a9..894a795 100644 --- a/google/cloud/billing/budgets_v1beta1/types/budget_model.py +++ b/google/cloud/billing/budgets_v1beta1/types/budget_model.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,34 +13,47 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - -from google.protobuf import struct_pb2 as struct # type: ignore -from google.type import money_pb2 as money # type: ignore +from google.protobuf import struct_pb2 # type: ignore +from google.type import date_pb2 # type: ignore +from google.type import money_pb2 # type: ignore __protobuf__ = proto.module( package="google.cloud.billing.budgets.v1beta1", manifest={ + "CalendarPeriod", "Budget", "BudgetAmount", "LastPeriodAmount", "ThresholdRule", "AllUpdatesRule", "Filter", + "CustomPeriod", }, ) +class CalendarPeriod(proto.Enum): + r"""A ``CalendarPeriod`` represents the abstract concept of a time + period that has a canonical start. Grammatically, "the start of the + current ``CalendarPeriod``". All calendar times begin at 12 AM US + and Canadian Pacific Time (UTC-8). + """ + CALENDAR_PERIOD_UNSPECIFIED = 0 + MONTH = 1 + QUARTER = 2 + YEAR = 3 + + class Budget(proto.Message): r"""A budget is a plan that describes what you expect to spend on Cloud projects, plus the rules to execute as spend is tracked against that plan, (for example, send an alert when 90% of the - target spend is met). Currently all plans are monthly budgets so - the usage period(s) tracked are implied (calendar months of - usage back-to-back). + target spend is met). The budget time period is configurable, + with options such as month (default), quarter, year, or custom + time period. Attributes: name (str): @@ -54,7 +66,9 @@ class Budget(proto.Message): budget_filter (google.cloud.billing.budgets_v1beta1.types.Filter): Optional. Filters that define which resources are used to compute the actual spend against the - budget. + budget amount, such as projects, services, and + the budget's time period, as well as other + filters. amount (google.cloud.billing.budgets_v1beta1.types.BudgetAmount): Required. Budgeted amount. threshold_rules (Sequence[google.cloud.billing.budgets_v1beta1.types.ThresholdRule]): @@ -72,54 +86,54 @@ class Budget(proto.Message): other changes. """ - name = proto.Field(proto.STRING, number=1) - - display_name = proto.Field(proto.STRING, number=2) - + name = proto.Field(proto.STRING, number=1,) + display_name = proto.Field(proto.STRING, number=2,) budget_filter = proto.Field(proto.MESSAGE, number=3, message="Filter",) - amount = proto.Field(proto.MESSAGE, number=4, message="BudgetAmount",) - threshold_rules = proto.RepeatedField( proto.MESSAGE, number=5, message="ThresholdRule", ) - all_updates_rule = proto.Field(proto.MESSAGE, number=6, message="AllUpdatesRule",) - - etag = proto.Field(proto.STRING, number=7) + etag = proto.Field(proto.STRING, number=7,) class BudgetAmount(proto.Message): r"""The budgeted amount for each usage period. - Attributes: specified_amount (google.type.money_pb2.Money): A specified amount to use as the budget. ``currency_code`` is optional. If specified when creating a budget, it must match the currency of the billing account. If specified when - updating a budget, it must match the existing budget - currency_code. The ``currency_code`` is provided on output. + updating a budget, it must match the currency_code of the + existing budget. The ``currency_code`` is provided on + output. last_period_amount (google.cloud.billing.budgets_v1beta1.types.LastPeriodAmount): - Use the last period's actual spend as the - budget for the present period. + Use the last period's actual spend as the budget for the + present period. LastPeriodAmount can only be set when the + budget's time period is a + [Filter.calendar_period][google.cloud.billing.budgets.v1beta1.Filter.calendar_period]. + It cannot be set in combination with + [Filter.custom_period][google.cloud.billing.budgets.v1beta1.Filter.custom_period]. """ specified_amount = proto.Field( - proto.MESSAGE, number=1, oneof="budget_amount", message=money.Money, + proto.MESSAGE, number=1, oneof="budget_amount", message=money_pb2.Money, ) - last_period_amount = proto.Field( proto.MESSAGE, number=2, oneof="budget_amount", message="LastPeriodAmount", ) class LastPeriodAmount(proto.Message): - r"""Describes a budget amount targeted to last period's spend. - At this time, the amount is automatically 100% of last period's - spend; that is, there are no other options yet. - Future configuration will be described here (for example, - configuring a percentage of last period's spend). - """ + r"""Describes a budget amount targeted to the last + [Filter.calendar_period][google.cloud.billing.budgets.v1beta1.Filter.calendar_period] + spend. At this time, the amount is automatically 100% of the last + calendar period's spend; that is, there are no other options yet. + Future configuration options will be described here (for example, + configuring a percentage of last period's spend). LastPeriodAmount + cannot be set for a budget configured with a + [Filter.custom_period][google.cloud.billing.budgets.v1beta1.Filter.custom_period]. + """ class ThresholdRule(proto.Message): @@ -150,8 +164,7 @@ class Basis(proto.Enum): CURRENT_SPEND = 1 FORECASTED_SPEND = 2 - threshold_percent = proto.Field(proto.DOUBLE, number=1) - + threshold_percent = proto.Field(proto.DOUBLE, number=1,) spend_basis = proto.Field(proto.ENUM, number=2, enum=Basis,) @@ -166,12 +179,12 @@ class AllUpdatesRule(proto.Message): ``projects/{project_id}/topics/{topic_id}``. Updates are sent at regular intervals to the topic. The topic needs to be created before the budget is created; see - https://cloud.google.com/billing/docs/how-to/budgets#manage-notifications + https://cloud.google.com/billing/docs/how-to/budgets-programmatic-notifications for more details. Caller is expected to have ``pubsub.topics.setIamPolicy`` permission on the topic when it's set for a budget, otherwise, the API call will fail with PERMISSION_DENIED. See - https://cloud.google.com/billing/docs/how-to/budgets-programmatic-notifications + https://cloud.google.com/billing/docs/how-to/budgets-programmatic-notifications#permissions_required_for_this_task for more details on Pub/Sub roles and permissions. schema_version (str): Optional. Required when @@ -199,13 +212,10 @@ class AllUpdatesRule(proto.Message): Account User IAM roles for the target account. """ - pubsub_topic = proto.Field(proto.STRING, number=1) - - schema_version = proto.Field(proto.STRING, number=2) - - monitoring_notification_channels = proto.RepeatedField(proto.STRING, number=3) - - disable_default_iam_recipients = proto.Field(proto.BOOL, number=4) + pubsub_topic = proto.Field(proto.STRING, number=1,) + schema_version = proto.Field(proto.STRING, number=2,) + monitoring_notification_channels = proto.RepeatedField(proto.STRING, number=3,) + disable_default_iam_recipients = proto.Field(proto.BOOL, number=4,) class Filter(proto.Message): @@ -225,13 +235,14 @@ class Filter(proto.Message): [Filter.credit_types_treatment][google.cloud.billing.budgets.v1beta1.Filter.credit_types_treatment] is INCLUDE_SPECIFIED_CREDITS, this is a list of credit types to be subtracted from gross cost to determine the spend for - threshold calculations. + threshold calculations. See `a list of acceptable credit + type + values `__. If [Filter.credit_types_treatment][google.cloud.billing.budgets.v1beta1.Filter.credit_types_treatment] is **not** INCLUDE_SPECIFIED_CREDITS, this field must be - empty. See `a list of acceptable credit type - values `__. + empty. credit_types_treatment (google.cloud.billing.budgets_v1beta1.types.Filter.CreditTypesTreatment): Optional. If not set, default behavior is ``INCLUDE_ALL_CREDITS``. @@ -258,32 +269,68 @@ class Filter(proto.Message): values per entry are not allowed. If omitted, the report will include all labeled and unlabeled usage. + calendar_period (google.cloud.billing.budgets_v1beta1.types.CalendarPeriod): + Optional. Specifies to track usage for + recurring calendar period. For example, assume + that CalendarPeriod.QUARTER is set. The budget + will track usage from April 1 to June 30, when + the current calendar month is April, May, June. + After that, it will track usage from July 1 to + September 30 when the current calendar month is + July, August, September, so on. + custom_period (google.cloud.billing.budgets_v1beta1.types.CustomPeriod): + Optional. Specifies to track usage from any + start date (required) to any end date + (optional). This time period is static, it does + not recur. """ class CreditTypesTreatment(proto.Enum): - r"""Specifies how credits should be treated when determining - spend for threshold calculations. + r"""Specifies how credits are applied when determining the spend for + threshold calculations. Budgets track the total cost minus any + applicable selected credits. `See the documentation for a list of + credit + types `__. """ CREDIT_TYPES_TREATMENT_UNSPECIFIED = 0 INCLUDE_ALL_CREDITS = 1 EXCLUDE_ALL_CREDITS = 2 INCLUDE_SPECIFIED_CREDITS = 3 - projects = proto.RepeatedField(proto.STRING, number=1) - - credit_types = proto.RepeatedField(proto.STRING, number=7) - + projects = proto.RepeatedField(proto.STRING, number=1,) + credit_types = proto.RepeatedField(proto.STRING, number=7,) credit_types_treatment = proto.Field( proto.ENUM, number=4, enum=CreditTypesTreatment, ) + services = proto.RepeatedField(proto.STRING, number=3,) + subaccounts = proto.RepeatedField(proto.STRING, number=5,) + labels = proto.MapField( + proto.STRING, proto.MESSAGE, number=6, message=struct_pb2.ListValue, + ) + calendar_period = proto.Field( + proto.ENUM, number=8, oneof="usage_period", enum="CalendarPeriod", + ) + custom_period = proto.Field( + proto.MESSAGE, number=9, oneof="usage_period", message="CustomPeriod", + ) - services = proto.RepeatedField(proto.STRING, number=3) - subaccounts = proto.RepeatedField(proto.STRING, number=5) +class CustomPeriod(proto.Message): + r"""All date times begin at 12 AM US and Canadian Pacific Time + (UTC-8). - labels = proto.MapField( - proto.STRING, proto.MESSAGE, number=6, message=struct.ListValue, - ) + Attributes: + start_date (google.type.date_pb2.Date): + Required. The start date must be after + January 1, 2017. + end_date (google.type.date_pb2.Date): + Optional. The end date of the time period. Budgets with + elapsed end date won't be processed. If unset, specifies to + track all usage incurred since the start_date. + """ + + start_date = proto.Field(proto.MESSAGE, number=1, message=date_pb2.Date,) + end_date = proto.Field(proto.MESSAGE, number=2, message=date_pb2.Date,) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/billing/budgets_v1beta1/types/budget_service.py b/google/cloud/billing/budgets_v1beta1/types/budget_service.py index eee85c5..4f40a75 100644 --- a/google/cloud/billing/budgets_v1beta1/types/budget_service.py +++ b/google/cloud/billing/budgets_v1beta1/types/budget_service.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,12 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # - import proto # type: ignore - from google.cloud.billing.budgets_v1beta1.types import budget_model -from google.protobuf import field_mask_pb2 as field_mask # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore __protobuf__ = proto.module( @@ -37,7 +34,6 @@ class CreateBudgetRequest(proto.Message): r"""Request for CreateBudget - Attributes: parent (str): Required. The name of the billing account to create the @@ -47,14 +43,12 @@ class CreateBudgetRequest(proto.Message): Required. Budget to create. """ - parent = proto.Field(proto.STRING, number=1) - + parent = proto.Field(proto.STRING, number=1,) budget = proto.Field(proto.MESSAGE, number=2, message=budget_model.Budget,) class UpdateBudgetRequest(proto.Message): r"""Request for UpdateBudget - Attributes: budget (google.cloud.billing.budgets_v1beta1.types.Budget): Required. The updated budget object. @@ -70,25 +64,24 @@ class UpdateBudgetRequest(proto.Message): """ budget = proto.Field(proto.MESSAGE, number=1, message=budget_model.Budget,) - - update_mask = proto.Field(proto.MESSAGE, number=2, message=field_mask.FieldMask,) + update_mask = proto.Field( + proto.MESSAGE, number=2, message=field_mask_pb2.FieldMask, + ) class GetBudgetRequest(proto.Message): r"""Request for GetBudget - Attributes: name (str): Required. Name of budget to get. Values are of the form ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. """ - name = proto.Field(proto.STRING, number=1) + name = proto.Field(proto.STRING, number=1,) class ListBudgetsRequest(proto.Message): r"""Request for ListBudgets - Attributes: parent (str): Required. Name of billing account to list budgets under. @@ -105,16 +98,13 @@ class ListBudgetsRequest(proto.Message): system should return the next page of data. """ - parent = proto.Field(proto.STRING, number=1) - - page_size = proto.Field(proto.INT32, number=2) - - page_token = proto.Field(proto.STRING, number=3) + parent = proto.Field(proto.STRING, number=1,) + page_size = proto.Field(proto.INT32, number=2,) + page_token = proto.Field(proto.STRING, number=3,) class ListBudgetsResponse(proto.Message): r"""Response for ListBudgets - Attributes: budgets (Sequence[google.cloud.billing.budgets_v1beta1.types.Budget]): List of the budgets owned by the requested @@ -130,13 +120,11 @@ def raw_page(self): return self budgets = proto.RepeatedField(proto.MESSAGE, number=1, message=budget_model.Budget,) - - next_page_token = proto.Field(proto.STRING, number=2) + next_page_token = proto.Field(proto.STRING, number=2,) class DeleteBudgetRequest(proto.Message): r"""Request for DeleteBudget - Attributes: name (str): Required. Name of the budget to delete. Values are of the @@ -144,7 +132,7 @@ class DeleteBudgetRequest(proto.Message): ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. """ - name = proto.Field(proto.STRING, number=1) + name = proto.Field(proto.STRING, number=1,) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/scripts/fixup_budgets_v1_keywords.py b/scripts/fixup_budgets_v1_keywords.py index ebf535e..80e9450 100644 --- a/scripts/fixup_budgets_v1_keywords.py +++ b/scripts/fixup_budgets_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,12 +39,11 @@ def partition( class budgetsCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'create_budget': ('parent', 'budget', ), - 'delete_budget': ('name', ), - 'get_budget': ('name', ), - 'list_budgets': ('parent', 'page_size', 'page_token', ), - 'update_budget': ('budget', 'update_mask', ), - + 'create_budget': ('parent', 'budget', ), + 'delete_budget': ('name', ), + 'get_budget': ('name', ), + 'list_budgets': ('parent', 'page_size', 'page_token', ), + 'update_budget': ('budget', 'update_mask', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: @@ -77,7 +74,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_budgets_v1beta1_keywords.py b/scripts/fixup_budgets_v1beta1_keywords.py index ebf535e..80e9450 100644 --- a/scripts/fixup_budgets_v1beta1_keywords.py +++ b/scripts/fixup_budgets_v1beta1_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,12 +39,11 @@ def partition( class budgetsCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'create_budget': ('parent', 'budget', ), - 'delete_budget': ('name', ), - 'get_budget': ('name', ), - 'list_budgets': ('parent', 'page_size', 'page_token', ), - 'update_budget': ('budget', 'update_mask', ), - + 'create_budget': ('parent', 'budget', ), + 'delete_budget': ('name', ), + 'get_budget': ('name', ), + 'list_budgets': ('parent', 'page_size', 'page_token', ), + 'update_budget': ('budget', 'update_mask', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: @@ -77,7 +74,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/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..4de6597 --- /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 0000000..4de6597 --- /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 0000000..4de6597 --- /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/budgets_v1/__init__.py b/tests/unit/gapic/budgets_v1/__init__.py index 42ffdf2..4de6597 100644 --- a/tests/unit/gapic/budgets_v1/__init__.py +++ b/tests/unit/gapic/budgets_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/budgets_v1/test_budget_service.py b/tests/unit/gapic/budgets_v1/test_budget_service.py index 5258264..7ce7bee 100644 --- a/tests/unit/gapic/budgets_v1/test_budget_service.py +++ b/tests/unit/gapic/budgets_v1/test_budget_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,13 +23,13 @@ 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.billing.budgets_v1.services.budget_service import ( BudgetServiceAsyncClient, @@ -38,12 +37,43 @@ from google.cloud.billing.budgets_v1.services.budget_service import BudgetServiceClient from google.cloud.billing.budgets_v1.services.budget_service import pagers from google.cloud.billing.budgets_v1.services.budget_service import transports +from google.cloud.billing.budgets_v1.services.budget_service.transports.base import ( + _API_CORE_VERSION, +) +from google.cloud.billing.budgets_v1.services.budget_service.transports.base import ( + _GOOGLE_AUTH_VERSION, +) from google.cloud.billing.budgets_v1.types import budget_model from google.cloud.billing.budgets_v1.types import budget_service from google.oauth2 import service_account -from google.protobuf import field_mask_pb2 as field_mask # type: ignore -from google.protobuf import struct_pb2 as struct # type: ignore -from google.type import money_pb2 as money # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import struct_pb2 # type: ignore +from google.type import date_pb2 # type: ignore +from google.type import money_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(): @@ -94,7 +124,7 @@ def test__get_default_mtls_endpoint(): "client_class", [BudgetServiceClient, BudgetServiceAsyncClient,] ) def test_budget_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: @@ -111,7 +141,7 @@ def test_budget_service_client_from_service_account_info(client_class): "client_class", [BudgetServiceClient, BudgetServiceAsyncClient,] ) def test_budget_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: @@ -164,7 +194,7 @@ def test_budget_service_client_client_options( ): # Check that if channel is provided we won't create a new one. with mock.patch.object(BudgetServiceClient, "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() @@ -452,7 +482,7 @@ def test_create_budget( transport: str = "grpc", request_type=budget_service.CreateBudgetRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -465,23 +495,17 @@ def test_create_budget( call.return_value = budget_model.Budget( name="name_value", display_name="display_name_value", etag="etag_value", ) - response = client.create_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.CreateBudgetRequest() # Establish that the response is the type that we expect. - assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -493,7 +517,7 @@ def test_create_budget_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -501,7 +525,6 @@ def test_create_budget_empty_call(): client.create_budget() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.CreateBudgetRequest() @@ -510,7 +533,7 @@ async def test_create_budget_async( transport: str = "grpc_asyncio", request_type=budget_service.CreateBudgetRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -525,22 +548,17 @@ async def test_create_budget_async( name="name_value", display_name="display_name_value", etag="etag_value", ) ) - response = await client.create_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.CreateBudgetRequest() # Establish that the response is the type that we expect. assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -550,17 +568,17 @@ async def test_create_budget_async_from_dict(): def test_create_budget_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.CreateBudgetRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_budget), "__call__") as call: call.return_value = budget_model.Budget() - client.create_budget(request) # Establish that the underlying gRPC stub method was called. @@ -575,17 +593,19 @@ def test_create_budget_field_headers(): @pytest.mark.asyncio async def test_create_budget_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.CreateBudgetRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_budget), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) - await client.create_budget(request) # Establish that the underlying gRPC stub method was called. @@ -599,13 +619,12 @@ async def test_create_budget_field_headers_async(): def test_create_budget_flattened(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_budget), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = budget_model.Budget() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.create_budget( @@ -616,14 +635,12 @@ def test_create_budget_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].budget == budget_model.Budget(name="name_value") def test_create_budget_flattened_error(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -637,7 +654,9 @@ def test_create_budget_flattened_error(): @pytest.mark.asyncio async def test_create_budget_flattened_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_budget), "__call__") as call: @@ -655,15 +674,15 @@ async def test_create_budget_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].budget == budget_model.Budget(name="name_value") @pytest.mark.asyncio async def test_create_budget_flattened_error_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -679,7 +698,7 @@ def test_update_budget( transport: str = "grpc", request_type=budget_service.UpdateBudgetRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -692,23 +711,17 @@ def test_update_budget( call.return_value = budget_model.Budget( name="name_value", display_name="display_name_value", etag="etag_value", ) - response = client.update_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.UpdateBudgetRequest() # Establish that the response is the type that we expect. - assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -720,7 +733,7 @@ def test_update_budget_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -728,7 +741,6 @@ def test_update_budget_empty_call(): client.update_budget() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.UpdateBudgetRequest() @@ -737,7 +749,7 @@ async def test_update_budget_async( transport: str = "grpc_asyncio", request_type=budget_service.UpdateBudgetRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -752,22 +764,17 @@ async def test_update_budget_async( name="name_value", display_name="display_name_value", etag="etag_value", ) ) - response = await client.update_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.UpdateBudgetRequest() # Establish that the response is the type that we expect. assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -777,17 +784,17 @@ async def test_update_budget_async_from_dict(): def test_update_budget_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.UpdateBudgetRequest() + request.budget.name = "budget.name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_budget), "__call__") as call: call.return_value = budget_model.Budget() - client.update_budget(request) # Establish that the underlying gRPC stub method was called. @@ -802,17 +809,19 @@ def test_update_budget_field_headers(): @pytest.mark.asyncio async def test_update_budget_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.UpdateBudgetRequest() + request.budget.name = "budget.name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_budget), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) - await client.update_budget(request) # Establish that the underlying gRPC stub method was called. @@ -826,32 +835,29 @@ async def test_update_budget_field_headers_async(): def test_update_budget_flattened(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_budget), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = budget_model.Budget() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.update_budget( budget=budget_model.Budget(name="name_value"), - update_mask=field_mask.FieldMask(paths=["paths_value"]), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].budget == budget_model.Budget(name="name_value") - - assert args[0].update_mask == field_mask.FieldMask(paths=["paths_value"]) + assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) def test_update_budget_flattened_error(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -859,13 +865,15 @@ def test_update_budget_flattened_error(): client.update_budget( budget_service.UpdateBudgetRequest(), budget=budget_model.Budget(name="name_value"), - update_mask=field_mask.FieldMask(paths=["paths_value"]), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) @pytest.mark.asyncio async def test_update_budget_flattened_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_budget), "__call__") as call: @@ -877,22 +885,22 @@ async def test_update_budget_flattened_async(): # using the keyword arguments to the method. response = await client.update_budget( budget=budget_model.Budget(name="name_value"), - update_mask=field_mask.FieldMask(paths=["paths_value"]), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].budget == budget_model.Budget(name="name_value") - - assert args[0].update_mask == field_mask.FieldMask(paths=["paths_value"]) + assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) @pytest.mark.asyncio async def test_update_budget_flattened_error_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -900,7 +908,7 @@ async def test_update_budget_flattened_error_async(): await client.update_budget( budget_service.UpdateBudgetRequest(), budget=budget_model.Budget(name="name_value"), - update_mask=field_mask.FieldMask(paths=["paths_value"]), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) @@ -908,7 +916,7 @@ def test_get_budget( transport: str = "grpc", request_type=budget_service.GetBudgetRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -921,23 +929,17 @@ def test_get_budget( call.return_value = budget_model.Budget( name="name_value", display_name="display_name_value", etag="etag_value", ) - response = client.get_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.GetBudgetRequest() # Establish that the response is the type that we expect. - assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -949,7 +951,7 @@ def test_get_budget_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -957,7 +959,6 @@ def test_get_budget_empty_call(): client.get_budget() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.GetBudgetRequest() @@ -966,7 +967,7 @@ async def test_get_budget_async( transport: str = "grpc_asyncio", request_type=budget_service.GetBudgetRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -981,22 +982,17 @@ async def test_get_budget_async( name="name_value", display_name="display_name_value", etag="etag_value", ) ) - response = await client.get_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.GetBudgetRequest() # Establish that the response is the type that we expect. assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -1006,17 +1002,17 @@ async def test_get_budget_async_from_dict(): def test_get_budget_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.GetBudgetRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_budget), "__call__") as call: call.return_value = budget_model.Budget() - client.get_budget(request) # Establish that the underlying gRPC stub method was called. @@ -1031,17 +1027,19 @@ def test_get_budget_field_headers(): @pytest.mark.asyncio async def test_get_budget_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.GetBudgetRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_budget), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) - await client.get_budget(request) # Establish that the underlying gRPC stub method was called. @@ -1055,13 +1053,12 @@ async def test_get_budget_field_headers_async(): def test_get_budget_flattened(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_budget), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = budget_model.Budget() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.get_budget(name="name_value",) @@ -1070,12 +1067,11 @@ def test_get_budget_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" def test_get_budget_flattened_error(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1087,7 +1083,9 @@ def test_get_budget_flattened_error(): @pytest.mark.asyncio async def test_get_budget_flattened_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_budget), "__call__") as call: @@ -1103,13 +1101,14 @@ async def test_get_budget_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" @pytest.mark.asyncio async def test_get_budget_flattened_error_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1123,7 +1122,7 @@ def test_list_budgets( transport: str = "grpc", request_type=budget_service.ListBudgetsRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -1136,19 +1135,15 @@ def test_list_budgets( call.return_value = budget_service.ListBudgetsResponse( next_page_token="next_page_token_value", ) - response = client.list_budgets(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.ListBudgetsRequest() # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListBudgetsPager) - assert response.next_page_token == "next_page_token_value" @@ -1160,7 +1155,7 @@ def test_list_budgets_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1168,7 +1163,6 @@ def test_list_budgets_empty_call(): client.list_budgets() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.ListBudgetsRequest() @@ -1177,7 +1171,7 @@ async def test_list_budgets_async( transport: str = "grpc_asyncio", request_type=budget_service.ListBudgetsRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -1190,18 +1184,15 @@ async def test_list_budgets_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( budget_service.ListBudgetsResponse(next_page_token="next_page_token_value",) ) - response = await client.list_budgets(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.ListBudgetsRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListBudgetsAsyncPager) - assert response.next_page_token == "next_page_token_value" @@ -1211,17 +1202,17 @@ async def test_list_budgets_async_from_dict(): def test_list_budgets_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.ListBudgetsRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_budgets), "__call__") as call: call.return_value = budget_service.ListBudgetsResponse() - client.list_budgets(request) # Establish that the underlying gRPC stub method was called. @@ -1236,11 +1227,14 @@ def test_list_budgets_field_headers(): @pytest.mark.asyncio async def test_list_budgets_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.ListBudgetsRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. @@ -1248,7 +1242,6 @@ async def test_list_budgets_field_headers_async(): call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( budget_service.ListBudgetsResponse() ) - await client.list_budgets(request) # Establish that the underlying gRPC stub method was called. @@ -1262,13 +1255,12 @@ async def test_list_budgets_field_headers_async(): def test_list_budgets_flattened(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_budgets), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = budget_service.ListBudgetsResponse() - # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. client.list_budgets(parent="parent_value",) @@ -1277,12 +1269,11 @@ def test_list_budgets_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" def test_list_budgets_flattened_error(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1294,7 +1285,9 @@ def test_list_budgets_flattened_error(): @pytest.mark.asyncio async def test_list_budgets_flattened_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_budgets), "__call__") as call: @@ -1312,13 +1305,14 @@ async def test_list_budgets_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" @pytest.mark.asyncio async def test_list_budgets_flattened_error_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1329,7 +1323,7 @@ async def test_list_budgets_flattened_error_async(): def test_list_budgets_pager(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials,) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_budgets), "__call__") as call: @@ -1367,7 +1361,7 @@ def test_list_budgets_pager(): def test_list_budgets_pages(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials,) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_budgets), "__call__") as call: @@ -1397,7 +1391,7 @@ def test_list_budgets_pages(): @pytest.mark.asyncio async def test_list_budgets_async_pager(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + client = BudgetServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -1434,7 +1428,7 @@ async def test_list_budgets_async_pager(): @pytest.mark.asyncio async def test_list_budgets_async_pages(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + client = BudgetServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -1470,7 +1464,7 @@ def test_delete_budget( transport: str = "grpc", request_type=budget_service.DeleteBudgetRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -1481,13 +1475,11 @@ def test_delete_budget( with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = None - response = client.delete_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.DeleteBudgetRequest() # Establish that the response is the type that we expect. @@ -1502,7 +1494,7 @@ def test_delete_budget_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1510,7 +1502,6 @@ def test_delete_budget_empty_call(): client.delete_budget() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.DeleteBudgetRequest() @@ -1519,7 +1510,7 @@ async def test_delete_budget_async( transport: str = "grpc_asyncio", request_type=budget_service.DeleteBudgetRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -1530,13 +1521,11 @@ async def test_delete_budget_async( with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - response = await client.delete_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.DeleteBudgetRequest() # Establish that the response is the type that we expect. @@ -1549,17 +1538,17 @@ async def test_delete_budget_async_from_dict(): def test_delete_budget_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.DeleteBudgetRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: call.return_value = None - client.delete_budget(request) # Establish that the underlying gRPC stub method was called. @@ -1574,17 +1563,19 @@ def test_delete_budget_field_headers(): @pytest.mark.asyncio async def test_delete_budget_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.DeleteBudgetRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - await client.delete_budget(request) # Establish that the underlying gRPC stub method was called. @@ -1598,13 +1589,12 @@ async def test_delete_budget_field_headers_async(): def test_delete_budget_flattened(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_budget), "__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.delete_budget(name="name_value",) @@ -1613,12 +1603,11 @@ def test_delete_budget_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" def test_delete_budget_flattened_error(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1630,7 +1619,9 @@ def test_delete_budget_flattened_error(): @pytest.mark.asyncio async def test_delete_budget_flattened_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: @@ -1646,13 +1637,14 @@ async def test_delete_budget_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" @pytest.mark.asyncio async def test_delete_budget_flattened_error_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Attempting to call a method with both a request object and flattened # fields is an error. @@ -1665,16 +1657,16 @@ async def test_delete_budget_flattened_error_async(): def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. transport = transports.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = BudgetServiceClient( - 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.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = BudgetServiceClient( @@ -1684,7 +1676,7 @@ def test_credentials_transport_error(): # It is an error to provide scopes and a transport instance. transport = transports.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = BudgetServiceClient( @@ -1695,7 +1687,7 @@ def test_credentials_transport_error(): def test_transport_instance(): # A client may be instantiated with a custom transport instance. transport = transports.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) client = BudgetServiceClient(transport=transport) assert client.transport is transport @@ -1704,13 +1696,13 @@ def test_transport_instance(): def test_transport_get_channel(): # A client may be instantiated with a custom transport instance. transport = transports.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel transport = transports.BudgetServiceGrpcAsyncIOTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel @@ -1725,23 +1717,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 = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) assert isinstance(client.transport, transports.BudgetServiceGrpcTransport,) def test_budget_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.BudgetServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), credentials_file="credentials.json", ) @@ -1753,7 +1745,7 @@ def test_budget_service_base_transport(): ) as Transport: Transport.return_value = None transport = transports.BudgetServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Every method on the transport should just blindly @@ -1770,15 +1762,40 @@ def test_budget_service_base_transport(): getattr(transport, method)(request=object()) +@requires_google_auth_gte_1_25_0 def test_budget_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.billing.budgets_v1.services.budget_service.transports.BudgetServiceTransport._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.BudgetServiceTransport( + 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-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id="octopus", + ) + + +@requires_google_auth_lt_1_25_0 +def test_budget_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.billing.budgets_v1.services.budget_service.transports.BudgetServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.BudgetServiceTransport( credentials_file="credentials.json", quota_project_id="octopus", ) @@ -1794,19 +1811,36 @@ def test_budget_service_base_transport_with_credentials_file(): def test_budget_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.billing.budgets_v1.services.budget_service.transports.BudgetServiceTransport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - adc.return_value = (credentials.AnonymousCredentials(), None) + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.BudgetServiceTransport() adc.assert_called_once() +@requires_google_auth_gte_1_25_0 def test_budget_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) + BudgetServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/cloud-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id=None, + ) + + +@requires_google_auth_lt_1_25_0 +def test_budget_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) BudgetServiceClient() adc.assert_called_once_with( scopes=( @@ -1817,14 +1851,44 @@ def test_budget_service_auth_adc(): ) -def test_budget_service_transport_auth_adc(): +@pytest.mark.parametrize( + "transport_class", + [ + transports.BudgetServiceGrpcTransport, + transports.BudgetServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_gte_1_25_0 +def test_budget_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.BudgetServiceGrpcTransport( - 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-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id="octopus", ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.BudgetServiceGrpcTransport, + transports.BudgetServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_lt_1_25_0 +def test_budget_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-billing", @@ -1834,6 +1898,121 @@ def test_budget_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.BudgetServiceGrpcTransport, grpc_helpers), + (transports.BudgetServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_gte_1_26_0 +def test_budget_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( + "billingbudgets.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=( + "https://www.googleapis.com/auth/cloud-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + scopes=["1", "2"], + default_host="billingbudgets.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.BudgetServiceGrpcTransport, grpc_helpers), + (transports.BudgetServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_budget_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( + "billingbudgets.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=( + "https://www.googleapis.com/auth/cloud-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.BudgetServiceGrpcTransport, grpc_helpers), + (transports.BudgetServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_budget_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( + "billingbudgets.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", [ @@ -1842,7 +2021,7 @@ def test_budget_service_transport_auth_adc(): ], ) def test_budget_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: @@ -1884,7 +2063,7 @@ def test_budget_service_grpc_transport_client_cert_source_for_mtls(transport_cla def test_budget_service_host_no_port(): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="billingbudgets.googleapis.com" ), @@ -1894,7 +2073,7 @@ def test_budget_service_host_no_port(): def test_budget_service_host_with_port(): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="billingbudgets.googleapis.com:8000" ), @@ -1948,9 +2127,9 @@ def test_budget_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", @@ -2033,7 +2212,6 @@ def test_budget_service_transport_channel_mtls_with_adc(transport_class): def test_budget_path(): billing_account = "squid" budget = "clam" - expected = "billingAccounts/{billing_account}/budgets/{budget}".format( billing_account=billing_account, budget=budget, ) @@ -2055,7 +2233,6 @@ def test_parse_budget_path(): def test_common_billing_account_path(): billing_account = "oyster" - expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -2076,7 +2253,6 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): folder = "cuttlefish" - expected = "folders/{folder}".format(folder=folder,) actual = BudgetServiceClient.common_folder_path(folder) assert expected == actual @@ -2095,7 +2271,6 @@ def test_parse_common_folder_path(): def test_common_organization_path(): organization = "winkle" - expected = "organizations/{organization}".format(organization=organization,) actual = BudgetServiceClient.common_organization_path(organization) assert expected == actual @@ -2114,7 +2289,6 @@ def test_parse_common_organization_path(): def test_common_project_path(): project = "scallop" - expected = "projects/{project}".format(project=project,) actual = BudgetServiceClient.common_project_path(project) assert expected == actual @@ -2134,7 +2308,6 @@ def test_parse_common_project_path(): def test_common_location_path(): project = "squid" location = "clam" - expected = "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -2161,7 +2334,7 @@ def test_client_withDEFAULT_CLIENT_INFO(): transports.BudgetServiceTransport, "_prep_wrapped_messages" ) as prep: client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) @@ -2170,6 +2343,6 @@ def test_client_withDEFAULT_CLIENT_INFO(): ) as prep: transport_class = BudgetServiceClient.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/budgets_v1beta1/__init__.py b/tests/unit/gapic/budgets_v1beta1/__init__.py index 42ffdf2..4de6597 100644 --- a/tests/unit/gapic/budgets_v1beta1/__init__.py +++ b/tests/unit/gapic/budgets_v1beta1/__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/budgets_v1beta1/test_budget_service.py b/tests/unit/gapic/budgets_v1beta1/test_budget_service.py index 19f50cc..09a8b0c 100644 --- a/tests/unit/gapic/budgets_v1beta1/test_budget_service.py +++ b/tests/unit/gapic/budgets_v1beta1/test_budget_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,13 +23,13 @@ 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.billing.budgets_v1beta1.services.budget_service import ( BudgetServiceAsyncClient, @@ -40,12 +39,43 @@ ) from google.cloud.billing.budgets_v1beta1.services.budget_service import pagers from google.cloud.billing.budgets_v1beta1.services.budget_service import transports +from google.cloud.billing.budgets_v1beta1.services.budget_service.transports.base import ( + _API_CORE_VERSION, +) +from google.cloud.billing.budgets_v1beta1.services.budget_service.transports.base import ( + _GOOGLE_AUTH_VERSION, +) from google.cloud.billing.budgets_v1beta1.types import budget_model from google.cloud.billing.budgets_v1beta1.types import budget_service from google.oauth2 import service_account -from google.protobuf import field_mask_pb2 as field_mask # type: ignore -from google.protobuf import struct_pb2 as struct # type: ignore -from google.type import money_pb2 as money # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import struct_pb2 # type: ignore +from google.type import date_pb2 # type: ignore +from google.type import money_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(): @@ -96,7 +126,7 @@ def test__get_default_mtls_endpoint(): "client_class", [BudgetServiceClient, BudgetServiceAsyncClient,] ) def test_budget_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: @@ -113,7 +143,7 @@ def test_budget_service_client_from_service_account_info(client_class): "client_class", [BudgetServiceClient, BudgetServiceAsyncClient,] ) def test_budget_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: @@ -166,7 +196,7 @@ def test_budget_service_client_client_options( ): # Check that if channel is provided we won't create a new one. with mock.patch.object(BudgetServiceClient, "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() @@ -454,7 +484,7 @@ def test_create_budget( transport: str = "grpc", request_type=budget_service.CreateBudgetRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -467,23 +497,17 @@ def test_create_budget( call.return_value = budget_model.Budget( name="name_value", display_name="display_name_value", etag="etag_value", ) - response = client.create_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.CreateBudgetRequest() # Establish that the response is the type that we expect. - assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -495,7 +519,7 @@ def test_create_budget_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -503,7 +527,6 @@ def test_create_budget_empty_call(): client.create_budget() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.CreateBudgetRequest() @@ -512,7 +535,7 @@ async def test_create_budget_async( transport: str = "grpc_asyncio", request_type=budget_service.CreateBudgetRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -527,22 +550,17 @@ async def test_create_budget_async( name="name_value", display_name="display_name_value", etag="etag_value", ) ) - response = await client.create_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.CreateBudgetRequest() # Establish that the response is the type that we expect. assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -552,17 +570,17 @@ async def test_create_budget_async_from_dict(): def test_create_budget_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.CreateBudgetRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_budget), "__call__") as call: call.return_value = budget_model.Budget() - client.create_budget(request) # Establish that the underlying gRPC stub method was called. @@ -577,17 +595,19 @@ def test_create_budget_field_headers(): @pytest.mark.asyncio async def test_create_budget_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.CreateBudgetRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_budget), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) - await client.create_budget(request) # Establish that the underlying gRPC stub method was called. @@ -604,7 +624,7 @@ def test_update_budget( transport: str = "grpc", request_type=budget_service.UpdateBudgetRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -617,23 +637,17 @@ def test_update_budget( call.return_value = budget_model.Budget( name="name_value", display_name="display_name_value", etag="etag_value", ) - response = client.update_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.UpdateBudgetRequest() # Establish that the response is the type that we expect. - assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -645,7 +659,7 @@ def test_update_budget_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -653,7 +667,6 @@ def test_update_budget_empty_call(): client.update_budget() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.UpdateBudgetRequest() @@ -662,7 +675,7 @@ async def test_update_budget_async( transport: str = "grpc_asyncio", request_type=budget_service.UpdateBudgetRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -677,22 +690,17 @@ async def test_update_budget_async( name="name_value", display_name="display_name_value", etag="etag_value", ) ) - response = await client.update_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.UpdateBudgetRequest() # Establish that the response is the type that we expect. assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -702,17 +710,17 @@ async def test_update_budget_async_from_dict(): def test_update_budget_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.UpdateBudgetRequest() + request.budget.name = "budget.name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_budget), "__call__") as call: call.return_value = budget_model.Budget() - client.update_budget(request) # Establish that the underlying gRPC stub method was called. @@ -727,17 +735,19 @@ def test_update_budget_field_headers(): @pytest.mark.asyncio async def test_update_budget_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.UpdateBudgetRequest() + request.budget.name = "budget.name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_budget), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) - await client.update_budget(request) # Establish that the underlying gRPC stub method was called. @@ -754,7 +764,7 @@ def test_get_budget( transport: str = "grpc", request_type=budget_service.GetBudgetRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -767,23 +777,17 @@ def test_get_budget( call.return_value = budget_model.Budget( name="name_value", display_name="display_name_value", etag="etag_value", ) - response = client.get_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.GetBudgetRequest() # Establish that the response is the type that we expect. - assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -795,7 +799,7 @@ def test_get_budget_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -803,7 +807,6 @@ def test_get_budget_empty_call(): client.get_budget() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.GetBudgetRequest() @@ -812,7 +815,7 @@ async def test_get_budget_async( transport: str = "grpc_asyncio", request_type=budget_service.GetBudgetRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -827,22 +830,17 @@ async def test_get_budget_async( name="name_value", display_name="display_name_value", etag="etag_value", ) ) - response = await client.get_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.GetBudgetRequest() # Establish that the response is the type that we expect. assert isinstance(response, budget_model.Budget) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert response.etag == "etag_value" @@ -852,17 +850,17 @@ async def test_get_budget_async_from_dict(): def test_get_budget_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.GetBudgetRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_budget), "__call__") as call: call.return_value = budget_model.Budget() - client.get_budget(request) # Establish that the underlying gRPC stub method was called. @@ -877,17 +875,19 @@ def test_get_budget_field_headers(): @pytest.mark.asyncio async def test_get_budget_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.GetBudgetRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_budget), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(budget_model.Budget()) - await client.get_budget(request) # Establish that the underlying gRPC stub method was called. @@ -904,7 +904,7 @@ def test_list_budgets( transport: str = "grpc", request_type=budget_service.ListBudgetsRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -917,19 +917,15 @@ def test_list_budgets( call.return_value = budget_service.ListBudgetsResponse( next_page_token="next_page_token_value", ) - response = client.list_budgets(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.ListBudgetsRequest() # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListBudgetsPager) - assert response.next_page_token == "next_page_token_value" @@ -941,7 +937,7 @@ def test_list_budgets_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -949,7 +945,6 @@ def test_list_budgets_empty_call(): client.list_budgets() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.ListBudgetsRequest() @@ -958,7 +953,7 @@ async def test_list_budgets_async( transport: str = "grpc_asyncio", request_type=budget_service.ListBudgetsRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -971,18 +966,15 @@ async def test_list_budgets_async( call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( budget_service.ListBudgetsResponse(next_page_token="next_page_token_value",) ) - response = await client.list_budgets(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.ListBudgetsRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListBudgetsAsyncPager) - assert response.next_page_token == "next_page_token_value" @@ -992,17 +984,17 @@ async def test_list_budgets_async_from_dict(): def test_list_budgets_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.ListBudgetsRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_budgets), "__call__") as call: call.return_value = budget_service.ListBudgetsResponse() - client.list_budgets(request) # Establish that the underlying gRPC stub method was called. @@ -1017,11 +1009,14 @@ def test_list_budgets_field_headers(): @pytest.mark.asyncio async def test_list_budgets_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.ListBudgetsRequest() + request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. @@ -1029,7 +1024,6 @@ async def test_list_budgets_field_headers_async(): call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( budget_service.ListBudgetsResponse() ) - await client.list_budgets(request) # Establish that the underlying gRPC stub method was called. @@ -1043,7 +1037,7 @@ async def test_list_budgets_field_headers_async(): def test_list_budgets_pager(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials,) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_budgets), "__call__") as call: @@ -1081,7 +1075,7 @@ def test_list_budgets_pager(): def test_list_budgets_pages(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials,) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_budgets), "__call__") as call: @@ -1111,7 +1105,7 @@ def test_list_budgets_pages(): @pytest.mark.asyncio async def test_list_budgets_async_pager(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + client = BudgetServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -1148,7 +1142,7 @@ async def test_list_budgets_async_pager(): @pytest.mark.asyncio async def test_list_budgets_async_pages(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + client = BudgetServiceAsyncClient(credentials=ga_credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( @@ -1184,7 +1178,7 @@ def test_delete_budget( transport: str = "grpc", request_type=budget_service.DeleteBudgetRequest ): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -1195,13 +1189,11 @@ def test_delete_budget( with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = None - response = client.delete_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.DeleteBudgetRequest() # Establish that the response is the type that we expect. @@ -1216,7 +1208,7 @@ def test_delete_budget_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 = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), transport="grpc", + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1224,7 +1216,6 @@ def test_delete_budget_empty_call(): client.delete_budget() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.DeleteBudgetRequest() @@ -1233,7 +1224,7 @@ async def test_delete_budget_async( transport: str = "grpc_asyncio", request_type=budget_service.DeleteBudgetRequest ): client = BudgetServiceAsyncClient( - credentials=credentials.AnonymousCredentials(), transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -1244,13 +1235,11 @@ async def test_delete_budget_async( with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - response = await client.delete_budget(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == budget_service.DeleteBudgetRequest() # Establish that the response is the type that we expect. @@ -1263,17 +1252,17 @@ async def test_delete_budget_async_from_dict(): def test_delete_budget_field_headers(): - client = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(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 = budget_service.DeleteBudgetRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: call.return_value = None - client.delete_budget(request) # Establish that the underlying gRPC stub method was called. @@ -1288,17 +1277,19 @@ def test_delete_budget_field_headers(): @pytest.mark.asyncio async def test_delete_budget_field_headers_async(): - client = BudgetServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceAsyncClient( + 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 = budget_service.DeleteBudgetRequest() + request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_budget), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - await client.delete_budget(request) # Establish that the underlying gRPC stub method was called. @@ -1314,16 +1305,16 @@ async def test_delete_budget_field_headers_async(): def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. transport = transports.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = BudgetServiceClient( - 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.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = BudgetServiceClient( @@ -1333,7 +1324,7 @@ def test_credentials_transport_error(): # It is an error to provide scopes and a transport instance. transport = transports.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) with pytest.raises(ValueError): client = BudgetServiceClient( @@ -1344,7 +1335,7 @@ def test_credentials_transport_error(): def test_transport_instance(): # A client may be instantiated with a custom transport instance. transport = transports.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) client = BudgetServiceClient(transport=transport) assert client.transport is transport @@ -1353,13 +1344,13 @@ def test_transport_instance(): def test_transport_get_channel(): # A client may be instantiated with a custom transport instance. transport = transports.BudgetServiceGrpcTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel transport = transports.BudgetServiceGrpcAsyncIOTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) channel = transport.grpc_channel assert channel @@ -1374,23 +1365,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 = BudgetServiceClient(credentials=credentials.AnonymousCredentials(),) + client = BudgetServiceClient(credentials=ga_credentials.AnonymousCredentials(),) assert isinstance(client.transport, transports.BudgetServiceGrpcTransport,) def test_budget_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.BudgetServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), credentials_file="credentials.json", ) @@ -1402,7 +1393,7 @@ def test_budget_service_base_transport(): ) as Transport: Transport.return_value = None transport = transports.BudgetServiceTransport( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), ) # Every method on the transport should just blindly @@ -1419,15 +1410,40 @@ def test_budget_service_base_transport(): getattr(transport, method)(request=object()) +@requires_google_auth_gte_1_25_0 def test_budget_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.billing.budgets_v1beta1.services.budget_service.transports.BudgetServiceTransport._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.BudgetServiceTransport( + 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-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id="octopus", + ) + + +@requires_google_auth_lt_1_25_0 +def test_budget_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.billing.budgets_v1beta1.services.budget_service.transports.BudgetServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.BudgetServiceTransport( credentials_file="credentials.json", quota_project_id="octopus", ) @@ -1443,19 +1459,36 @@ def test_budget_service_base_transport_with_credentials_file(): def test_budget_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.billing.budgets_v1beta1.services.budget_service.transports.BudgetServiceTransport._prep_wrapped_messages" ) as Transport: Transport.return_value = None - adc.return_value = (credentials.AnonymousCredentials(), None) + adc.return_value = (ga_credentials.AnonymousCredentials(), None) transport = transports.BudgetServiceTransport() adc.assert_called_once() +@requires_google_auth_gte_1_25_0 def test_budget_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) + BudgetServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/cloud-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id=None, + ) + + +@requires_google_auth_lt_1_25_0 +def test_budget_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) BudgetServiceClient() adc.assert_called_once_with( scopes=( @@ -1466,14 +1499,44 @@ def test_budget_service_auth_adc(): ) -def test_budget_service_transport_auth_adc(): +@pytest.mark.parametrize( + "transport_class", + [ + transports.BudgetServiceGrpcTransport, + transports.BudgetServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_gte_1_25_0 +def test_budget_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.BudgetServiceGrpcTransport( - 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-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id="octopus", ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.BudgetServiceGrpcTransport, + transports.BudgetServiceGrpcAsyncIOTransport, + ], +) +@requires_google_auth_lt_1_25_0 +def test_budget_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-billing", @@ -1483,6 +1546,121 @@ def test_budget_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.BudgetServiceGrpcTransport, grpc_helpers), + (transports.BudgetServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_gte_1_26_0 +def test_budget_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( + "billingbudgets.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=( + "https://www.googleapis.com/auth/cloud-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + scopes=["1", "2"], + default_host="billingbudgets.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.BudgetServiceGrpcTransport, grpc_helpers), + (transports.BudgetServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_budget_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( + "billingbudgets.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + scopes=( + "https://www.googleapis.com/auth/cloud-billing", + "https://www.googleapis.com/auth/cloud-platform", + ), + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.BudgetServiceGrpcTransport, grpc_helpers), + (transports.BudgetServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +@requires_api_core_lt_1_26_0 +def test_budget_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( + "billingbudgets.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", [ @@ -1491,7 +1669,7 @@ def test_budget_service_transport_auth_adc(): ], ) def test_budget_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: @@ -1533,7 +1711,7 @@ def test_budget_service_grpc_transport_client_cert_source_for_mtls(transport_cla def test_budget_service_host_no_port(): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="billingbudgets.googleapis.com" ), @@ -1543,7 +1721,7 @@ def test_budget_service_host_no_port(): def test_budget_service_host_with_port(): client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), + credentials=ga_credentials.AnonymousCredentials(), client_options=client_options.ClientOptions( api_endpoint="billingbudgets.googleapis.com:8000" ), @@ -1597,9 +1775,9 @@ def test_budget_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", @@ -1682,7 +1860,6 @@ def test_budget_service_transport_channel_mtls_with_adc(transport_class): def test_budget_path(): billing_account = "squid" budget = "clam" - expected = "billingAccounts/{billing_account}/budgets/{budget}".format( billing_account=billing_account, budget=budget, ) @@ -1704,7 +1881,6 @@ def test_parse_budget_path(): def test_common_billing_account_path(): billing_account = "oyster" - expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -1725,7 +1901,6 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): folder = "cuttlefish" - expected = "folders/{folder}".format(folder=folder,) actual = BudgetServiceClient.common_folder_path(folder) assert expected == actual @@ -1744,7 +1919,6 @@ def test_parse_common_folder_path(): def test_common_organization_path(): organization = "winkle" - expected = "organizations/{organization}".format(organization=organization,) actual = BudgetServiceClient.common_organization_path(organization) assert expected == actual @@ -1763,7 +1937,6 @@ def test_parse_common_organization_path(): def test_common_project_path(): project = "scallop" - expected = "projects/{project}".format(project=project,) actual = BudgetServiceClient.common_project_path(project) assert expected == actual @@ -1783,7 +1956,6 @@ def test_parse_common_project_path(): def test_common_location_path(): project = "squid" location = "clam" - expected = "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -1810,7 +1982,7 @@ def test_client_withDEFAULT_CLIENT_INFO(): transports.BudgetServiceTransport, "_prep_wrapped_messages" ) as prep: client = BudgetServiceClient( - credentials=credentials.AnonymousCredentials(), client_info=client_info, + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) @@ -1819,6 +1991,6 @@ def test_client_withDEFAULT_CLIENT_INFO(): ) as prep: transport_class = BudgetServiceClient.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)