Skip to content

Commit

Permalink
Massive changes for rest transport
Browse files Browse the repository at this point in the history
* Rest transport methods now return callable class instances to
facilitate patching in generated unit tests
* Inject into generated unit tests via parameters
* Add to showcase tests and genericize showcase test file names
* Minor wording cleanups
* Minor bug cleanups
  • Loading branch information
software-dov committed Nov 23, 2021
1 parent b35b647 commit 5e5df3e
Show file tree
Hide file tree
Showing 10 changed files with 2,635 additions and 780 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,29 @@
{% block content %}

import abc
import typing
import packaging.version
from typing import Awaitable, Callable, Dict, Optional, Sequence, Union
import pkg_resources
from typing import Dict, Optional, {% if service.any_server_streaming %}Iterable, {% endif %}{% if service.any_client_streaming %}Iterator, {% endif %}Sequence, Tuple, Type, Union

import google.auth # type: ignore
from google.api_core import gapic_v1 # type: ignore
import google.api_core # type: ignore
from google.api_core import exceptions as core_exceptions # type: ignore
from google.api_core import gapic_v1 # type: ignore
from google.api_core import retry as retries # type: ignore
{% if service.has_lro %}
from google.api_core import operations_v1
{% endif %}
from google.auth import credentials as ga_credentials # type: ignore
from google.oauth2 import service_account # type: ignore

{% filter sort_lines %}
{% for method in service.methods.values() %}
{{ method.input.ident.python_import }}
{{ method.output.ident.python_import }}
{% endfor %}
{% if opts.add_iam_methods %}
from google.iam.v1 import iam_policy_pb2 # type: ignore
from google.iam.v1 import policy_pb2 # type: ignore
{% endif %}
{% endfilter %}

try:
Expand All @@ -33,17 +37,8 @@ try:
except pkg_resources.DistributionNotFound:
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()

try:
# google.auth.__version__ was added in 1.26.0
_GOOGLE_AUTH_VERSION = google.auth.__version__
except AttributeError:
try: # try pkg_resources if it is available
_GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version
except pkg_resources.DistributionNotFound: # pragma: NO COVER
_GOOGLE_AUTH_VERSION = None


class {{ service.name }}Transport(metaclass=abc.ABCMeta):
class {{ service.name }}Transport(abc.ABC):
"""Abstract transport class for {{ service.name }}."""

AUTH_SCOPES = (
Expand All @@ -56,13 +51,14 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):

def __init__(
self, *,
host: str{% if service.host %} = '{{ service.host }}'{% endif %},
host: str = DEFAULT_HOST,
credentials: ga_credentials.Credentials = None,
credentials_file: Optional[str] = None,
scopes: Optional[Sequence[str]] = None,
quota_project_id: Optional[str] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
always_use_jwt_access: Optional[bool] = False,
**kwargs,
) -> None:
"""Instantiate the transport.

Expand Down Expand Up @@ -93,7 +89,7 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
host += ':443'
self._host = host

scopes_kwargs = self._get_scopes_kwargs(self._host, scopes)
scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES}

# Save the scopes.
self._scopes = scopes
Expand All @@ -112,40 +108,16 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
elif credentials is None:
credentials, _ = google.auth.default(**scopes_kwargs, quota_project_id=quota_project_id)

# If the credentials are service account credentials, then always try to use self signed JWT.
if always_use_jwt_access and isinstance(credentials, service_account.Credentials) and hasattr(service_account.Credentials, "with_always_use_jwt_access"):
credentials = credentials.with_always_use_jwt_access(True)

# If no credentials are provided, then determine the appropriate
# defaults.
if credentials is None:
credentials, _ = google.auth.default(scopes=self.AUTH_SCOPES)

# Save the credentials.
self._credentials = credentials

# Lifted into its own function so it can be stubbed out during tests.
self._prep_wrapped_messages(client_info)


# TODO: Remove this function once google-auth >= 1.25.0 is required
@classmethod
def _get_scopes_kwargs(cls, host: str, scopes: Optional[Sequence[str]]) -> Dict[str, Optional[Sequence[str]]]:
"""Returns scopes kwargs to pass to google-auth methods depending on the google-auth version"""

scopes_kwargs = {}

if _GOOGLE_AUTH_VERSION and (
packaging.version.parse(_GOOGLE_AUTH_VERSION)
>= packaging.version.parse("1.25.0")
):
scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES}
else:
scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES}

return scopes_kwargs

def _prep_wrapped_messages(self, client_info):
# Precomputed wrapped methods
# Precompute the wrapped methods.
self._wrapped_methods = {
{% for method in service.methods.values() %}
self.{{ method.name|snake_case }}: gapic_v1.method.wrap_method(
Expand All @@ -172,7 +144,7 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
def close(self):
"""Closes resources associated with the transport.

.. warning::
.. warning::
Only call this method if the transport is NOT shared
with other clients - this may cause errors in other clients!
"""
Expand All @@ -183,18 +155,53 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta):
@property
def operations_client(self):
"""Return the client designed to process long-running operations."""
raise NotImplementedError
raise NotImplementedError()
{% endif %}
{% for method in service.methods.values() %}

@property
def {{ method.name|snake_case }}(self) -> typing.Callable[
def {{ method.name|snake_case }}(self) -> Callable[
[{{ method.input.ident }}],
{{ method.output.ident }}]:
raise NotImplementedError
Union[
{{ method.output.ident }},
Awaitable[{{ method.output.ident }}]
]]:
raise NotImplementedError()
{% endfor %}


{% if opts.add_iam_methods %}
@property
def set_iam_policy(
self,
) -> Callable[
[iam_policy_pb2.SetIamPolicyRequest],
Union[policy_pb2.Policy, Awaitable[policy_pb2.Policy]],
]:
raise NotImplementedError()

@property
def get_iam_policy(
self,
) -> Callable[
[iam_policy_pb2.GetIamPolicyRequest],
Union[policy_pb2.Policy, Awaitable[policy_pb2.Policy]],
]:
raise NotImplementedError()

@property
def test_iam_permissions(
self,
) -> Callable[
[iam_policy_pb2.TestIamPermissionsRequest],
Union[
iam_policy_pb2.TestIamPermissionsResponse,
Awaitable[iam_policy_pb2.TestIamPermissionsResponse],
],
]:
raise NotImplementedError()
{% endif %}

__all__ = (
'{{ service.name }}Transport',
)
Expand Down
Loading

0 comments on commit 5e5df3e

Please sign in to comment.