1# -*- coding: utf-8 -*- 
    2# Copyright 2025 Google LLC 
    3# 
    4# Licensed under the Apache License, Version 2.0 (the "License"); 
    5# you may not use this file except in compliance with the License. 
    6# You may obtain a copy of the License at 
    7# 
    8#     http://www.apache.org/licenses/LICENSE-2.0 
    9# 
    10# Unless required by applicable law or agreed to in writing, software 
    11# distributed under the License is distributed on an "AS IS" BASIS, 
    12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    13# See the License for the specific language governing permissions and 
    14# limitations under the License. 
    15# 
    16from collections import OrderedDict 
    17from http import HTTPStatus 
    18import json 
    19import logging as std_logging 
    20import os 
    21import re 
    22from typing import ( 
    23    Dict, 
    24    Callable, 
    25    Mapping, 
    26    MutableMapping, 
    27    MutableSequence, 
    28    Optional, 
    29    Sequence, 
    30    Tuple, 
    31    Type, 
    32    Union, 
    33    cast, 
    34) 
    35import warnings 
    36 
    37from google.cloud.errorreporting_v1beta1 import gapic_version as package_version 
    38 
    39from google.api_core import client_options as client_options_lib 
    40from google.api_core import exceptions as core_exceptions 
    41from google.api_core import gapic_v1 
    42from google.api_core import retry as retries 
    43from google.auth import credentials as ga_credentials  # type: ignore 
    44from google.auth.transport import mtls  # type: ignore 
    45from google.auth.transport.grpc import SslCredentials  # type: ignore 
    46from google.auth.exceptions import MutualTLSChannelError  # type: ignore 
    47from google.oauth2 import service_account  # type: ignore 
    48import google.protobuf 
    49 
    50try: 
    51    OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] 
    52except AttributeError:  # pragma: NO COVER 
    53    OptionalRetry = Union[retries.Retry, object, None]  # type: ignore 
    54 
    55try: 
    56    from google.api_core import client_logging  # type: ignore 
    57 
    58    CLIENT_LOGGING_SUPPORTED = True  # pragma: NO COVER 
    59except ImportError:  # pragma: NO COVER 
    60    CLIENT_LOGGING_SUPPORTED = False 
    61 
    62_LOGGER = std_logging.getLogger(__name__) 
    63 
    64from google.cloud.errorreporting_v1beta1.types import common 
    65from google.cloud.errorreporting_v1beta1.types import error_group_service 
    66from .transports.base import ErrorGroupServiceTransport, DEFAULT_CLIENT_INFO 
    67from .transports.grpc import ErrorGroupServiceGrpcTransport 
    68from .transports.grpc_asyncio import ErrorGroupServiceGrpcAsyncIOTransport 
    69from .transports.rest import ErrorGroupServiceRestTransport 
    70 
    71 
    72class ErrorGroupServiceClientMeta(type): 
    73    """Metaclass for the ErrorGroupService client. 
    74 
    75    This provides class-level methods for building and retrieving 
    76    support objects (e.g. transport) without polluting the client instance 
    77    objects. 
    78    """ 
    79 
    80    _transport_registry = ( 
    81        OrderedDict() 
    82    )  # type: Dict[str, Type[ErrorGroupServiceTransport]] 
    83    _transport_registry["grpc"] = ErrorGroupServiceGrpcTransport 
    84    _transport_registry["grpc_asyncio"] = ErrorGroupServiceGrpcAsyncIOTransport 
    85    _transport_registry["rest"] = ErrorGroupServiceRestTransport 
    86 
    87    def get_transport_class( 
    88        cls, 
    89        label: Optional[str] = None, 
    90    ) -> Type[ErrorGroupServiceTransport]: 
    91        """Returns an appropriate transport class. 
    92 
    93        Args: 
    94            label: The name of the desired transport. If none is 
    95                provided, then the first transport in the registry is used. 
    96 
    97        Returns: 
    98            The transport class to use. 
    99        """ 
    100        # If a specific transport is requested, return that one. 
    101        if label: 
    102            return cls._transport_registry[label] 
    103 
    104        # No transport is requested; return the default (that is, the first one 
    105        # in the dictionary). 
    106        return next(iter(cls._transport_registry.values())) 
    107 
    108 
    109class ErrorGroupServiceClient(metaclass=ErrorGroupServiceClientMeta): 
    110    """Service for retrieving and updating individual error groups.""" 
    111 
    112    @staticmethod 
    113    def _get_default_mtls_endpoint(api_endpoint): 
    114        """Converts api endpoint to mTLS endpoint. 
    115 
    116        Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to 
    117        "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. 
    118        Args: 
    119            api_endpoint (Optional[str]): the api endpoint to convert. 
    120        Returns: 
    121            str: converted mTLS api endpoint. 
    122        """ 
    123        if not api_endpoint: 
    124            return api_endpoint 
    125 
    126        mtls_endpoint_re = re.compile( 
    127            r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?" 
    128        ) 
    129 
    130        m = mtls_endpoint_re.match(api_endpoint) 
    131        name, mtls, sandbox, googledomain = m.groups() 
    132        if mtls or not googledomain: 
    133            return api_endpoint 
    134 
    135        if sandbox: 
    136            return api_endpoint.replace( 
    137                "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" 
    138            ) 
    139 
    140        return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") 
    141 
    142    # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. 
    143    DEFAULT_ENDPOINT = "clouderrorreporting.googleapis.com" 
    144    DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__(  # type: ignore 
    145        DEFAULT_ENDPOINT 
    146    ) 
    147 
    148    _DEFAULT_ENDPOINT_TEMPLATE = "clouderrorreporting.{UNIVERSE_DOMAIN}" 
    149    _DEFAULT_UNIVERSE = "googleapis.com" 
    150 
    151    @classmethod 
    152    def from_service_account_info(cls, info: dict, *args, **kwargs): 
    153        """Creates an instance of this client using the provided credentials 
    154            info. 
    155 
    156        Args: 
    157            info (dict): The service account private key info. 
    158            args: Additional arguments to pass to the constructor. 
    159            kwargs: Additional arguments to pass to the constructor. 
    160 
    161        Returns: 
    162            ErrorGroupServiceClient: The constructed client. 
    163        """ 
    164        credentials = service_account.Credentials.from_service_account_info(info) 
    165        kwargs["credentials"] = credentials 
    166        return cls(*args, **kwargs) 
    167 
    168    @classmethod 
    169    def from_service_account_file(cls, filename: str, *args, **kwargs): 
    170        """Creates an instance of this client using the provided credentials 
    171            file. 
    172 
    173        Args: 
    174            filename (str): The path to the service account private key json 
    175                file. 
    176            args: Additional arguments to pass to the constructor. 
    177            kwargs: Additional arguments to pass to the constructor. 
    178 
    179        Returns: 
    180            ErrorGroupServiceClient: The constructed client. 
    181        """ 
    182        credentials = service_account.Credentials.from_service_account_file(filename) 
    183        kwargs["credentials"] = credentials 
    184        return cls(*args, **kwargs) 
    185 
    186    from_service_account_json = from_service_account_file 
    187 
    188    @property 
    189    def transport(self) -> ErrorGroupServiceTransport: 
    190        """Returns the transport used by the client instance. 
    191 
    192        Returns: 
    193            ErrorGroupServiceTransport: The transport used by the client 
    194                instance. 
    195        """ 
    196        return self._transport 
    197 
    198    @staticmethod 
    199    def error_group_path( 
    200        project: str, 
    201        group: str, 
    202    ) -> str: 
    203        """Returns a fully-qualified error_group string.""" 
    204        return "projects/{project}/groups/{group}".format( 
    205            project=project, 
    206            group=group, 
    207        ) 
    208 
    209    @staticmethod 
    210    def parse_error_group_path(path: str) -> Dict[str, str]: 
    211        """Parses a error_group path into its component segments.""" 
    212        m = re.match(r"^projects/(?P<project>.+?)/groups/(?P<group>.+?)$", path) 
    213        return m.groupdict() if m else {} 
    214 
    215    @staticmethod 
    216    def common_billing_account_path( 
    217        billing_account: str, 
    218    ) -> str: 
    219        """Returns a fully-qualified billing_account string.""" 
    220        return "billingAccounts/{billing_account}".format( 
    221            billing_account=billing_account, 
    222        ) 
    223 
    224    @staticmethod 
    225    def parse_common_billing_account_path(path: str) -> Dict[str, str]: 
    226        """Parse a billing_account path into its component segments.""" 
    227        m = re.match(r"^billingAccounts/(?P<billing_account>.+?)$", path) 
    228        return m.groupdict() if m else {} 
    229 
    230    @staticmethod 
    231    def common_folder_path( 
    232        folder: str, 
    233    ) -> str: 
    234        """Returns a fully-qualified folder string.""" 
    235        return "folders/{folder}".format( 
    236            folder=folder, 
    237        ) 
    238 
    239    @staticmethod 
    240    def parse_common_folder_path(path: str) -> Dict[str, str]: 
    241        """Parse a folder path into its component segments.""" 
    242        m = re.match(r"^folders/(?P<folder>.+?)$", path) 
    243        return m.groupdict() if m else {} 
    244 
    245    @staticmethod 
    246    def common_organization_path( 
    247        organization: str, 
    248    ) -> str: 
    249        """Returns a fully-qualified organization string.""" 
    250        return "organizations/{organization}".format( 
    251            organization=organization, 
    252        ) 
    253 
    254    @staticmethod 
    255    def parse_common_organization_path(path: str) -> Dict[str, str]: 
    256        """Parse a organization path into its component segments.""" 
    257        m = re.match(r"^organizations/(?P<organization>.+?)$", path) 
    258        return m.groupdict() if m else {} 
    259 
    260    @staticmethod 
    261    def common_project_path( 
    262        project: str, 
    263    ) -> str: 
    264        """Returns a fully-qualified project string.""" 
    265        return "projects/{project}".format( 
    266            project=project, 
    267        ) 
    268 
    269    @staticmethod 
    270    def parse_common_project_path(path: str) -> Dict[str, str]: 
    271        """Parse a project path into its component segments.""" 
    272        m = re.match(r"^projects/(?P<project>.+?)$", path) 
    273        return m.groupdict() if m else {} 
    274 
    275    @staticmethod 
    276    def common_location_path( 
    277        project: str, 
    278        location: str, 
    279    ) -> str: 
    280        """Returns a fully-qualified location string.""" 
    281        return "projects/{project}/locations/{location}".format( 
    282            project=project, 
    283            location=location, 
    284        ) 
    285 
    286    @staticmethod 
    287    def parse_common_location_path(path: str) -> Dict[str, str]: 
    288        """Parse a location path into its component segments.""" 
    289        m = re.match(r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$", path) 
    290        return m.groupdict() if m else {} 
    291 
    292    @classmethod 
    293    def get_mtls_endpoint_and_cert_source( 
    294        cls, client_options: Optional[client_options_lib.ClientOptions] = None 
    295    ): 
    296        """Deprecated. Return the API endpoint and client cert source for mutual TLS. 
    297 
    298        The client cert source is determined in the following order: 
    299        (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the 
    300        client cert source is None. 
    301        (2) if `client_options.client_cert_source` is provided, use the provided one; if the 
    302        default client cert source exists, use the default one; otherwise the client cert 
    303        source is None. 
    304 
    305        The API endpoint is determined in the following order: 
    306        (1) if `client_options.api_endpoint` if provided, use the provided one. 
    307        (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the 
    308        default mTLS endpoint; if the environment variable is "never", use the default API 
    309        endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise 
    310        use the default API endpoint. 
    311 
    312        More details can be found at https://google.aip.dev/auth/4114. 
    313 
    314        Args: 
    315            client_options (google.api_core.client_options.ClientOptions): Custom options for the 
    316                client. Only the `api_endpoint` and `client_cert_source` properties may be used 
    317                in this method. 
    318 
    319        Returns: 
    320            Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the 
    321                client cert source to use. 
    322 
    323        Raises: 
    324            google.auth.exceptions.MutualTLSChannelError: If any errors happen. 
    325        """ 
    326 
    327        warnings.warn( 
    328            "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", 
    329            DeprecationWarning, 
    330        ) 
    331        if client_options is None: 
    332            client_options = client_options_lib.ClientOptions() 
    333        use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") 
    334        use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") 
    335        if use_client_cert not in ("true", "false"): 
    336            raise ValueError( 
    337                "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" 
    338            ) 
    339        if use_mtls_endpoint not in ("auto", "never", "always"): 
    340            raise MutualTLSChannelError( 
    341                "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" 
    342            ) 
    343 
    344        # Figure out the client cert source to use. 
    345        client_cert_source = None 
    346        if use_client_cert == "true": 
    347            if client_options.client_cert_source: 
    348                client_cert_source = client_options.client_cert_source 
    349            elif mtls.has_default_client_cert_source(): 
    350                client_cert_source = mtls.default_client_cert_source() 
    351 
    352        # Figure out which api endpoint to use. 
    353        if client_options.api_endpoint is not None: 
    354            api_endpoint = client_options.api_endpoint 
    355        elif use_mtls_endpoint == "always" or ( 
    356            use_mtls_endpoint == "auto" and client_cert_source 
    357        ): 
    358            api_endpoint = cls.DEFAULT_MTLS_ENDPOINT 
    359        else: 
    360            api_endpoint = cls.DEFAULT_ENDPOINT 
    361 
    362        return api_endpoint, client_cert_source 
    363 
    364    @staticmethod 
    365    def _read_environment_variables(): 
    366        """Returns the environment variables used by the client. 
    367 
    368        Returns: 
    369            Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, 
    370            GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. 
    371 
    372        Raises: 
    373            ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not 
    374                any of ["true", "false"]. 
    375            google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT 
    376                is not any of ["auto", "never", "always"]. 
    377        """ 
    378        use_client_cert = os.getenv( 
    379            "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" 
    380        ).lower() 
    381        use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() 
    382        universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") 
    383        if use_client_cert not in ("true", "false"): 
    384            raise ValueError( 
    385                "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" 
    386            ) 
    387        if use_mtls_endpoint not in ("auto", "never", "always"): 
    388            raise MutualTLSChannelError( 
    389                "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" 
    390            ) 
    391        return use_client_cert == "true", use_mtls_endpoint, universe_domain_env 
    392 
    393    @staticmethod 
    394    def _get_client_cert_source(provided_cert_source, use_cert_flag): 
    395        """Return the client cert source to be used by the client. 
    396 
    397        Args: 
    398            provided_cert_source (bytes): The client certificate source provided. 
    399            use_cert_flag (bool): A flag indicating whether to use the client certificate. 
    400 
    401        Returns: 
    402            bytes or None: The client cert source to be used by the client. 
    403        """ 
    404        client_cert_source = None 
    405        if use_cert_flag: 
    406            if provided_cert_source: 
    407                client_cert_source = provided_cert_source 
    408            elif mtls.has_default_client_cert_source(): 
    409                client_cert_source = mtls.default_client_cert_source() 
    410        return client_cert_source 
    411 
    412    @staticmethod 
    413    def _get_api_endpoint( 
    414        api_override, client_cert_source, universe_domain, use_mtls_endpoint 
    415    ): 
    416        """Return the API endpoint used by the client. 
    417 
    418        Args: 
    419            api_override (str): The API endpoint override. If specified, this is always 
    420                the return value of this function and the other arguments are not used. 
    421            client_cert_source (bytes): The client certificate source used by the client. 
    422            universe_domain (str): The universe domain used by the client. 
    423            use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. 
    424                Possible values are "always", "auto", or "never". 
    425 
    426        Returns: 
    427            str: The API endpoint to be used by the client. 
    428        """ 
    429        if api_override is not None: 
    430            api_endpoint = api_override 
    431        elif use_mtls_endpoint == "always" or ( 
    432            use_mtls_endpoint == "auto" and client_cert_source 
    433        ): 
    434            _default_universe = ErrorGroupServiceClient._DEFAULT_UNIVERSE 
    435            if universe_domain != _default_universe: 
    436                raise MutualTLSChannelError( 
    437                    f"mTLS is not supported in any universe other than {_default_universe}." 
    438                ) 
    439            api_endpoint = ErrorGroupServiceClient.DEFAULT_MTLS_ENDPOINT 
    440        else: 
    441            api_endpoint = ErrorGroupServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( 
    442                UNIVERSE_DOMAIN=universe_domain 
    443            ) 
    444        return api_endpoint 
    445 
    446    @staticmethod 
    447    def _get_universe_domain( 
    448        client_universe_domain: Optional[str], universe_domain_env: Optional[str] 
    449    ) -> str: 
    450        """Return the universe domain used by the client. 
    451 
    452        Args: 
    453            client_universe_domain (Optional[str]): The universe domain configured via the client options. 
    454            universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. 
    455 
    456        Returns: 
    457            str: The universe domain to be used by the client. 
    458 
    459        Raises: 
    460            ValueError: If the universe domain is an empty string. 
    461        """ 
    462        universe_domain = ErrorGroupServiceClient._DEFAULT_UNIVERSE 
    463        if client_universe_domain is not None: 
    464            universe_domain = client_universe_domain 
    465        elif universe_domain_env is not None: 
    466            universe_domain = universe_domain_env 
    467        if len(universe_domain.strip()) == 0: 
    468            raise ValueError("Universe Domain cannot be an empty string.") 
    469        return universe_domain 
    470 
    471    def _validate_universe_domain(self): 
    472        """Validates client's and credentials' universe domains are consistent. 
    473 
    474        Returns: 
    475            bool: True iff the configured universe domain is valid. 
    476 
    477        Raises: 
    478            ValueError: If the configured universe domain is not valid. 
    479        """ 
    480 
    481        # NOTE (b/349488459): universe validation is disabled until further notice. 
    482        return True 
    483 
    484    def _add_cred_info_for_auth_errors( 
    485        self, error: core_exceptions.GoogleAPICallError 
    486    ) -> None: 
    487        """Adds credential info string to error details for 401/403/404 errors. 
    488 
    489        Args: 
    490            error (google.api_core.exceptions.GoogleAPICallError): The error to add the cred info. 
    491        """ 
    492        if error.code not in [ 
    493            HTTPStatus.UNAUTHORIZED, 
    494            HTTPStatus.FORBIDDEN, 
    495            HTTPStatus.NOT_FOUND, 
    496        ]: 
    497            return 
    498 
    499        cred = self._transport._credentials 
    500 
    501        # get_cred_info is only available in google-auth>=2.35.0 
    502        if not hasattr(cred, "get_cred_info"): 
    503            return 
    504 
    505        # ignore the type check since pypy test fails when get_cred_info 
    506        # is not available 
    507        cred_info = cred.get_cred_info()  # type: ignore 
    508        if cred_info and hasattr(error._details, "append"): 
    509            error._details.append(json.dumps(cred_info)) 
    510 
    511    @property 
    512    def api_endpoint(self): 
    513        """Return the API endpoint used by the client instance. 
    514 
    515        Returns: 
    516            str: The API endpoint used by the client instance. 
    517        """ 
    518        return self._api_endpoint 
    519 
    520    @property 
    521    def universe_domain(self) -> str: 
    522        """Return the universe domain used by the client instance. 
    523 
    524        Returns: 
    525            str: The universe domain used by the client instance. 
    526        """ 
    527        return self._universe_domain 
    528 
    529    def __init__( 
    530        self, 
    531        *, 
    532        credentials: Optional[ga_credentials.Credentials] = None, 
    533        transport: Optional[ 
    534            Union[ 
    535                str, 
    536                ErrorGroupServiceTransport, 
    537                Callable[..., ErrorGroupServiceTransport], 
    538            ] 
    539        ] = None, 
    540        client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, 
    541        client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, 
    542    ) -> None: 
    543        """Instantiates the error group service client. 
    544 
    545        Args: 
    546            credentials (Optional[google.auth.credentials.Credentials]): The 
    547                authorization credentials to attach to requests. These 
    548                credentials identify the application to the service; if none 
    549                are specified, the client will attempt to ascertain the 
    550                credentials from the environment. 
    551            transport (Optional[Union[str,ErrorGroupServiceTransport,Callable[..., ErrorGroupServiceTransport]]]): 
    552                The transport to use, or a Callable that constructs and returns a new transport. 
    553                If a Callable is given, it will be called with the same set of initialization 
    554                arguments as used in the ErrorGroupServiceTransport constructor. 
    555                If set to None, a transport is chosen automatically. 
    556            client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): 
    557                Custom options for the client. 
    558 
    559                1. The ``api_endpoint`` property can be used to override the 
    560                default endpoint provided by the client when ``transport`` is 
    561                not explicitly provided. Only if this property is not set and 
    562                ``transport`` was not explicitly provided, the endpoint is 
    563                determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment 
    564                variable, which have one of the following values: 
    565                "always" (always use the default mTLS endpoint), "never" (always 
    566                use the default regular endpoint) and "auto" (auto-switch to the 
    567                default mTLS endpoint if client certificate is present; this is 
    568                the default value). 
    569 
    570                2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable 
    571                is "true", then the ``client_cert_source`` property can be used 
    572                to provide a client certificate for mTLS transport. If 
    573                not provided, the default SSL client certificate will be used if 
    574                present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not 
    575                set, no client certificate will be used. 
    576 
    577                3. The ``universe_domain`` property can be used to override the 
    578                default "googleapis.com" universe. Note that the ``api_endpoint`` 
    579                property still takes precedence; and ``universe_domain`` is 
    580                currently not supported for mTLS. 
    581 
    582            client_info (google.api_core.gapic_v1.client_info.ClientInfo): 
    583                The client info used to send a user-agent string along with 
    584                API requests. If ``None``, then default info will be used. 
    585                Generally, you only need to set this if you're developing 
    586                your own client library. 
    587 
    588        Raises: 
    589            google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport 
    590                creation failed for any reason. 
    591        """ 
    592        self._client_options = client_options 
    593        if isinstance(self._client_options, dict): 
    594            self._client_options = client_options_lib.from_dict(self._client_options) 
    595        if self._client_options is None: 
    596            self._client_options = client_options_lib.ClientOptions() 
    597        self._client_options = cast( 
    598            client_options_lib.ClientOptions, self._client_options 
    599        ) 
    600 
    601        universe_domain_opt = getattr(self._client_options, "universe_domain", None) 
    602 
    603        ( 
    604            self._use_client_cert, 
    605            self._use_mtls_endpoint, 
    606            self._universe_domain_env, 
    607        ) = ErrorGroupServiceClient._read_environment_variables() 
    608        self._client_cert_source = ErrorGroupServiceClient._get_client_cert_source( 
    609            self._client_options.client_cert_source, self._use_client_cert 
    610        ) 
    611        self._universe_domain = ErrorGroupServiceClient._get_universe_domain( 
    612            universe_domain_opt, self._universe_domain_env 
    613        ) 
    614        self._api_endpoint = None  # updated below, depending on `transport` 
    615 
    616        # Initialize the universe domain validation. 
    617        self._is_universe_domain_valid = False 
    618 
    619        if CLIENT_LOGGING_SUPPORTED:  # pragma: NO COVER 
    620            # Setup logging. 
    621            client_logging.initialize_logging() 
    622 
    623        api_key_value = getattr(self._client_options, "api_key", None) 
    624        if api_key_value and credentials: 
    625            raise ValueError( 
    626                "client_options.api_key and credentials are mutually exclusive" 
    627            ) 
    628 
    629        # Save or instantiate the transport. 
    630        # Ordinarily, we provide the transport, but allowing a custom transport 
    631        # instance provides an extensibility point for unusual situations. 
    632        transport_provided = isinstance(transport, ErrorGroupServiceTransport) 
    633        if transport_provided: 
    634            # transport is a ErrorGroupServiceTransport instance. 
    635            if credentials or self._client_options.credentials_file or api_key_value: 
    636                raise ValueError( 
    637                    "When providing a transport instance, " 
    638                    "provide its credentials directly." 
    639                ) 
    640            if self._client_options.scopes: 
    641                raise ValueError( 
    642                    "When providing a transport instance, provide its scopes " 
    643                    "directly." 
    644                ) 
    645            self._transport = cast(ErrorGroupServiceTransport, transport) 
    646            self._api_endpoint = self._transport.host 
    647 
    648        self._api_endpoint = ( 
    649            self._api_endpoint 
    650            or ErrorGroupServiceClient._get_api_endpoint( 
    651                self._client_options.api_endpoint, 
    652                self._client_cert_source, 
    653                self._universe_domain, 
    654                self._use_mtls_endpoint, 
    655            ) 
    656        ) 
    657 
    658        if not transport_provided: 
    659            import google.auth._default  # type: ignore 
    660 
    661            if api_key_value and hasattr( 
    662                google.auth._default, "get_api_key_credentials" 
    663            ): 
    664                credentials = google.auth._default.get_api_key_credentials( 
    665                    api_key_value 
    666                ) 
    667 
    668            transport_init: Union[ 
    669                Type[ErrorGroupServiceTransport], 
    670                Callable[..., ErrorGroupServiceTransport], 
    671            ] = ( 
    672                ErrorGroupServiceClient.get_transport_class(transport) 
    673                if isinstance(transport, str) or transport is None 
    674                else cast(Callable[..., ErrorGroupServiceTransport], transport) 
    675            ) 
    676            # initialize with the provided callable or the passed in class 
    677            self._transport = transport_init( 
    678                credentials=credentials, 
    679                credentials_file=self._client_options.credentials_file, 
    680                host=self._api_endpoint, 
    681                scopes=self._client_options.scopes, 
    682                client_cert_source_for_mtls=self._client_cert_source, 
    683                quota_project_id=self._client_options.quota_project_id, 
    684                client_info=client_info, 
    685                always_use_jwt_access=True, 
    686                api_audience=self._client_options.api_audience, 
    687            ) 
    688 
    689        if "async" not in str(self._transport): 
    690            if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( 
    691                std_logging.DEBUG 
    692            ):  # pragma: NO COVER 
    693                _LOGGER.debug( 
    694                    "Created client `google.devtools.clouderrorreporting_v1beta1.ErrorGroupServiceClient`.", 
    695                    extra={ 
    696                        "serviceName": "google.devtools.clouderrorreporting.v1beta1.ErrorGroupService", 
    697                        "universeDomain": getattr( 
    698                            self._transport._credentials, "universe_domain", "" 
    699                        ), 
    700                        "credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}", 
    701                        "credentialsInfo": getattr( 
    702                            self.transport._credentials, "get_cred_info", lambda: None 
    703                        )(), 
    704                    } 
    705                    if hasattr(self._transport, "_credentials") 
    706                    else { 
    707                        "serviceName": "google.devtools.clouderrorreporting.v1beta1.ErrorGroupService", 
    708                        "credentialsType": None, 
    709                    }, 
    710                ) 
    711 
    712    def get_group( 
    713        self, 
    714        request: Optional[Union[error_group_service.GetGroupRequest, dict]] = None, 
    715        *, 
    716        group_name: Optional[str] = None, 
    717        retry: OptionalRetry = gapic_v1.method.DEFAULT, 
    718        timeout: Union[float, object] = gapic_v1.method.DEFAULT, 
    719        metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), 
    720    ) -> common.ErrorGroup: 
    721        r"""Get the specified group. 
    722 
    723        .. code-block:: python 
    724 
    725            # This snippet has been automatically generated and should be regarded as a 
    726            # code template only. 
    727            # It will require modifications to work: 
    728            # - It may require correct/in-range values for request initialization. 
    729            # - It may require specifying regional endpoints when creating the service 
    730            #   client as shown in: 
    731            #   https://googleapis.dev/python/google-api-core/latest/client_options.html 
    732            from google.cloud import errorreporting_v1beta1 
    733 
    734            def sample_get_group(): 
    735                # Create a client 
    736                client = errorreporting_v1beta1.ErrorGroupServiceClient() 
    737 
    738                # Initialize request argument(s) 
    739                request = errorreporting_v1beta1.GetGroupRequest( 
    740                    group_name="group_name_value", 
    741                ) 
    742 
    743                # Make the request 
    744                response = client.get_group(request=request) 
    745 
    746                # Handle the response 
    747                print(response) 
    748 
    749        Args: 
    750            request (Union[google.cloud.errorreporting_v1beta1.types.GetGroupRequest, dict]): 
    751                The request object. A request to return an individual 
    752                group. 
    753            group_name (str): 
    754                Required. The group resource name. Written as either 
    755                ``projects/{projectID}/groups/{group_id}`` or 
    756                ``projects/{projectID}/locations/{location}/groups/{group_id}``. 
    757                Call [groupStats.list] 
    758                [google.devtools.clouderrorreporting.v1beta1.ErrorStatsService.ListGroupStats] 
    759                to return a list of groups belonging to this project. 
    760 
    761                Examples: ``projects/my-project-123/groups/my-group``, 
    762                ``projects/my-project-123/locations/global/groups/my-group`` 
    763 
    764                In the group resource name, the ``group_id`` is a unique 
    765                identifier for a particular error group. The identifier 
    766                is derived from key parts of the error-log content and 
    767                is treated as Service Data. For information about how 
    768                Service Data is handled, see `Google Cloud Privacy 
    769                Notice <https://cloud.google.com/terms/cloud-privacy-notice>`__. 
    770 
    771                For a list of supported locations, see `Supported 
    772                Regions <https://cloud.google.com/logging/docs/region-support>`__. 
    773                ``global`` is the default when unspecified. 
    774 
    775                This corresponds to the ``group_name`` field 
    776                on the ``request`` instance; if ``request`` is provided, this 
    777                should not be set. 
    778            retry (google.api_core.retry.Retry): Designation of what errors, if any, 
    779                should be retried. 
    780            timeout (float): The timeout for this request. 
    781            metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be 
    782                sent along with the request as metadata. Normally, each value must be of type `str`, 
    783                but for metadata keys ending with the suffix `-bin`, the corresponding values must 
    784                be of type `bytes`. 
    785 
    786        Returns: 
    787            google.cloud.errorreporting_v1beta1.types.ErrorGroup: 
    788                Description of a group of similar 
    789                error events. 
    790 
    791        """ 
    792        # Create or coerce a protobuf request object. 
    793        # - Quick check: If we got a request object, we should *not* have 
    794        #   gotten any keyword arguments that map to the request. 
    795        flattened_params = [group_name] 
    796        has_flattened_params = ( 
    797            len([param for param in flattened_params if param is not None]) > 0 
    798        ) 
    799        if request is not None and has_flattened_params: 
    800            raise ValueError( 
    801                "If the `request` argument is set, then none of " 
    802                "the individual field arguments should be set." 
    803            ) 
    804 
    805        # - Use the request object if provided (there's no risk of modifying the input as 
    806        #   there are no flattened fields), or create one. 
    807        if not isinstance(request, error_group_service.GetGroupRequest): 
    808            request = error_group_service.GetGroupRequest(request) 
    809            # If we have keyword arguments corresponding to fields on the 
    810            # request, apply these. 
    811            if group_name is not None: 
    812                request.group_name = group_name 
    813 
    814        # Wrap the RPC method; this adds retry and timeout information, 
    815        # and friendly error handling. 
    816        rpc = self._transport._wrapped_methods[self._transport.get_group] 
    817 
    818        # Certain fields should be provided within the metadata header; 
    819        # add these here. 
    820        metadata = tuple(metadata) + ( 
    821            gapic_v1.routing_header.to_grpc_metadata( 
    822                (("group_name", request.group_name),) 
    823            ), 
    824        ) 
    825 
    826        # Validate the universe domain. 
    827        self._validate_universe_domain() 
    828 
    829        # Send the request. 
    830        response = rpc( 
    831            request, 
    832            retry=retry, 
    833            timeout=timeout, 
    834            metadata=metadata, 
    835        ) 
    836 
    837        # Done; return the response. 
    838        return response 
    839 
    840    def update_group( 
    841        self, 
    842        request: Optional[Union[error_group_service.UpdateGroupRequest, dict]] = None, 
    843        *, 
    844        group: Optional[common.ErrorGroup] = None, 
    845        retry: OptionalRetry = gapic_v1.method.DEFAULT, 
    846        timeout: Union[float, object] = gapic_v1.method.DEFAULT, 
    847        metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), 
    848    ) -> common.ErrorGroup: 
    849        r"""Replace the data for the specified group. 
    850        Fails if the group does not exist. 
    851 
    852        .. code-block:: python 
    853 
    854            # This snippet has been automatically generated and should be regarded as a 
    855            # code template only. 
    856            # It will require modifications to work: 
    857            # - It may require correct/in-range values for request initialization. 
    858            # - It may require specifying regional endpoints when creating the service 
    859            #   client as shown in: 
    860            #   https://googleapis.dev/python/google-api-core/latest/client_options.html 
    861            from google.cloud import errorreporting_v1beta1 
    862 
    863            def sample_update_group(): 
    864                # Create a client 
    865                client = errorreporting_v1beta1.ErrorGroupServiceClient() 
    866 
    867                # Initialize request argument(s) 
    868                request = errorreporting_v1beta1.UpdateGroupRequest( 
    869                ) 
    870 
    871                # Make the request 
    872                response = client.update_group(request=request) 
    873 
    874                # Handle the response 
    875                print(response) 
    876 
    877        Args: 
    878            request (Union[google.cloud.errorreporting_v1beta1.types.UpdateGroupRequest, dict]): 
    879                The request object. A request to replace the existing 
    880                data for the given group. 
    881            group (google.cloud.errorreporting_v1beta1.types.ErrorGroup): 
    882                Required. The group which replaces 
    883                the resource on the server. 
    884 
    885                This corresponds to the ``group`` field 
    886                on the ``request`` instance; if ``request`` is provided, this 
    887                should not be set. 
    888            retry (google.api_core.retry.Retry): Designation of what errors, if any, 
    889                should be retried. 
    890            timeout (float): The timeout for this request. 
    891            metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be 
    892                sent along with the request as metadata. Normally, each value must be of type `str`, 
    893                but for metadata keys ending with the suffix `-bin`, the corresponding values must 
    894                be of type `bytes`. 
    895 
    896        Returns: 
    897            google.cloud.errorreporting_v1beta1.types.ErrorGroup: 
    898                Description of a group of similar 
    899                error events. 
    900 
    901        """ 
    902        # Create or coerce a protobuf request object. 
    903        # - Quick check: If we got a request object, we should *not* have 
    904        #   gotten any keyword arguments that map to the request. 
    905        flattened_params = [group] 
    906        has_flattened_params = ( 
    907            len([param for param in flattened_params if param is not None]) > 0 
    908        ) 
    909        if request is not None and has_flattened_params: 
    910            raise ValueError( 
    911                "If the `request` argument is set, then none of " 
    912                "the individual field arguments should be set." 
    913            ) 
    914 
    915        # - Use the request object if provided (there's no risk of modifying the input as 
    916        #   there are no flattened fields), or create one. 
    917        if not isinstance(request, error_group_service.UpdateGroupRequest): 
    918            request = error_group_service.UpdateGroupRequest(request) 
    919            # If we have keyword arguments corresponding to fields on the 
    920            # request, apply these. 
    921            if group is not None: 
    922                request.group = group 
    923 
    924        # Wrap the RPC method; this adds retry and timeout information, 
    925        # and friendly error handling. 
    926        rpc = self._transport._wrapped_methods[self._transport.update_group] 
    927 
    928        # Certain fields should be provided within the metadata header; 
    929        # add these here. 
    930        metadata = tuple(metadata) + ( 
    931            gapic_v1.routing_header.to_grpc_metadata( 
    932                (("group.name", request.group.name),) 
    933            ), 
    934        ) 
    935 
    936        # Validate the universe domain. 
    937        self._validate_universe_domain() 
    938 
    939        # Send the request. 
    940        response = rpc( 
    941            request, 
    942            retry=retry, 
    943            timeout=timeout, 
    944            metadata=metadata, 
    945        ) 
    946 
    947        # Done; return the response. 
    948        return response 
    949 
    950    def __enter__(self) -> "ErrorGroupServiceClient": 
    951        return self 
    952 
    953    def __exit__(self, type, value, traceback): 
    954        """Releases underlying transport's resources. 
    955 
    956        .. warning:: 
    957            ONLY use as a context manager if the transport is NOT shared 
    958            with other clients! Exiting the with block will CLOSE the transport 
    959            and may cause errors in other clients! 
    960        """ 
    961        self.transport.close() 
    962 
    963 
    964DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( 
    965    gapic_version=package_version.__version__ 
    966) 
    967 
    968if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"):  # pragma: NO COVER 
    969    DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ 
    970 
    971__all__ = ("ErrorGroupServiceClient",)