diff --git a/.coveragerc b/.coveragerc index 33d10d7..347d67f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -5,6 +5,7 @@ branch = True show_missing = True omit = google/cloud/video/transcoder/__init__.py + google/cloud/video/transcoder/gapic_version.py exclude_lines = # Re-enable the standard pragma pragma: NO COVER diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 889f77d..5fc5daa 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest - digest: sha256:c43f1d918bcf817d337aa29ff833439494a158a0831508fda4ec75dc4c0d0320 + digest: sha256:8555f0e37e6261408f792bfd6635102d2da5ad73f8f09bcb24f25e6afb5fac97 diff --git a/.kokoro/requirements.in b/.kokoro/requirements.in index cbd7e77..882178c 100644 --- a/.kokoro/requirements.in +++ b/.kokoro/requirements.in @@ -1,5 +1,5 @@ gcp-docuploader -gcp-releasetool +gcp-releasetool>=1.10.5 # required for compatibility with cryptography>=39.x importlib-metadata typing-extensions twine diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt index 05dc467..fa99c12 100644 --- a/.kokoro/requirements.txt +++ b/.kokoro/requirements.txt @@ -113,33 +113,28 @@ commonmark==0.9.1 \ --hash=sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60 \ --hash=sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9 # via rich -cryptography==38.0.3 \ - --hash=sha256:068147f32fa662c81aebab95c74679b401b12b57494872886eb5c1139250ec5d \ - --hash=sha256:06fc3cc7b6f6cca87bd56ec80a580c88f1da5306f505876a71c8cfa7050257dd \ - --hash=sha256:25c1d1f19729fb09d42e06b4bf9895212292cb27bb50229f5aa64d039ab29146 \ - --hash=sha256:402852a0aea73833d982cabb6d0c3bb582c15483d29fb7085ef2c42bfa7e38d7 \ - --hash=sha256:4e269dcd9b102c5a3d72be3c45d8ce20377b8076a43cbed6f660a1afe365e436 \ - --hash=sha256:5419a127426084933076132d317911e3c6eb77568a1ce23c3ac1e12d111e61e0 \ - --hash=sha256:554bec92ee7d1e9d10ded2f7e92a5d70c1f74ba9524947c0ba0c850c7b011828 \ - --hash=sha256:5e89468fbd2fcd733b5899333bc54d0d06c80e04cd23d8c6f3e0542358c6060b \ - --hash=sha256:65535bc550b70bd6271984d9863a37741352b4aad6fb1b3344a54e6950249b55 \ - --hash=sha256:6ab9516b85bebe7aa83f309bacc5f44a61eeb90d0b4ec125d2d003ce41932d36 \ - --hash=sha256:6addc3b6d593cd980989261dc1cce38263c76954d758c3c94de51f1e010c9a50 \ - --hash=sha256:728f2694fa743a996d7784a6194da430f197d5c58e2f4e278612b359f455e4a2 \ - --hash=sha256:785e4056b5a8b28f05a533fab69febf5004458e20dad7e2e13a3120d8ecec75a \ - --hash=sha256:78cf5eefac2b52c10398a42765bfa981ce2372cbc0457e6bf9658f41ec3c41d8 \ - --hash=sha256:7f836217000342d448e1c9a342e9163149e45d5b5eca76a30e84503a5a96cab0 \ - --hash=sha256:8d41a46251bf0634e21fac50ffd643216ccecfaf3701a063257fe0b2be1b6548 \ - --hash=sha256:984fe150f350a3c91e84de405fe49e688aa6092b3525f407a18b9646f6612320 \ - --hash=sha256:9b24bcff7853ed18a63cfb0c2b008936a9554af24af2fb146e16d8e1aed75748 \ - --hash=sha256:b1b35d9d3a65542ed2e9d90115dfd16bbc027b3f07ee3304fc83580f26e43249 \ - --hash=sha256:b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959 \ - --hash=sha256:bbf203f1a814007ce24bd4d51362991d5cb90ba0c177a9c08825f2cc304d871f \ - --hash=sha256:be243c7e2bfcf6cc4cb350c0d5cdf15ca6383bbcb2a8ef51d3c9411a9d4386f0 \ - --hash=sha256:bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd \ - --hash=sha256:c46837ea467ed1efea562bbeb543994c2d1f6e800785bd5a2c98bc096f5cb220 \ - --hash=sha256:dfb4f4dd568de1b6af9f4cda334adf7d72cf5bc052516e1b2608b683375dd95c \ - --hash=sha256:ed7b00096790213e09eb11c97cc6e2b757f15f3d2f85833cd2d3ec3fe37c1722 +cryptography==39.0.1 \ + --hash=sha256:0f8da300b5c8af9f98111ffd512910bc792b4c77392a9523624680f7956a99d4 \ + --hash=sha256:35f7c7d015d474f4011e859e93e789c87d21f6f4880ebdc29896a60403328f1f \ + --hash=sha256:5aa67414fcdfa22cf052e640cb5ddc461924a045cacf325cd164e65312d99502 \ + --hash=sha256:5d2d8b87a490bfcd407ed9d49093793d0f75198a35e6eb1a923ce1ee86c62b41 \ + --hash=sha256:6687ef6d0a6497e2b58e7c5b852b53f62142cfa7cd1555795758934da363a965 \ + --hash=sha256:6f8ba7f0328b79f08bdacc3e4e66fb4d7aab0c3584e0bd41328dce5262e26b2e \ + --hash=sha256:706843b48f9a3f9b9911979761c91541e3d90db1ca905fd63fee540a217698bc \ + --hash=sha256:807ce09d4434881ca3a7594733669bd834f5b2c6d5c7e36f8c00f691887042ad \ + --hash=sha256:83e17b26de248c33f3acffb922748151d71827d6021d98c70e6c1a25ddd78505 \ + --hash=sha256:96f1157a7c08b5b189b16b47bc9db2332269d6680a196341bf30046330d15388 \ + --hash=sha256:aec5a6c9864be7df2240c382740fcf3b96928c46604eaa7f3091f58b878c0bb6 \ + --hash=sha256:b0afd054cd42f3d213bf82c629efb1ee5f22eba35bf0eec88ea9ea7304f511a2 \ + --hash=sha256:ced4e447ae29ca194449a3f1ce132ded8fcab06971ef5f618605aacaa612beac \ + --hash=sha256:d1f6198ee6d9148405e49887803907fe8962a23e6c6f83ea7d98f1c0de375695 \ + --hash=sha256:e124352fd3db36a9d4a21c1aa27fd5d051e621845cb87fb851c08f4f75ce8be6 \ + --hash=sha256:e422abdec8b5fa8462aa016786680720d78bdce7a30c652b7fadf83a4ba35336 \ + --hash=sha256:ef8b72fa70b348724ff1218267e7f7375b8de4e8194d1636ee60510aae104cd0 \ + --hash=sha256:f0c64d1bd842ca2633e74a1a28033d139368ad959872533b1bab8c80e8240a0c \ + --hash=sha256:f24077a3b5298a5a06a8e0536e3ea9ec60e4c7ac486755e5fb6e6ea9b3500106 \ + --hash=sha256:fdd188c8a6ef8769f148f88f859884507b954cc64db6b52f66ef199bb9ad660a \ + --hash=sha256:fe913f20024eb2cb2f323e42a64bdf2911bb9738a15dba7d3cce48151034e3a8 # via # gcp-releasetool # secretstorage @@ -159,9 +154,9 @@ gcp-docuploader==0.6.4 \ --hash=sha256:01486419e24633af78fd0167db74a2763974765ee8078ca6eb6964d0ebd388af \ --hash=sha256:70861190c123d907b3b067da896265ead2eeb9263969d6955c9e0bb091b5ccbf # via -r requirements.in -gcp-releasetool==1.10.0 \ - --hash=sha256:72a38ca91b59c24f7e699e9227c90cbe4dd71b789383cb0164b088abae294c83 \ - --hash=sha256:8c7c99320208383d4bb2b808c6880eb7a81424afe7cdba3c8d84b25f4f0e097d +gcp-releasetool==1.10.5 \ + --hash=sha256:174b7b102d704b254f2a26a3eda2c684fd3543320ec239baf771542a2e58e109 \ + --hash=sha256:e29d29927fe2ca493105a82958c6873bb2b90d503acac56be2c229e74de0eec9 # via -r requirements.in google-api-core==2.10.2 \ --hash=sha256:10c06f7739fe57781f87523375e8e1a3a4674bf6392cd6131a3222182b971320 \ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 093be7e..64e0684 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.6.1" + ".": "1.7.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 57ec3d4..601eef6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.7.0](https://github.com/googleapis/python-video-transcoder/compare/v1.6.1...v1.7.0) (2023-02-28) + + +### Features + +* Enable "rest" transport in Python for services supporting numeric enums ([#283](https://github.com/googleapis/python-video-transcoder/issues/283)) ([3c36813](https://github.com/googleapis/python-video-transcoder/commit/3c368135a0874f76909e0f9b92f12fea32617acd)) + ## [1.6.1](https://github.com/googleapis/python-video-transcoder/compare/v1.6.0...v1.6.1) (2023-01-23) diff --git a/google/cloud/video/transcoder/gapic_version.py b/google/cloud/video/transcoder/gapic_version.py index b4028ab..f033c61 100644 --- a/google/cloud/video/transcoder/gapic_version.py +++ b/google/cloud/video/transcoder/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "1.6.1" # {x-release-please-version} +__version__ = "1.7.0" # {x-release-please-version} diff --git a/google/cloud/video/transcoder_v1/__init__.py b/google/cloud/video/transcoder_v1/__init__.py index 6a5c73b..205153c 100644 --- a/google/cloud/video/transcoder_v1/__init__.py +++ b/google/cloud/video/transcoder_v1/__init__.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from google.cloud.video.transcoder import gapic_version as package_version +from google.cloud.video.transcoder_v1 import gapic_version as package_version __version__ = package_version.__version__ diff --git a/google/cloud/video/transcoder_v1/gapic_metadata.json b/google/cloud/video/transcoder_v1/gapic_metadata.json index 6651379..aa469ac 100644 --- a/google/cloud/video/transcoder_v1/gapic_metadata.json +++ b/google/cloud/video/transcoder_v1/gapic_metadata.json @@ -96,6 +96,51 @@ ] } } + }, + "rest": { + "libraryClient": "TranscoderServiceClient", + "rpcs": { + "CreateJob": { + "methods": [ + "create_job" + ] + }, + "CreateJobTemplate": { + "methods": [ + "create_job_template" + ] + }, + "DeleteJob": { + "methods": [ + "delete_job" + ] + }, + "DeleteJobTemplate": { + "methods": [ + "delete_job_template" + ] + }, + "GetJob": { + "methods": [ + "get_job" + ] + }, + "GetJobTemplate": { + "methods": [ + "get_job_template" + ] + }, + "ListJobTemplates": { + "methods": [ + "list_job_templates" + ] + }, + "ListJobs": { + "methods": [ + "list_jobs" + ] + } + } } } } diff --git a/google/cloud/video/transcoder_v1/gapic_version.py b/google/cloud/video/transcoder_v1/gapic_version.py index b4028ab..f033c61 100644 --- a/google/cloud/video/transcoder_v1/gapic_version.py +++ b/google/cloud/video/transcoder_v1/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "1.6.1" # {x-release-please-version} +__version__ = "1.7.0" # {x-release-please-version} diff --git a/google/cloud/video/transcoder_v1/services/transcoder_service/client.py b/google/cloud/video/transcoder_v1/services/transcoder_service/client.py index 2eb6ac9..3d7d323 100644 --- a/google/cloud/video/transcoder_v1/services/transcoder_service/client.py +++ b/google/cloud/video/transcoder_v1/services/transcoder_service/client.py @@ -55,6 +55,7 @@ from .transports.base import DEFAULT_CLIENT_INFO, TranscoderServiceTransport from .transports.grpc import TranscoderServiceGrpcTransport from .transports.grpc_asyncio import TranscoderServiceGrpcAsyncIOTransport +from .transports.rest import TranscoderServiceRestTransport class TranscoderServiceClientMeta(type): @@ -70,6 +71,7 @@ class TranscoderServiceClientMeta(type): ) # type: Dict[str, Type[TranscoderServiceTransport]] _transport_registry["grpc"] = TranscoderServiceGrpcTransport _transport_registry["grpc_asyncio"] = TranscoderServiceGrpcAsyncIOTransport + _transport_registry["rest"] = TranscoderServiceRestTransport def get_transport_class( cls, diff --git a/google/cloud/video/transcoder_v1/services/transcoder_service/transports/__init__.py b/google/cloud/video/transcoder_v1/services/transcoder_service/transports/__init__.py index cc28a5c..31082bd 100644 --- a/google/cloud/video/transcoder_v1/services/transcoder_service/transports/__init__.py +++ b/google/cloud/video/transcoder_v1/services/transcoder_service/transports/__init__.py @@ -19,14 +19,18 @@ from .base import TranscoderServiceTransport from .grpc import TranscoderServiceGrpcTransport from .grpc_asyncio import TranscoderServiceGrpcAsyncIOTransport +from .rest import TranscoderServiceRestInterceptor, TranscoderServiceRestTransport # Compile a registry of transports. _transport_registry = OrderedDict() # type: Dict[str, Type[TranscoderServiceTransport]] _transport_registry["grpc"] = TranscoderServiceGrpcTransport _transport_registry["grpc_asyncio"] = TranscoderServiceGrpcAsyncIOTransport +_transport_registry["rest"] = TranscoderServiceRestTransport __all__ = ( "TranscoderServiceTransport", "TranscoderServiceGrpcTransport", "TranscoderServiceGrpcAsyncIOTransport", + "TranscoderServiceRestTransport", + "TranscoderServiceRestInterceptor", ) diff --git a/google/cloud/video/transcoder_v1/services/transcoder_service/transports/rest.py b/google/cloud/video/transcoder_v1/services/transcoder_service/transports/rest.py new file mode 100644 index 0000000..d730688 --- /dev/null +++ b/google/cloud/video/transcoder_v1/services/transcoder_service/transports/rest.py @@ -0,0 +1,1156 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# + +import dataclasses +import json # type: ignore +import re +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, path_template, rest_helpers, rest_streaming +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore +from google.protobuf import json_format +import grpc # type: ignore +from requests import __version__ as requests_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + + +from google.protobuf import empty_pb2 # type: ignore + +from google.cloud.video.transcoder_v1.types import resources, services + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import TranscoderServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class TranscoderServiceRestInterceptor: + """Interceptor for TranscoderService. + + Interceptors are used to manipulate requests, request metadata, and responses + in arbitrary ways. + Example use cases include: + * Logging + * Verifying requests according to service or custom semantics + * Stripping extraneous information from responses + + These use cases and more can be enabled by injecting an + instance of a custom subclass when constructing the TranscoderServiceRestTransport. + + .. code-block:: python + class MyCustomTranscoderServiceInterceptor(TranscoderServiceRestInterceptor): + def pre_create_job(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_create_job(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_create_job_template(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_create_job_template(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_delete_job(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def pre_delete_job_template(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def pre_get_job(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_job(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_get_job_template(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_job_template(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_list_jobs(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_jobs(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_list_job_templates(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_job_templates(self, response): + logging.log(f"Received response: {response}") + return response + + transport = TranscoderServiceRestTransport(interceptor=MyCustomTranscoderServiceInterceptor()) + client = TranscoderServiceClient(transport=transport) + + + """ + + def pre_create_job( + self, request: services.CreateJobRequest, metadata: Sequence[Tuple[str, str]] + ) -> Tuple[services.CreateJobRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for create_job + + Override in a subclass to manipulate the request or metadata + before they are sent to the TranscoderService server. + """ + return request, metadata + + def post_create_job(self, response: resources.Job) -> resources.Job: + """Post-rpc interceptor for create_job + + Override in a subclass to manipulate the response + after it is returned by the TranscoderService server but before + it is returned to user code. + """ + return response + + def pre_create_job_template( + self, + request: services.CreateJobTemplateRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[services.CreateJobTemplateRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for create_job_template + + Override in a subclass to manipulate the request or metadata + before they are sent to the TranscoderService server. + """ + return request, metadata + + def post_create_job_template( + self, response: resources.JobTemplate + ) -> resources.JobTemplate: + """Post-rpc interceptor for create_job_template + + Override in a subclass to manipulate the response + after it is returned by the TranscoderService server but before + it is returned to user code. + """ + return response + + def pre_delete_job( + self, request: services.DeleteJobRequest, metadata: Sequence[Tuple[str, str]] + ) -> Tuple[services.DeleteJobRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for delete_job + + Override in a subclass to manipulate the request or metadata + before they are sent to the TranscoderService server. + """ + return request, metadata + + def pre_delete_job_template( + self, + request: services.DeleteJobTemplateRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[services.DeleteJobTemplateRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for delete_job_template + + Override in a subclass to manipulate the request or metadata + before they are sent to the TranscoderService server. + """ + return request, metadata + + def pre_get_job( + self, request: services.GetJobRequest, metadata: Sequence[Tuple[str, str]] + ) -> Tuple[services.GetJobRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_job + + Override in a subclass to manipulate the request or metadata + before they are sent to the TranscoderService server. + """ + return request, metadata + + def post_get_job(self, response: resources.Job) -> resources.Job: + """Post-rpc interceptor for get_job + + Override in a subclass to manipulate the response + after it is returned by the TranscoderService server but before + it is returned to user code. + """ + return response + + def pre_get_job_template( + self, + request: services.GetJobTemplateRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[services.GetJobTemplateRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_job_template + + Override in a subclass to manipulate the request or metadata + before they are sent to the TranscoderService server. + """ + return request, metadata + + def post_get_job_template( + self, response: resources.JobTemplate + ) -> resources.JobTemplate: + """Post-rpc interceptor for get_job_template + + Override in a subclass to manipulate the response + after it is returned by the TranscoderService server but before + it is returned to user code. + """ + return response + + def pre_list_jobs( + self, request: services.ListJobsRequest, metadata: Sequence[Tuple[str, str]] + ) -> Tuple[services.ListJobsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for list_jobs + + Override in a subclass to manipulate the request or metadata + before they are sent to the TranscoderService server. + """ + return request, metadata + + def post_list_jobs( + self, response: services.ListJobsResponse + ) -> services.ListJobsResponse: + """Post-rpc interceptor for list_jobs + + Override in a subclass to manipulate the response + after it is returned by the TranscoderService server but before + it is returned to user code. + """ + return response + + def pre_list_job_templates( + self, + request: services.ListJobTemplatesRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[services.ListJobTemplatesRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for list_job_templates + + Override in a subclass to manipulate the request or metadata + before they are sent to the TranscoderService server. + """ + return request, metadata + + def post_list_job_templates( + self, response: services.ListJobTemplatesResponse + ) -> services.ListJobTemplatesResponse: + """Post-rpc interceptor for list_job_templates + + Override in a subclass to manipulate the response + after it is returned by the TranscoderService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class TranscoderServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: TranscoderServiceRestInterceptor + + +class TranscoderServiceRestTransport(TranscoderServiceTransport): + """REST backend transport for TranscoderService. + + Using the Transcoder API, you can queue asynchronous jobs for + transcoding media into various output formats. Output formats + may include different streaming standards such as HTTP Live + Streaming (HLS) and Dynamic Adaptive Streaming over HTTP (DASH). + You can also customize jobs using advanced features such as + Digital Rights Management (DRM), audio equalization, content + concatenation, and digital ad-stitch ready content generation. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends JSON representations of protocol buffers over HTTP/1.1 + + """ + + def __init__( + self, + *, + host: str = "transcoder.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + interceptor: Optional[TranscoderServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + 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 + are specified, the client will attempt to ascertain the + credentials from the environment. + + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client + certificate to configure mutual TLS HTTP channel. It is ignored + if ``channel`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you are developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + url_scheme: the protocol scheme for the API endpoint. Normally + "https", but for testing or local servers, + "http" can be specified. + """ + # Run the base constructor + # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc. + # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the + # credentials object + maybe_url_match = re.match("^(?Phttp(?:s)?://)?(?P.*)$", host) + if maybe_url_match is None: + raise ValueError( + f"Unexpected hostname structure: {host}" + ) # pragma: NO COVER + + url_match_items = maybe_url_match.groupdict() + + host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host + + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + self._session = AuthorizedSession( + self._credentials, default_host=self.DEFAULT_HOST + ) + if client_cert_source_for_mtls: + self._session.configure_mtls_channel(client_cert_source_for_mtls) + self._interceptor = interceptor or TranscoderServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _CreateJob(TranscoderServiceRestStub): + def __hash__(self): + return hash("CreateJob") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: services.CreateJobRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> resources.Job: + r"""Call the create job method over HTTP. + + Args: + request (~.services.CreateJobRequest): + The request object. Request message for ``TranscoderService.CreateJob``. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.resources.Job: + Transcoding job resource. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/{parent=projects/*/locations/*}/jobs", + "body": "job", + }, + ] + request, metadata = self._interceptor.pre_create_job(request, metadata) + pb_request = services.CreateJobRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = resources.Job() + pb_resp = resources.Job.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_create_job(resp) + return resp + + class _CreateJobTemplate(TranscoderServiceRestStub): + def __hash__(self): + return hash("CreateJobTemplate") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = { + "jobTemplateId": "", + } + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: services.CreateJobTemplateRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> resources.JobTemplate: + r"""Call the create job template method over HTTP. + + Args: + request (~.services.CreateJobTemplateRequest): + The request object. Request message for + ``TranscoderService.CreateJobTemplate``. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.resources.JobTemplate: + Transcoding job template resource. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/{parent=projects/*/locations/*}/jobTemplates", + "body": "job_template", + }, + ] + request, metadata = self._interceptor.pre_create_job_template( + request, metadata + ) + pb_request = services.CreateJobTemplateRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = resources.JobTemplate() + pb_resp = resources.JobTemplate.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_create_job_template(resp) + return resp + + class _DeleteJob(TranscoderServiceRestStub): + def __hash__(self): + return hash("DeleteJob") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: services.DeleteJobRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ): + r"""Call the delete job method over HTTP. + + Args: + request (~.services.DeleteJobRequest): + The request object. Request message for ``TranscoderService.DeleteJob``. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "delete", + "uri": "/v1/{name=projects/*/locations/*/jobs/*}", + }, + ] + request, metadata = self._interceptor.pre_delete_job(request, metadata) + pb_request = services.DeleteJobRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + class _DeleteJobTemplate(TranscoderServiceRestStub): + def __hash__(self): + return hash("DeleteJobTemplate") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: services.DeleteJobTemplateRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ): + r"""Call the delete job template method over HTTP. + + Args: + request (~.services.DeleteJobTemplateRequest): + The request object. Request message for + ``TranscoderService.DeleteJobTemplate``. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "delete", + "uri": "/v1/{name=projects/*/locations/*/jobTemplates/*}", + }, + ] + request, metadata = self._interceptor.pre_delete_job_template( + request, metadata + ) + pb_request = services.DeleteJobTemplateRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + class _GetJob(TranscoderServiceRestStub): + def __hash__(self): + return hash("GetJob") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: services.GetJobRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> resources.Job: + r"""Call the get job method over HTTP. + + Args: + request (~.services.GetJobRequest): + The request object. Request message for ``TranscoderService.GetJob``. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.resources.Job: + Transcoding job resource. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/jobs/*}", + }, + ] + request, metadata = self._interceptor.pre_get_job(request, metadata) + pb_request = services.GetJobRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = resources.Job() + pb_resp = resources.Job.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_job(resp) + return resp + + class _GetJobTemplate(TranscoderServiceRestStub): + def __hash__(self): + return hash("GetJobTemplate") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: services.GetJobTemplateRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> resources.JobTemplate: + r"""Call the get job template method over HTTP. + + Args: + request (~.services.GetJobTemplateRequest): + The request object. Request message for + ``TranscoderService.GetJobTemplate``. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.resources.JobTemplate: + Transcoding job template resource. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/jobTemplates/*}", + }, + ] + request, metadata = self._interceptor.pre_get_job_template( + request, metadata + ) + pb_request = services.GetJobTemplateRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = resources.JobTemplate() + pb_resp = resources.JobTemplate.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_job_template(resp) + return resp + + class _ListJobs(TranscoderServiceRestStub): + def __hash__(self): + return hash("ListJobs") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: services.ListJobsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> services.ListJobsResponse: + r"""Call the list jobs method over HTTP. + + Args: + request (~.services.ListJobsRequest): + The request object. Request message for ``TranscoderService.ListJobs``. The + parent location from which to retrieve the collection of + jobs. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.services.ListJobsResponse: + Response message for ``TranscoderService.ListJobs``. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{parent=projects/*/locations/*}/jobs", + }, + ] + request, metadata = self._interceptor.pre_list_jobs(request, metadata) + pb_request = services.ListJobsRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = services.ListJobsResponse() + pb_resp = services.ListJobsResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_list_jobs(resp) + return resp + + class _ListJobTemplates(TranscoderServiceRestStub): + def __hash__(self): + return hash("ListJobTemplates") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: services.ListJobTemplatesRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> services.ListJobTemplatesResponse: + r"""Call the list job templates method over HTTP. + + Args: + request (~.services.ListJobTemplatesRequest): + The request object. Request message for + ``TranscoderService.ListJobTemplates``. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.services.ListJobTemplatesResponse: + Response message for + ``TranscoderService.ListJobTemplates``. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{parent=projects/*/locations/*}/jobTemplates", + }, + ] + request, metadata = self._interceptor.pre_list_job_templates( + request, metadata + ) + pb_request = services.ListJobTemplatesRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = services.ListJobTemplatesResponse() + pb_resp = services.ListJobTemplatesResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_list_job_templates(resp) + return resp + + @property + def create_job(self) -> Callable[[services.CreateJobRequest], resources.Job]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._CreateJob(self._session, self._host, self._interceptor) # type: ignore + + @property + def create_job_template( + self, + ) -> Callable[[services.CreateJobTemplateRequest], resources.JobTemplate]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._CreateJobTemplate(self._session, self._host, self._interceptor) # type: ignore + + @property + def delete_job(self) -> Callable[[services.DeleteJobRequest], empty_pb2.Empty]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._DeleteJob(self._session, self._host, self._interceptor) # type: ignore + + @property + def delete_job_template( + self, + ) -> Callable[[services.DeleteJobTemplateRequest], empty_pb2.Empty]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._DeleteJobTemplate(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_job(self) -> Callable[[services.GetJobRequest], resources.Job]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetJob(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_job_template( + self, + ) -> Callable[[services.GetJobTemplateRequest], resources.JobTemplate]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetJobTemplate(self._session, self._host, self._interceptor) # type: ignore + + @property + def list_jobs( + self, + ) -> Callable[[services.ListJobsRequest], services.ListJobsResponse]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ListJobs(self._session, self._host, self._interceptor) # type: ignore + + @property + def list_job_templates( + self, + ) -> Callable[ + [services.ListJobTemplatesRequest], services.ListJobTemplatesResponse + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ListJobTemplates(self._session, self._host, self._interceptor) # type: ignore + + @property + def kind(self) -> str: + return "rest" + + def close(self): + self._session.close() + + +__all__ = ("TranscoderServiceRestTransport",) diff --git a/google/cloud/video/transcoder_v1/types/resources.py b/google/cloud/video/transcoder_v1/types/resources.py index c19e824..250a379 100644 --- a/google/cloud/video/transcoder_v1/types/resources.py +++ b/google/cloud/video/transcoder_v1/types/resources.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.protobuf import duration_pb2 # type: ignore diff --git a/google/cloud/video/transcoder_v1/types/services.py b/google/cloud/video/transcoder_v1/types/services.py index c7b864f..867f711 100644 --- a/google/cloud/video/transcoder_v1/types/services.py +++ b/google/cloud/video/transcoder_v1/types/services.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence import proto # type: ignore diff --git a/noxfile.py b/noxfile.py index e716318..95e58c5 100644 --- a/noxfile.py +++ b/noxfile.py @@ -189,9 +189,9 @@ def unit(session): def install_systemtest_dependencies(session, *constraints): # Use pre-release gRPC for system tests. - # Exclude version 1.49.0rc1 which has a known issue. - # See https://github.com/grpc/grpc/pull/30642 - session.install("--pre", "grpcio!=1.49.0rc1") + # Exclude version 1.52.0rc1 which has a known issue. + # See https://github.com/grpc/grpc/issues/32163 + session.install("--pre", "grpcio!=1.52.0rc1") session.install(*SYSTEM_TEST_STANDARD_DEPENDENCIES, *constraints) @@ -346,9 +346,7 @@ def prerelease_deps(session): unit_deps_all = UNIT_TEST_STANDARD_DEPENDENCIES + UNIT_TEST_EXTERNAL_DEPENDENCIES session.install(*unit_deps_all) system_deps_all = ( - SYSTEM_TEST_STANDARD_DEPENDENCIES - + SYSTEM_TEST_EXTERNAL_DEPENDENCIES - + SYSTEM_TEST_EXTRAS + SYSTEM_TEST_STANDARD_DEPENDENCIES + SYSTEM_TEST_EXTERNAL_DEPENDENCIES ) session.install(*system_deps_all) @@ -378,8 +376,8 @@ def prerelease_deps(session): # dependency of grpc "six", "googleapis-common-protos", - # Exclude version 1.49.0rc1 which has a known issue. See https://github.com/grpc/grpc/pull/30642 - "grpcio!=1.49.0rc1", + # Exclude version 1.52.0rc1 which has a known issue. See https://github.com/grpc/grpc/issues/32163 + "grpcio!=1.52.0rc1", "grpcio-status", "google-api-core", "proto-plus", diff --git a/samples/generated_samples/snippet_metadata_google.cloud.video.transcoder.v1.json b/samples/generated_samples/snippet_metadata_google.cloud.video.transcoder.v1.json index e57df64..ae2619e 100644 --- a/samples/generated_samples/snippet_metadata_google.cloud.video.transcoder.v1.json +++ b/samples/generated_samples/snippet_metadata_google.cloud.video.transcoder.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-video-transcoder", - "version": "1.6.1" + "version": "1.7.0" }, "snippets": [ { diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt index 4cc009a..ef3da3e 100644 --- a/samples/snippets/requirements.txt +++ b/samples/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-api-python-client==2.73.0 +google-api-python-client==2.78.0 grpcio==1.51.1 -google-cloud-video-transcoder==1.6.0 +google-cloud-video-transcoder==1.6.1 diff --git a/setup.py b/setup.py index a2cc3ef..2ad87bf 100644 --- a/setup.py +++ b/setup.py @@ -57,9 +57,7 @@ if package.startswith("google") ] -namespaces = ["google"] -if "google.cloud" in packages: - namespaces.append("google.cloud") +namespaces = ["google", "google.cloud", "google.cloud.video"] setuptools.setup( name=name, diff --git a/tests/unit/gapic/transcoder_v1/test_transcoder_service.py b/tests/unit/gapic/transcoder_v1/test_transcoder_service.py index 97ea34e..194a058 100644 --- a/tests/unit/gapic/transcoder_v1/test_transcoder_service.py +++ b/tests/unit/gapic/transcoder_v1/test_transcoder_service.py @@ -22,6 +22,8 @@ except ImportError: # pragma: NO COVER import mock +from collections.abc import Iterable +import json import math from google.api_core import gapic_v1, grpc_helpers, grpc_helpers_async, path_template @@ -33,6 +35,7 @@ from google.oauth2 import service_account from google.protobuf import any_pb2 # type: ignore from google.protobuf import duration_pb2 # type: ignore +from google.protobuf import json_format from google.protobuf import timestamp_pb2 # type: ignore from google.rpc import status_pb2 # type: ignore import grpc @@ -40,6 +43,8 @@ from proto.marshal.rules import wrappers from proto.marshal.rules.dates import DurationRule, TimestampRule import pytest +from requests import PreparedRequest, Request, Response +from requests.sessions import Session from google.cloud.video.transcoder_v1.services.transcoder_service import ( TranscoderServiceAsyncClient, @@ -100,6 +105,7 @@ def test__get_default_mtls_endpoint(): [ (TranscoderServiceClient, "grpc"), (TranscoderServiceAsyncClient, "grpc_asyncio"), + (TranscoderServiceClient, "rest"), ], ) def test_transcoder_service_client_from_service_account_info( @@ -115,7 +121,11 @@ def test_transcoder_service_client_from_service_account_info( assert client.transport._credentials == creds assert isinstance(client, client_class) - assert client.transport._host == ("transcoder.googleapis.com:443") + assert client.transport._host == ( + "transcoder.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://transcoder.googleapis.com" + ) @pytest.mark.parametrize( @@ -123,6 +133,7 @@ def test_transcoder_service_client_from_service_account_info( [ (transports.TranscoderServiceGrpcTransport, "grpc"), (transports.TranscoderServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.TranscoderServiceRestTransport, "rest"), ], ) def test_transcoder_service_client_service_account_always_use_jwt( @@ -148,6 +159,7 @@ def test_transcoder_service_client_service_account_always_use_jwt( [ (TranscoderServiceClient, "grpc"), (TranscoderServiceAsyncClient, "grpc_asyncio"), + (TranscoderServiceClient, "rest"), ], ) def test_transcoder_service_client_from_service_account_file( @@ -170,13 +182,18 @@ def test_transcoder_service_client_from_service_account_file( assert client.transport._credentials == creds assert isinstance(client, client_class) - assert client.transport._host == ("transcoder.googleapis.com:443") + assert client.transport._host == ( + "transcoder.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://transcoder.googleapis.com" + ) def test_transcoder_service_client_get_transport_class(): transport = TranscoderServiceClient.get_transport_class() available_transports = [ transports.TranscoderServiceGrpcTransport, + transports.TranscoderServiceRestTransport, ] assert transport in available_transports @@ -193,6 +210,7 @@ def test_transcoder_service_client_get_transport_class(): transports.TranscoderServiceGrpcAsyncIOTransport, "grpc_asyncio", ), + (TranscoderServiceClient, transports.TranscoderServiceRestTransport, "rest"), ], ) @mock.patch.object( @@ -348,6 +366,18 @@ def test_transcoder_service_client_client_options( "grpc_asyncio", "false", ), + ( + TranscoderServiceClient, + transports.TranscoderServiceRestTransport, + "rest", + "true", + ), + ( + TranscoderServiceClient, + transports.TranscoderServiceRestTransport, + "rest", + "false", + ), ], ) @mock.patch.object( @@ -547,6 +577,7 @@ def test_transcoder_service_client_get_mtls_endpoint_and_cert_source(client_clas transports.TranscoderServiceGrpcAsyncIOTransport, "grpc_asyncio", ), + (TranscoderServiceClient, transports.TranscoderServiceRestTransport, "rest"), ], ) def test_transcoder_service_client_client_options_scopes( @@ -587,6 +618,12 @@ def test_transcoder_service_client_client_options_scopes( "grpc_asyncio", grpc_helpers_async, ), + ( + TranscoderServiceClient, + transports.TranscoderServiceRestTransport, + "rest", + None, + ), ], ) def test_transcoder_service_client_client_options_credentials_file( @@ -3021,158 +3058,3334 @@ async def test_delete_job_template_flattened_error_async(): ) -def test_credentials_transport_error(): - # It is an error to provide credentials and a transport instance. - transport = transports.TranscoderServiceGrpcTransport( +@pytest.mark.parametrize( + "request_type", + [ + services.CreateJobRequest, + dict, + ], +) +def test_create_job_rest(request_type): + client = TranscoderServiceClient( credentials=ga_credentials.AnonymousCredentials(), + transport="rest", ) - with pytest.raises(ValueError): - client = TranscoderServiceClient( - credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2"} + request_init["job"] = { + "name": "name_value", + "input_uri": "input_uri_value", + "output_uri": "output_uri_value", + "template_id": "template_id_value", + "config": { + "inputs": [ + { + "key": "key_value", + "uri": "uri_value", + "preprocessing_config": { + "color": { + "saturation": 0.10980000000000001, + "contrast": 0.878, + "brightness": 0.1081, + }, + "denoise": {"strength": 0.879, "tune": "tune_value"}, + "deblock": {"strength": 0.879, "enabled": True}, + "audio": {"lufs": 0.442, "high_boost": True, "low_boost": True}, + "crop": { + "top_pixels": 1095, + "bottom_pixels": 1417, + "left_pixels": 1183, + "right_pixels": 1298, + }, + "pad": { + "top_pixels": 1095, + "bottom_pixels": 1417, + "left_pixels": 1183, + "right_pixels": 1298, + }, + "deinterlace": { + "yadif": { + "mode": "mode_value", + "disable_spatial_interlacing": True, + "parity": "parity_value", + "deinterlace_all_frames": True, + }, + "bwdif": { + "mode": "mode_value", + "parity": "parity_value", + "deinterlace_all_frames": True, + }, + }, + }, + } + ], + "edit_list": [ + { + "key": "key_value", + "inputs": ["inputs_value1", "inputs_value2"], + "end_time_offset": {"seconds": 751, "nanos": 543}, + "start_time_offset": {}, + } + ], + "elementary_streams": [ + { + "key": "key_value", + "video_stream": { + "h264": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "allow_open_gop": True, + "gop_frame_count": 1592, + "gop_duration": {}, + "enable_two_pass": True, + "vbv_size_bits": 1401, + "vbv_fullness_bits": 1834, + "entropy_coder": "entropy_coder_value", + "b_pyramid": True, + "b_frame_count": 1364, + "aq_strength": 0.1184, + "profile": "profile_value", + "tune": "tune_value", + "preset": "preset_value", + }, + "h265": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "allow_open_gop": True, + "gop_frame_count": 1592, + "gop_duration": {}, + "enable_two_pass": True, + "vbv_size_bits": 1401, + "vbv_fullness_bits": 1834, + "b_pyramid": True, + "b_frame_count": 1364, + "aq_strength": 0.1184, + "profile": "profile_value", + "tune": "tune_value", + "preset": "preset_value", + }, + "vp9": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "gop_frame_count": 1592, + "gop_duration": {}, + "profile": "profile_value", + }, + }, + "audio_stream": { + "codec": "codec_value", + "bitrate_bps": 1167, + "channel_count": 1377, + "channel_layout": [ + "channel_layout_value1", + "channel_layout_value2", + ], + "mapping_": [ + { + "atom_key": "atom_key_value", + "input_key": "input_key_value", + "input_track": 1188, + "input_channel": 1384, + "output_channel": 1513, + "gain_db": 0.708, + } + ], + "sample_rate_hertz": 1817, + }, + "text_stream": { + "codec": "codec_value", + "mapping_": [ + { + "atom_key": "atom_key_value", + "input_key": "input_key_value", + "input_track": 1188, + } + ], + }, + } + ], + "mux_streams": [ + { + "key": "key_value", + "file_name": "file_name_value", + "container": "container_value", + "elementary_streams": [ + "elementary_streams_value1", + "elementary_streams_value2", + ], + "segment_settings": { + "segment_duration": {}, + "individual_segments": True, + }, + } + ], + "manifests": [ + { + "file_name": "file_name_value", + "type_": 1, + "mux_streams": ["mux_streams_value1", "mux_streams_value2"], + } + ], + "output": {"uri": "uri_value"}, + "ad_breaks": [{"start_time_offset": {}}], + "pubsub_destination": {"topic": "topic_value"}, + "sprite_sheets": [ + { + "format_": "format__value", + "file_prefix": "file_prefix_value", + "sprite_width_pixels": 2058, + "sprite_height_pixels": 2147, + "column_count": 1302, + "row_count": 992, + "start_time_offset": {}, + "end_time_offset": {}, + "total_count": 1196, + "interval": {}, + "quality": 777, + } + ], + "overlays": [ + { + "image": { + "uri": "uri_value", + "resolution": {"x": 0.12, "y": 0.121}, + "alpha": 0.518, + }, + "animations": [ + { + "animation_static": {"xy": {}, "start_time_offset": {}}, + "animation_fade": { + "fade_type": 1, + "xy": {}, + "start_time_offset": {}, + "end_time_offset": {}, + }, + "animation_end": {"start_time_offset": {}}, + } + ], + } + ], + }, + "state": 1, + "create_time": {"seconds": 751, "nanos": 543}, + "start_time": {}, + "end_time": {}, + "ttl_after_completion_days": 2670, + "labels": {}, + "error": { + "code": 411, + "message": "message_value", + "details": [ + { + "type_url": "type.googleapis.com/google.protobuf.Duration", + "value": b"\x08\x0c\x10\xdb\x07", + } + ], + }, + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = resources.Job( + name="name_value", + input_uri="input_uri_value", + output_uri="output_uri_value", + state=resources.Job.ProcessingState.PENDING, + ttl_after_completion_days=2670, + template_id="template_id_value", ) - # It is an error to provide a credentials file and a transport instance. - transport = transports.TranscoderServiceGrpcTransport( - credentials=ga_credentials.AnonymousCredentials(), - ) - with pytest.raises(ValueError): - client = TranscoderServiceClient( - client_options={"credentials_file": "credentials.json"}, - transport=transport, + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = resources.Job.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.create_job(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, resources.Job) + assert response.name == "name_value" + assert response.input_uri == "input_uri_value" + assert response.output_uri == "output_uri_value" + assert response.state == resources.Job.ProcessingState.PENDING + assert response.ttl_after_completion_days == 2670 + + +def test_create_job_rest_required_fields(request_type=services.CreateJobRequest): + transport_class = transports.TranscoderServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, ) + ) - # It is an error to provide an api_key and a transport instance. - transport = transports.TranscoderServiceGrpcTransport( + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).create_job._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).create_job._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = TranscoderServiceClient( credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = resources.Job() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + pb_return_value = resources.Job.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.create_job(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_create_job_rest_unset_required_fields(): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials ) - options = client_options.ClientOptions() - options.api_key = "api_key" - with pytest.raises(ValueError): - client = TranscoderServiceClient( - client_options=options, - transport=transport, - ) - # It is an error to provide an api_key and a credential. - options = mock.Mock() - options.api_key = "api_key" - with pytest.raises(ValueError): - client = TranscoderServiceClient( - client_options=options, credentials=ga_credentials.AnonymousCredentials() + unset_fields = transport.create_job._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "job", + ) ) + ) - # It is an error to provide scopes and a transport instance. - transport = transports.TranscoderServiceGrpcTransport( + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_create_job_rest_interceptors(null_interceptor): + transport = transports.TranscoderServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.TranscoderServiceRestInterceptor(), ) - with pytest.raises(ValueError): - client = TranscoderServiceClient( - client_options={"scopes": ["1", "2"]}, - transport=transport, + client = TranscoderServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "post_create_job" + ) as post, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "pre_create_job" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = services.CreateJobRequest.pb(services.CreateJobRequest()) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = resources.Job.to_json(resources.Job()) + + request = services.CreateJobRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = resources.Job() + + client.create_job( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], ) + pre.assert_called_once() + post.assert_called_once() -def test_transport_instance(): - # A client may be instantiated with a custom transport instance. - transport = transports.TranscoderServiceGrpcTransport( + +def test_create_job_rest_bad_request( + transport: str = "rest", request_type=services.CreateJobRequest +): + client = TranscoderServiceClient( credentials=ga_credentials.AnonymousCredentials(), + transport=transport, ) - client = TranscoderServiceClient(transport=transport) - assert client.transport is transport + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2"} + request_init["job"] = { + "name": "name_value", + "input_uri": "input_uri_value", + "output_uri": "output_uri_value", + "template_id": "template_id_value", + "config": { + "inputs": [ + { + "key": "key_value", + "uri": "uri_value", + "preprocessing_config": { + "color": { + "saturation": 0.10980000000000001, + "contrast": 0.878, + "brightness": 0.1081, + }, + "denoise": {"strength": 0.879, "tune": "tune_value"}, + "deblock": {"strength": 0.879, "enabled": True}, + "audio": {"lufs": 0.442, "high_boost": True, "low_boost": True}, + "crop": { + "top_pixels": 1095, + "bottom_pixels": 1417, + "left_pixels": 1183, + "right_pixels": 1298, + }, + "pad": { + "top_pixels": 1095, + "bottom_pixels": 1417, + "left_pixels": 1183, + "right_pixels": 1298, + }, + "deinterlace": { + "yadif": { + "mode": "mode_value", + "disable_spatial_interlacing": True, + "parity": "parity_value", + "deinterlace_all_frames": True, + }, + "bwdif": { + "mode": "mode_value", + "parity": "parity_value", + "deinterlace_all_frames": True, + }, + }, + }, + } + ], + "edit_list": [ + { + "key": "key_value", + "inputs": ["inputs_value1", "inputs_value2"], + "end_time_offset": {"seconds": 751, "nanos": 543}, + "start_time_offset": {}, + } + ], + "elementary_streams": [ + { + "key": "key_value", + "video_stream": { + "h264": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "allow_open_gop": True, + "gop_frame_count": 1592, + "gop_duration": {}, + "enable_two_pass": True, + "vbv_size_bits": 1401, + "vbv_fullness_bits": 1834, + "entropy_coder": "entropy_coder_value", + "b_pyramid": True, + "b_frame_count": 1364, + "aq_strength": 0.1184, + "profile": "profile_value", + "tune": "tune_value", + "preset": "preset_value", + }, + "h265": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "allow_open_gop": True, + "gop_frame_count": 1592, + "gop_duration": {}, + "enable_two_pass": True, + "vbv_size_bits": 1401, + "vbv_fullness_bits": 1834, + "b_pyramid": True, + "b_frame_count": 1364, + "aq_strength": 0.1184, + "profile": "profile_value", + "tune": "tune_value", + "preset": "preset_value", + }, + "vp9": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "gop_frame_count": 1592, + "gop_duration": {}, + "profile": "profile_value", + }, + }, + "audio_stream": { + "codec": "codec_value", + "bitrate_bps": 1167, + "channel_count": 1377, + "channel_layout": [ + "channel_layout_value1", + "channel_layout_value2", + ], + "mapping_": [ + { + "atom_key": "atom_key_value", + "input_key": "input_key_value", + "input_track": 1188, + "input_channel": 1384, + "output_channel": 1513, + "gain_db": 0.708, + } + ], + "sample_rate_hertz": 1817, + }, + "text_stream": { + "codec": "codec_value", + "mapping_": [ + { + "atom_key": "atom_key_value", + "input_key": "input_key_value", + "input_track": 1188, + } + ], + }, + } + ], + "mux_streams": [ + { + "key": "key_value", + "file_name": "file_name_value", + "container": "container_value", + "elementary_streams": [ + "elementary_streams_value1", + "elementary_streams_value2", + ], + "segment_settings": { + "segment_duration": {}, + "individual_segments": True, + }, + } + ], + "manifests": [ + { + "file_name": "file_name_value", + "type_": 1, + "mux_streams": ["mux_streams_value1", "mux_streams_value2"], + } + ], + "output": {"uri": "uri_value"}, + "ad_breaks": [{"start_time_offset": {}}], + "pubsub_destination": {"topic": "topic_value"}, + "sprite_sheets": [ + { + "format_": "format__value", + "file_prefix": "file_prefix_value", + "sprite_width_pixels": 2058, + "sprite_height_pixels": 2147, + "column_count": 1302, + "row_count": 992, + "start_time_offset": {}, + "end_time_offset": {}, + "total_count": 1196, + "interval": {}, + "quality": 777, + } + ], + "overlays": [ + { + "image": { + "uri": "uri_value", + "resolution": {"x": 0.12, "y": 0.121}, + "alpha": 0.518, + }, + "animations": [ + { + "animation_static": {"xy": {}, "start_time_offset": {}}, + "animation_fade": { + "fade_type": 1, + "xy": {}, + "start_time_offset": {}, + "end_time_offset": {}, + }, + "animation_end": {"start_time_offset": {}}, + } + ], + } + ], + }, + "state": 1, + "create_time": {"seconds": 751, "nanos": 543}, + "start_time": {}, + "end_time": {}, + "ttl_after_completion_days": 2670, + "labels": {}, + "error": { + "code": 411, + "message": "message_value", + "details": [ + { + "type_url": "type.googleapis.com/google.protobuf.Duration", + "value": b"\x08\x0c\x10\xdb\x07", + } + ], + }, + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.create_job(request) -def test_transport_get_channel(): - # A client may be instantiated with a custom transport instance. - transport = transports.TranscoderServiceGrpcTransport( + +def test_create_job_rest_flattened(): + client = TranscoderServiceClient( credentials=ga_credentials.AnonymousCredentials(), + transport="rest", ) - channel = transport.grpc_channel - assert channel - transport = transports.TranscoderServiceGrpcAsyncIOTransport( + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = resources.Job() + + # get arguments that satisfy an http rule for this method + sample_request = {"parent": "projects/sample1/locations/sample2"} + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + job=resources.Job(name="name_value"), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = resources.Job.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.create_job(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{parent=projects/*/locations/*}/jobs" % client.transport._host, + args[1], + ) + + +def test_create_job_rest_flattened_error(transport: str = "rest"): + client = TranscoderServiceClient( credentials=ga_credentials.AnonymousCredentials(), + transport=transport, ) - channel = transport.grpc_channel - assert channel + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.create_job( + services.CreateJobRequest(), + parent="parent_value", + job=resources.Job(name="name_value"), + ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.TranscoderServiceGrpcTransport, - transports.TranscoderServiceGrpcAsyncIOTransport, - ], -) -def test_transport_adc(transport_class): - # Test default credentials are used if not provided. - with mock.patch.object(google.auth, "default") as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class() - adc.assert_called_once() + +def test_create_job_rest_error(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) @pytest.mark.parametrize( - "transport_name", + "request_type", [ - "grpc", + services.ListJobsRequest, + dict, ], ) -def test_transport_kind(transport_name): - transport = TranscoderServiceClient.get_transport_class(transport_name)( +def test_list_jobs_rest(request_type): + client = TranscoderServiceClient( credentials=ga_credentials.AnonymousCredentials(), + transport="rest", ) - assert transport.kind == transport_name + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = services.ListJobsResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = services.ListJobsResponse.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.list_jobs(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListJobsPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] + + +def test_list_jobs_rest_required_fields(request_type=services.ListJobsRequest): + transport_class = transports.TranscoderServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_jobs._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_jobs._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "filter", + "order_by", + "page_size", + "page_token", + ) + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" -def test_transport_grpc_default(): - # A client should use the gRPC transport by default. client = TranscoderServiceClient( credentials=ga_credentials.AnonymousCredentials(), + transport="rest", ) - assert isinstance( - client.transport, - transports.TranscoderServiceGrpcTransport, + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = services.ListJobsResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + pb_return_value = services.ListJobsResponse.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_jobs(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_jobs_rest_unset_required_fields(): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.list_jobs._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "filter", + "orderBy", + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) ) -def test_transcoder_service_base_transport_error(): - # Passing both a credentials object and credentials_file should raise an error - with pytest.raises(core_exceptions.DuplicateCredentialArgs): - transport = transports.TranscoderServiceTransport( - credentials=ga_credentials.AnonymousCredentials(), - credentials_file="credentials.json", +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_jobs_rest_interceptors(null_interceptor): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.TranscoderServiceRestInterceptor(), + ) + client = TranscoderServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "post_list_jobs" + ) as post, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "pre_list_jobs" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = services.ListJobsRequest.pb(services.ListJobsRequest()) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = services.ListJobsResponse.to_json( + services.ListJobsResponse() ) + request = services.ListJobsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = services.ListJobsResponse() -def test_transcoder_service_base_transport(): - # Instantiate the base transport. - with mock.patch( - "google.cloud.video.transcoder_v1.services.transcoder_service.transports.TranscoderServiceTransport.__init__" - ) as Transport: - Transport.return_value = None - transport = transports.TranscoderServiceTransport( - credentials=ga_credentials.AnonymousCredentials(), + client.list_jobs( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], ) - # Every method on the transport should just blindly - # raise NotImplementedError. - methods = ( - "create_job", - "list_jobs", - "get_job", - "delete_job", - "create_job_template", - "list_job_templates", - "get_job_template", - "delete_job_template", - ) - for method in methods: - with pytest.raises(NotImplementedError): - getattr(transport, method)(request=object()) + pre.assert_called_once() + post.assert_called_once() - with pytest.raises(NotImplementedError): - transport.close() + +def test_list_jobs_rest_bad_request( + transport: str = "rest", request_type=services.ListJobsRequest +): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_jobs(request) + + +def test_list_jobs_rest_flattened(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = services.ListJobsResponse() + + # get arguments that satisfy an http rule for this method + sample_request = {"parent": "projects/sample1/locations/sample2"} + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = services.ListJobsResponse.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.list_jobs(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{parent=projects/*/locations/*}/jobs" % client.transport._host, + args[1], + ) + + +def test_list_jobs_rest_flattened_error(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_jobs( + services.ListJobsRequest(), + parent="parent_value", + ) + + +def test_list_jobs_rest_pager(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + services.ListJobsResponse( + jobs=[ + resources.Job(), + resources.Job(), + resources.Job(), + ], + next_page_token="abc", + ), + services.ListJobsResponse( + jobs=[], + next_page_token="def", + ), + services.ListJobsResponse( + jobs=[ + resources.Job(), + ], + next_page_token="ghi", + ), + services.ListJobsResponse( + jobs=[ + resources.Job(), + resources.Job(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple(services.ListJobsResponse.to_json(x) for x in response) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = {"parent": "projects/sample1/locations/sample2"} + + pager = client.list_jobs(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, resources.Job) for i in results) + + pages = list(client.list_jobs(request=sample_request).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.parametrize( + "request_type", + [ + services.GetJobRequest, + dict, + ], +) +def test_get_job_rest(request_type): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/jobs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = resources.Job( + name="name_value", + input_uri="input_uri_value", + output_uri="output_uri_value", + state=resources.Job.ProcessingState.PENDING, + ttl_after_completion_days=2670, + template_id="template_id_value", + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = resources.Job.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.get_job(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, resources.Job) + assert response.name == "name_value" + assert response.input_uri == "input_uri_value" + assert response.output_uri == "output_uri_value" + assert response.state == resources.Job.ProcessingState.PENDING + assert response.ttl_after_completion_days == 2670 + + +def test_get_job_rest_required_fields(request_type=services.GetJobRequest): + transport_class = transports.TranscoderServiceRestTransport + + request_init = {} + request_init["name"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_job._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["name"] = "name_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_job._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = resources.Job() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + pb_return_value = resources.Job.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_job(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_job_rest_unset_required_fields(): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_job._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_job_rest_interceptors(null_interceptor): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.TranscoderServiceRestInterceptor(), + ) + client = TranscoderServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "post_get_job" + ) as post, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "pre_get_job" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = services.GetJobRequest.pb(services.GetJobRequest()) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = resources.Job.to_json(resources.Job()) + + request = services.GetJobRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = resources.Job() + + client.get_job( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_job_rest_bad_request( + transport: str = "rest", request_type=services.GetJobRequest +): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/jobs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_job(request) + + +def test_get_job_rest_flattened(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = resources.Job() + + # get arguments that satisfy an http rule for this method + sample_request = {"name": "projects/sample1/locations/sample2/jobs/sample3"} + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = resources.Job.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.get_job(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{name=projects/*/locations/*/jobs/*}" % client.transport._host, + args[1], + ) + + +def test_get_job_rest_flattened_error(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_job( + services.GetJobRequest(), + name="name_value", + ) + + +def test_get_job_rest_error(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + services.DeleteJobRequest, + dict, + ], +) +def test_delete_job_rest(request_type): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/jobs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = None + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.delete_job(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_job_rest_required_fields(request_type=services.DeleteJobRequest): + transport_class = transports.TranscoderServiceRestTransport + + request_init = {} + request_init["name"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).delete_job._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["name"] = "name_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).delete_job._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("allow_missing",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = None + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "delete", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.delete_job(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_delete_job_rest_unset_required_fields(): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_job._get_unset_required_fields({}) + assert set(unset_fields) == (set(("allowMissing",)) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_job_rest_interceptors(null_interceptor): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.TranscoderServiceRestInterceptor(), + ) + client = TranscoderServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "pre_delete_job" + ) as pre: + pre.assert_not_called() + pb_message = services.DeleteJobRequest.pb(services.DeleteJobRequest()) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + + request = services.DeleteJobRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + + client.delete_job( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + + +def test_delete_job_rest_bad_request( + transport: str = "rest", request_type=services.DeleteJobRequest +): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/jobs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.delete_job(request) + + +def test_delete_job_rest_flattened(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = None + + # get arguments that satisfy an http rule for this method + sample_request = {"name": "projects/sample1/locations/sample2/jobs/sample3"} + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.delete_job(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{name=projects/*/locations/*/jobs/*}" % client.transport._host, + args[1], + ) + + +def test_delete_job_rest_flattened_error(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.delete_job( + services.DeleteJobRequest(), + name="name_value", + ) + + +def test_delete_job_rest_error(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + services.CreateJobTemplateRequest, + dict, + ], +) +def test_create_job_template_rest(request_type): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2"} + request_init["job_template"] = { + "name": "name_value", + "config": { + "inputs": [ + { + "key": "key_value", + "uri": "uri_value", + "preprocessing_config": { + "color": { + "saturation": 0.10980000000000001, + "contrast": 0.878, + "brightness": 0.1081, + }, + "denoise": {"strength": 0.879, "tune": "tune_value"}, + "deblock": {"strength": 0.879, "enabled": True}, + "audio": {"lufs": 0.442, "high_boost": True, "low_boost": True}, + "crop": { + "top_pixels": 1095, + "bottom_pixels": 1417, + "left_pixels": 1183, + "right_pixels": 1298, + }, + "pad": { + "top_pixels": 1095, + "bottom_pixels": 1417, + "left_pixels": 1183, + "right_pixels": 1298, + }, + "deinterlace": { + "yadif": { + "mode": "mode_value", + "disable_spatial_interlacing": True, + "parity": "parity_value", + "deinterlace_all_frames": True, + }, + "bwdif": { + "mode": "mode_value", + "parity": "parity_value", + "deinterlace_all_frames": True, + }, + }, + }, + } + ], + "edit_list": [ + { + "key": "key_value", + "inputs": ["inputs_value1", "inputs_value2"], + "end_time_offset": {"seconds": 751, "nanos": 543}, + "start_time_offset": {}, + } + ], + "elementary_streams": [ + { + "key": "key_value", + "video_stream": { + "h264": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "allow_open_gop": True, + "gop_frame_count": 1592, + "gop_duration": {}, + "enable_two_pass": True, + "vbv_size_bits": 1401, + "vbv_fullness_bits": 1834, + "entropy_coder": "entropy_coder_value", + "b_pyramid": True, + "b_frame_count": 1364, + "aq_strength": 0.1184, + "profile": "profile_value", + "tune": "tune_value", + "preset": "preset_value", + }, + "h265": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "allow_open_gop": True, + "gop_frame_count": 1592, + "gop_duration": {}, + "enable_two_pass": True, + "vbv_size_bits": 1401, + "vbv_fullness_bits": 1834, + "b_pyramid": True, + "b_frame_count": 1364, + "aq_strength": 0.1184, + "profile": "profile_value", + "tune": "tune_value", + "preset": "preset_value", + }, + "vp9": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "gop_frame_count": 1592, + "gop_duration": {}, + "profile": "profile_value", + }, + }, + "audio_stream": { + "codec": "codec_value", + "bitrate_bps": 1167, + "channel_count": 1377, + "channel_layout": [ + "channel_layout_value1", + "channel_layout_value2", + ], + "mapping_": [ + { + "atom_key": "atom_key_value", + "input_key": "input_key_value", + "input_track": 1188, + "input_channel": 1384, + "output_channel": 1513, + "gain_db": 0.708, + } + ], + "sample_rate_hertz": 1817, + }, + "text_stream": { + "codec": "codec_value", + "mapping_": [ + { + "atom_key": "atom_key_value", + "input_key": "input_key_value", + "input_track": 1188, + } + ], + }, + } + ], + "mux_streams": [ + { + "key": "key_value", + "file_name": "file_name_value", + "container": "container_value", + "elementary_streams": [ + "elementary_streams_value1", + "elementary_streams_value2", + ], + "segment_settings": { + "segment_duration": {}, + "individual_segments": True, + }, + } + ], + "manifests": [ + { + "file_name": "file_name_value", + "type_": 1, + "mux_streams": ["mux_streams_value1", "mux_streams_value2"], + } + ], + "output": {"uri": "uri_value"}, + "ad_breaks": [{"start_time_offset": {}}], + "pubsub_destination": {"topic": "topic_value"}, + "sprite_sheets": [ + { + "format_": "format__value", + "file_prefix": "file_prefix_value", + "sprite_width_pixels": 2058, + "sprite_height_pixels": 2147, + "column_count": 1302, + "row_count": 992, + "start_time_offset": {}, + "end_time_offset": {}, + "total_count": 1196, + "interval": {}, + "quality": 777, + } + ], + "overlays": [ + { + "image": { + "uri": "uri_value", + "resolution": {"x": 0.12, "y": 0.121}, + "alpha": 0.518, + }, + "animations": [ + { + "animation_static": {"xy": {}, "start_time_offset": {}}, + "animation_fade": { + "fade_type": 1, + "xy": {}, + "start_time_offset": {}, + "end_time_offset": {}, + }, + "animation_end": {"start_time_offset": {}}, + } + ], + } + ], + }, + "labels": {}, + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = resources.JobTemplate( + name="name_value", + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = resources.JobTemplate.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.create_job_template(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, resources.JobTemplate) + assert response.name == "name_value" + + +def test_create_job_template_rest_required_fields( + request_type=services.CreateJobTemplateRequest, +): + transport_class = transports.TranscoderServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request_init["job_template_id"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + assert "jobTemplateId" not in jsonified_request + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).create_job_template._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + assert "jobTemplateId" in jsonified_request + assert jsonified_request["jobTemplateId"] == request_init["job_template_id"] + + jsonified_request["parent"] = "parent_value" + jsonified_request["jobTemplateId"] = "job_template_id_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).create_job_template._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("job_template_id",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + assert "jobTemplateId" in jsonified_request + assert jsonified_request["jobTemplateId"] == "job_template_id_value" + + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = resources.JobTemplate() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + pb_return_value = resources.JobTemplate.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.create_job_template(request) + + expected_params = [ + ( + "jobTemplateId", + "", + ), + ("$alt", "json;enum-encoding=int"), + ] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_create_job_template_rest_unset_required_fields(): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.create_job_template._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(("jobTemplateId",)) + & set( + ( + "parent", + "jobTemplate", + "jobTemplateId", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_create_job_template_rest_interceptors(null_interceptor): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.TranscoderServiceRestInterceptor(), + ) + client = TranscoderServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "post_create_job_template" + ) as post, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "pre_create_job_template" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = services.CreateJobTemplateRequest.pb( + services.CreateJobTemplateRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = resources.JobTemplate.to_json( + resources.JobTemplate() + ) + + request = services.CreateJobTemplateRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = resources.JobTemplate() + + client.create_job_template( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_create_job_template_rest_bad_request( + transport: str = "rest", request_type=services.CreateJobTemplateRequest +): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2"} + request_init["job_template"] = { + "name": "name_value", + "config": { + "inputs": [ + { + "key": "key_value", + "uri": "uri_value", + "preprocessing_config": { + "color": { + "saturation": 0.10980000000000001, + "contrast": 0.878, + "brightness": 0.1081, + }, + "denoise": {"strength": 0.879, "tune": "tune_value"}, + "deblock": {"strength": 0.879, "enabled": True}, + "audio": {"lufs": 0.442, "high_boost": True, "low_boost": True}, + "crop": { + "top_pixels": 1095, + "bottom_pixels": 1417, + "left_pixels": 1183, + "right_pixels": 1298, + }, + "pad": { + "top_pixels": 1095, + "bottom_pixels": 1417, + "left_pixels": 1183, + "right_pixels": 1298, + }, + "deinterlace": { + "yadif": { + "mode": "mode_value", + "disable_spatial_interlacing": True, + "parity": "parity_value", + "deinterlace_all_frames": True, + }, + "bwdif": { + "mode": "mode_value", + "parity": "parity_value", + "deinterlace_all_frames": True, + }, + }, + }, + } + ], + "edit_list": [ + { + "key": "key_value", + "inputs": ["inputs_value1", "inputs_value2"], + "end_time_offset": {"seconds": 751, "nanos": 543}, + "start_time_offset": {}, + } + ], + "elementary_streams": [ + { + "key": "key_value", + "video_stream": { + "h264": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "allow_open_gop": True, + "gop_frame_count": 1592, + "gop_duration": {}, + "enable_two_pass": True, + "vbv_size_bits": 1401, + "vbv_fullness_bits": 1834, + "entropy_coder": "entropy_coder_value", + "b_pyramid": True, + "b_frame_count": 1364, + "aq_strength": 0.1184, + "profile": "profile_value", + "tune": "tune_value", + "preset": "preset_value", + }, + "h265": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "allow_open_gop": True, + "gop_frame_count": 1592, + "gop_duration": {}, + "enable_two_pass": True, + "vbv_size_bits": 1401, + "vbv_fullness_bits": 1834, + "b_pyramid": True, + "b_frame_count": 1364, + "aq_strength": 0.1184, + "profile": "profile_value", + "tune": "tune_value", + "preset": "preset_value", + }, + "vp9": { + "width_pixels": 1300, + "height_pixels": 1389, + "frame_rate": 0.1046, + "bitrate_bps": 1167, + "pixel_format": "pixel_format_value", + "rate_control_mode": "rate_control_mode_value", + "crf_level": 946, + "gop_frame_count": 1592, + "gop_duration": {}, + "profile": "profile_value", + }, + }, + "audio_stream": { + "codec": "codec_value", + "bitrate_bps": 1167, + "channel_count": 1377, + "channel_layout": [ + "channel_layout_value1", + "channel_layout_value2", + ], + "mapping_": [ + { + "atom_key": "atom_key_value", + "input_key": "input_key_value", + "input_track": 1188, + "input_channel": 1384, + "output_channel": 1513, + "gain_db": 0.708, + } + ], + "sample_rate_hertz": 1817, + }, + "text_stream": { + "codec": "codec_value", + "mapping_": [ + { + "atom_key": "atom_key_value", + "input_key": "input_key_value", + "input_track": 1188, + } + ], + }, + } + ], + "mux_streams": [ + { + "key": "key_value", + "file_name": "file_name_value", + "container": "container_value", + "elementary_streams": [ + "elementary_streams_value1", + "elementary_streams_value2", + ], + "segment_settings": { + "segment_duration": {}, + "individual_segments": True, + }, + } + ], + "manifests": [ + { + "file_name": "file_name_value", + "type_": 1, + "mux_streams": ["mux_streams_value1", "mux_streams_value2"], + } + ], + "output": {"uri": "uri_value"}, + "ad_breaks": [{"start_time_offset": {}}], + "pubsub_destination": {"topic": "topic_value"}, + "sprite_sheets": [ + { + "format_": "format__value", + "file_prefix": "file_prefix_value", + "sprite_width_pixels": 2058, + "sprite_height_pixels": 2147, + "column_count": 1302, + "row_count": 992, + "start_time_offset": {}, + "end_time_offset": {}, + "total_count": 1196, + "interval": {}, + "quality": 777, + } + ], + "overlays": [ + { + "image": { + "uri": "uri_value", + "resolution": {"x": 0.12, "y": 0.121}, + "alpha": 0.518, + }, + "animations": [ + { + "animation_static": {"xy": {}, "start_time_offset": {}}, + "animation_fade": { + "fade_type": 1, + "xy": {}, + "start_time_offset": {}, + "end_time_offset": {}, + }, + "animation_end": {"start_time_offset": {}}, + } + ], + } + ], + }, + "labels": {}, + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.create_job_template(request) + + +def test_create_job_template_rest_flattened(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = resources.JobTemplate() + + # get arguments that satisfy an http rule for this method + sample_request = {"parent": "projects/sample1/locations/sample2"} + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + job_template=resources.JobTemplate(name="name_value"), + job_template_id="job_template_id_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = resources.JobTemplate.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.create_job_template(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{parent=projects/*/locations/*}/jobTemplates" + % client.transport._host, + args[1], + ) + + +def test_create_job_template_rest_flattened_error(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.create_job_template( + services.CreateJobTemplateRequest(), + parent="parent_value", + job_template=resources.JobTemplate(name="name_value"), + job_template_id="job_template_id_value", + ) + + +def test_create_job_template_rest_error(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + services.ListJobTemplatesRequest, + dict, + ], +) +def test_list_job_templates_rest(request_type): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = services.ListJobTemplatesResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = services.ListJobTemplatesResponse.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.list_job_templates(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListJobTemplatesPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] + + +def test_list_job_templates_rest_required_fields( + request_type=services.ListJobTemplatesRequest, +): + transport_class = transports.TranscoderServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_job_templates._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_job_templates._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "filter", + "order_by", + "page_size", + "page_token", + ) + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = services.ListJobTemplatesResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + pb_return_value = services.ListJobTemplatesResponse.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_job_templates(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_job_templates_rest_unset_required_fields(): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.list_job_templates._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "filter", + "orderBy", + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_job_templates_rest_interceptors(null_interceptor): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.TranscoderServiceRestInterceptor(), + ) + client = TranscoderServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "post_list_job_templates" + ) as post, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "pre_list_job_templates" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = services.ListJobTemplatesRequest.pb( + services.ListJobTemplatesRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = services.ListJobTemplatesResponse.to_json( + services.ListJobTemplatesResponse() + ) + + request = services.ListJobTemplatesRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = services.ListJobTemplatesResponse() + + client.list_job_templates( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_list_job_templates_rest_bad_request( + transport: str = "rest", request_type=services.ListJobTemplatesRequest +): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_job_templates(request) + + +def test_list_job_templates_rest_flattened(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = services.ListJobTemplatesResponse() + + # get arguments that satisfy an http rule for this method + sample_request = {"parent": "projects/sample1/locations/sample2"} + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = services.ListJobTemplatesResponse.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.list_job_templates(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{parent=projects/*/locations/*}/jobTemplates" + % client.transport._host, + args[1], + ) + + +def test_list_job_templates_rest_flattened_error(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_job_templates( + services.ListJobTemplatesRequest(), + parent="parent_value", + ) + + +def test_list_job_templates_rest_pager(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + services.ListJobTemplatesResponse( + job_templates=[ + resources.JobTemplate(), + resources.JobTemplate(), + resources.JobTemplate(), + ], + next_page_token="abc", + ), + services.ListJobTemplatesResponse( + job_templates=[], + next_page_token="def", + ), + services.ListJobTemplatesResponse( + job_templates=[ + resources.JobTemplate(), + ], + next_page_token="ghi", + ), + services.ListJobTemplatesResponse( + job_templates=[ + resources.JobTemplate(), + resources.JobTemplate(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple(services.ListJobTemplatesResponse.to_json(x) for x in response) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = {"parent": "projects/sample1/locations/sample2"} + + pager = client.list_job_templates(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, resources.JobTemplate) for i in results) + + pages = list(client.list_job_templates(request=sample_request).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.parametrize( + "request_type", + [ + services.GetJobTemplateRequest, + dict, + ], +) +def test_get_job_template_rest(request_type): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/jobTemplates/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = resources.JobTemplate( + name="name_value", + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = resources.JobTemplate.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.get_job_template(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, resources.JobTemplate) + assert response.name == "name_value" + + +def test_get_job_template_rest_required_fields( + request_type=services.GetJobTemplateRequest, +): + transport_class = transports.TranscoderServiceRestTransport + + request_init = {} + request_init["name"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_job_template._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["name"] = "name_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_job_template._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = resources.JobTemplate() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + pb_return_value = resources.JobTemplate.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_job_template(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_job_template_rest_unset_required_fields(): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_job_template._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_job_template_rest_interceptors(null_interceptor): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.TranscoderServiceRestInterceptor(), + ) + client = TranscoderServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "post_get_job_template" + ) as post, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "pre_get_job_template" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = services.GetJobTemplateRequest.pb(services.GetJobTemplateRequest()) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = resources.JobTemplate.to_json( + resources.JobTemplate() + ) + + request = services.GetJobTemplateRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = resources.JobTemplate() + + client.get_job_template( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_job_template_rest_bad_request( + transport: str = "rest", request_type=services.GetJobTemplateRequest +): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/jobTemplates/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_job_template(request) + + +def test_get_job_template_rest_flattened(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = resources.JobTemplate() + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/jobTemplates/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + pb_return_value = resources.JobTemplate.pb(return_value) + json_return_value = json_format.MessageToJson(pb_return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.get_job_template(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{name=projects/*/locations/*/jobTemplates/*}" + % client.transport._host, + args[1], + ) + + +def test_get_job_template_rest_flattened_error(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_job_template( + services.GetJobTemplateRequest(), + name="name_value", + ) + + +def test_get_job_template_rest_error(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + services.DeleteJobTemplateRequest, + dict, + ], +) +def test_delete_job_template_rest(request_type): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/jobTemplates/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = None + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.delete_job_template(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_job_template_rest_required_fields( + request_type=services.DeleteJobTemplateRequest, +): + transport_class = transports.TranscoderServiceRestTransport + + request_init = {} + request_init["name"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).delete_job_template._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["name"] = "name_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).delete_job_template._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("allow_missing",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = None + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "delete", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.delete_job_template(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_delete_job_template_rest_unset_required_fields(): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_job_template._get_unset_required_fields({}) + assert set(unset_fields) == (set(("allowMissing",)) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_job_template_rest_interceptors(null_interceptor): + transport = transports.TranscoderServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.TranscoderServiceRestInterceptor(), + ) + client = TranscoderServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.TranscoderServiceRestInterceptor, "pre_delete_job_template" + ) as pre: + pre.assert_not_called() + pb_message = services.DeleteJobTemplateRequest.pb( + services.DeleteJobTemplateRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + + request = services.DeleteJobTemplateRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + + client.delete_job_template( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + + +def test_delete_job_template_rest_bad_request( + transport: str = "rest", request_type=services.DeleteJobTemplateRequest +): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/jobTemplates/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.delete_job_template(request) + + +def test_delete_job_template_rest_flattened(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = None + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/jobTemplates/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.delete_job_template(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{name=projects/*/locations/*/jobTemplates/*}" + % client.transport._host, + args[1], + ) + + +def test_delete_job_template_rest_flattened_error(transport: str = "rest"): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.delete_job_template( + services.DeleteJobTemplateRequest(), + name="name_value", + ) + + +def test_delete_job_template_rest_error(): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.TranscoderServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.TranscoderServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = TranscoderServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.TranscoderServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = TranscoderServiceClient( + client_options=options, + transport=transport, + ) + + # It is an error to provide an api_key and a credential. + options = mock.Mock() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = TranscoderServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.TranscoderServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = TranscoderServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.TranscoderServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = TranscoderServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.TranscoderServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.TranscoderServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.TranscoderServiceGrpcTransport, + transports.TranscoderServiceGrpcAsyncIOTransport, + transports.TranscoderServiceRestTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "rest", + ], +) +def test_transport_kind(transport_name): + transport = TranscoderServiceClient.get_transport_class(transport_name)( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert transport.kind == transport_name + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = TranscoderServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.TranscoderServiceGrpcTransport, + ) + + +def test_transcoder_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.TranscoderServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_transcoder_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.video.transcoder_v1.services.transcoder_service.transports.TranscoderServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.TranscoderServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "create_job", + "list_jobs", + "get_job", + "delete_job", + "create_job_template", + "list_job_templates", + "get_job_template", + "delete_job_template", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + with pytest.raises(NotImplementedError): + transport.close() # Catch all for all remaining methods and properties remainder = [ @@ -3252,6 +6465,7 @@ def test_transcoder_service_transport_auth_adc(transport_class): [ transports.TranscoderServiceGrpcTransport, transports.TranscoderServiceGrpcAsyncIOTransport, + transports.TranscoderServiceRestTransport, ], ) def test_transcoder_service_transport_auth_gdch_credentials(transport_class): @@ -3349,11 +6563,23 @@ def test_transcoder_service_grpc_transport_client_cert_source_for_mtls(transport ) +def test_transcoder_service_http_transport_client_cert_source_for_mtls(): + cred = ga_credentials.AnonymousCredentials() + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ) as mock_configure_mtls_channel: + transports.TranscoderServiceRestTransport( + credentials=cred, client_cert_source_for_mtls=client_cert_source_callback + ) + mock_configure_mtls_channel.assert_called_once_with(client_cert_source_callback) + + @pytest.mark.parametrize( "transport_name", [ "grpc", "grpc_asyncio", + "rest", ], ) def test_transcoder_service_host_no_port(transport_name): @@ -3364,7 +6590,11 @@ def test_transcoder_service_host_no_port(transport_name): ), transport=transport_name, ) - assert client.transport._host == ("transcoder.googleapis.com:443") + assert client.transport._host == ( + "transcoder.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://transcoder.googleapis.com" + ) @pytest.mark.parametrize( @@ -3372,6 +6602,7 @@ def test_transcoder_service_host_no_port(transport_name): [ "grpc", "grpc_asyncio", + "rest", ], ) def test_transcoder_service_host_with_port(transport_name): @@ -3382,7 +6613,54 @@ def test_transcoder_service_host_with_port(transport_name): ), transport=transport_name, ) - assert client.transport._host == ("transcoder.googleapis.com:8000") + assert client.transport._host == ( + "transcoder.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://transcoder.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_transcoder_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = TranscoderServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = TranscoderServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.create_job._session + session2 = client2.transport.create_job._session + assert session1 != session2 + session1 = client1.transport.list_jobs._session + session2 = client2.transport.list_jobs._session + assert session1 != session2 + session1 = client1.transport.get_job._session + session2 = client2.transport.get_job._session + assert session1 != session2 + session1 = client1.transport.delete_job._session + session2 = client2.transport.delete_job._session + assert session1 != session2 + session1 = client1.transport.create_job_template._session + session2 = client2.transport.create_job_template._session + assert session1 != session2 + session1 = client1.transport.list_job_templates._session + session2 = client2.transport.list_job_templates._session + assert session1 != session2 + session1 = client1.transport.get_job_template._session + session2 = client2.transport.get_job_template._session + assert session1 != session2 + session1 = client1.transport.delete_job_template._session + session2 = client2.transport.delete_job_template._session + assert session1 != session2 def test_transcoder_service_grpc_transport_channel(): @@ -3707,6 +6985,7 @@ async def test_transport_close_async(): def test_transport_close(): transports = { + "rest": "_session", "grpc": "_grpc_channel", } @@ -3724,6 +7003,7 @@ def test_transport_close(): def test_client_ctx(): transports = [ + "rest", "grpc", ] for transport in transports: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy