Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8ea95e9
chore: unpin mypy check version
daniel-sanche Jan 20, 2026
e42c823
updated goldens
daniel-sanche Jan 20, 2026
7847002
handle empty requests in mixins
daniel-sanche Jan 20, 2026
e476732
allow dict as request type
daniel-sanche Jan 20, 2026
3cb8e92
handle none case in _get_default_mtls_endpoint
daniel-sanche Jan 20, 2026
7680213
add check_untyped_defs
daniel-sanche Jan 20, 2026
b8e99f4
fixed binary dump format
daniel-sanche Jan 20, 2026
75748ee
fixed inconsistent typing in api_endpoint
daniel-sanche Jan 21, 2026
0118aaf
fixed typo
daniel-sanche Jan 21, 2026
fb5f0cb
updated tests
daniel-sanche Jan 21, 2026
7189985
fixed missing bracket
daniel-sanche Jan 21, 2026
ffd53ad
updated mypy in other noxfiles
daniel-sanche Jan 21, 2026
4e8a7a6
added changes to ads-templates
daniel-sanche Jan 21, 2026
6664f75
updated ads template tests
daniel-sanche Jan 21, 2026
f394d57
updated async mixins
daniel-sanche Jan 21, 2026
7b7c8dc
updated iam templates
daniel-sanche Jan 21, 2026
96f14a3
updated async iam methods
daniel-sanche Jan 21, 2026
7264e63
updated iam methods in ads-template
daniel-sanche Jan 21, 2026
cbe19db
updated some goldens
daniel-sanche Jan 21, 2026
3920092
improved typing
daniel-sanche Jan 21, 2026
681e626
updated more goldens
daniel-sanche Jan 21, 2026
10007c2
updated api_endpoint type
daniel-sanche Jan 21, 2026
1a3afcd
set api_endpoint to empty string
daniel-sanche Jan 21, 2026
51b2253
updated goldens
daniel-sanche Jan 21, 2026
b50adfc
updated wrapped methods type
daniel-sanche Jan 21, 2026
c98f2f0
updated goldens
daniel-sanche Jan 21, 2026
e5ee739
Merge branch 'main' into unpin_mypy
daniel-sanche Jan 30, 2026
06b2000
Merge branch 'main' into unpin_mypy
daniel-sanche Feb 2, 2026
de47a24
Merge branch 'main' into unpin_mypy
daniel-sanche Feb 7, 2026
89964fc
removed Any from type definition
daniel-sanche Feb 7, 2026
0354666
remove Any from ads templates
daniel-sanche Feb 7, 2026
665c7c8
capitalize comments
daniel-sanche Feb 7, 2026
7f6c4ac
update goldens
daniel-sanche Feb 7, 2026
8d236ca
Merge branch 'main' into unpin_mypy
daniel-sanche Feb 13, 2026
0fd2443
Merge branch 'main' into unpin_mypy
daniel-sanche Feb 24, 2026
6077c20
add spacing to _test_mixins
daniel-sanche Feb 24, 2026
eb825b3
regenerated goldens
daniel-sanche Feb 25, 2026
610541d
Merge branch 'main' into unpin_mypy
daniel-sanche Mar 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
This class implements API version {{ service.version }}.{% endif %}"""

@staticmethod
def _get_default_mtls_endpoint(api_endpoint):
def _get_default_mtls_endpoint(api_endpoint) -> Optional[str]:
"""Converts api endpoint to mTLS endpoint.

Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
"*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
Args:
api_endpoint (Optional[str]): the api endpoint to convert.
Returns:
str: converted mTLS api endpoint.
Optional[str]: converted mTLS api endpoint.
"""
if not api_endpoint:
return api_endpoint
Expand All @@ -118,6 +118,9 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
)

m = mtls_endpoint_re.match(api_endpoint)
if m is None:
# could not parse api_endpoint; return as-is
return api_endpoint
name, mtls, sandbox, googledomain = m.groups()
if mtls or not googledomain:
return api_endpoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{% if "ListOperations" in api.mixin_api_methods %}
def list_operations(
self,
request: Optional[operations_pb2.ListOperationsRequest] = None,
request: Optional[Union[operations_pb2.ListOperationsRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand All @@ -26,6 +26,8 @@
# Create or coerce a protobuf request object.
# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = operations_pb2.ListOperationsRequest(**request)

Expand Down Expand Up @@ -59,7 +61,7 @@
{% if "GetOperation" in api.mixin_api_methods %}
def get_operation(
self,
request: Optional[operations_pb2.GetOperationRequest] = None,
request: Optional[Union[operations_pb2.GetOperationRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand All @@ -82,6 +84,8 @@
# Create or coerce a protobuf request object.
# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = operations_pb2.GetOperationRequest(**request)

Expand Down Expand Up @@ -114,7 +118,7 @@
{% if "DeleteOperation" in api.mixin_api_methods %}
def delete_operation(
self,
request: Optional[operations_pb2.DeleteOperationRequest] = None,
request: Optional[Union[operations_pb2.DeleteOperationRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand All @@ -141,6 +145,8 @@
# Create or coerce a protobuf request object.
# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = operations_pb2.DeleteOperationRequest(**request)

Expand All @@ -165,7 +171,7 @@
{% if "CancelOperation" in api.mixin_api_methods %}
def cancel_operation(
self,
request: Optional[operations_pb2.CancelOperationRequest] = None,
request: Optional[Union[operations_pb2.CancelOperationRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand All @@ -191,6 +197,8 @@
# Create or coerce a protobuf request object.
# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = operations_pb2.CancelOperationRequest(**request)

Expand All @@ -215,7 +223,7 @@
{% if "WaitOperation" in api.mixin_api_methods %}
def wait_operation(
self,
request: Optional[operations_pb2.WaitOperationRequest] = None,
request: Optional[Union[operations_pb2.WaitOperationRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand Down Expand Up @@ -244,6 +252,8 @@
# Create or coerce a protobuf request object.
# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = operations_pb2.WaitOperationRequest(**request)

Expand Down Expand Up @@ -281,7 +291,7 @@
{% if "SetIamPolicy" in api.mixin_api_methods %}
def set_iam_policy(
self,
request: Optional[iam_policy_pb2.SetIamPolicyRequest] = None,
request: Optional[Union[iam_policy_pb2.SetIamPolicyRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand Down Expand Up @@ -370,6 +380,8 @@

# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = iam_policy_pb2.SetIamPolicyRequest(**request)

Expand Down Expand Up @@ -402,7 +414,7 @@
{% if "GetIamPolicy" in api.mixin_api_methods %}
def get_iam_policy(
self,
request: Optional[iam_policy_pb2.GetIamPolicyRequest] = None,
request: Optional[Union[iam_policy_pb2.GetIamPolicyRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand Down Expand Up @@ -492,6 +504,8 @@

# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = iam_policy_pb2.GetIamPolicyRequest(**request)

Expand Down Expand Up @@ -524,7 +538,7 @@
{% if "TestIamPermissions" in api.mixin_api_methods %}
def test_iam_permissions(
self,
request: Optional[iam_policy_pb2.TestIamPermissionsRequest] = None,
request: Optional[Union[iam_policy_pb2.TestIamPermissionsRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand Down Expand Up @@ -552,6 +566,8 @@

# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = iam_policy_pb2.TestIamPermissionsRequest(**request)

Expand Down Expand Up @@ -588,7 +604,7 @@
{% if "GetLocation" in api.mixin_api_methods %}
def get_location(
self,
request: Optional[locations_pb2.GetLocationRequest] = None,
request: Optional[Union[locations_pb2.GetLocationRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand All @@ -611,6 +627,8 @@
# Create or coerce a protobuf request object.
# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = locations_pb2.GetLocationRequest(**request)

Expand Down Expand Up @@ -643,7 +661,7 @@
{% if "ListLocations" in api.mixin_api_methods %}
def list_locations(
self,
request: Optional[locations_pb2.ListLocationsRequest] = None,
request: Optional[Union[locations_pb2.ListLocationsRequest, dict] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
Expand All @@ -666,6 +684,8 @@
# Create or coerce a protobuf request object.
# The request isn't a proto-plus wrapped type,
# so it must be constructed via keyword expansion.
if request is None:
request = {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Initializing request to an empty dictionary when it's None is a good practice. This ensures that the subsequent isinstance(request, dict) check and keyword expansion for protobuf message construction work as expected, preventing potential TypeError or AttributeError if None was passed directly.

if isinstance(request, dict):
request = locations_pb2.ListLocationsRequest(**request)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ def _get_http_options():
elif isinstance(request, google.protobuf.message.Message):
request_payload = MessageToJson(request)
else:
request_payload = f"{type(request).__name__}: {pickle.dumps(request)}"
request_payload = f"{type(request).__name__}: {pickle.dumps(request)!r}"

request_metadata = {
key: value.decode("utf-8") if isinstance(value, bytes) else value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class {{ service.async_client_name }}:
return self._client.transport

@property
def api_endpoint(self):
def api_endpoint(self) -> str:
"""Return the API endpoint used by the client instance.

Returns:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,15 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
This class implements API version {{ service.version }}.{% endif %}"""

@staticmethod
def _get_default_mtls_endpoint(api_endpoint):
def _get_default_mtls_endpoint(api_endpoint) -> Optional[str]:
"""Converts api endpoint to mTLS endpoint.

Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
"*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
Args:
api_endpoint (Optional[str]): the api endpoint to convert.
Returns:
str: converted mTLS api endpoint.
Optional[str]: converted mTLS api endpoint.
"""
if not api_endpoint:
return api_endpoint
Expand All @@ -161,6 +161,10 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
)

m = mtls_endpoint_re.match(api_endpoint)
if m is None:
# could not parse api_endpoint; return as-is
return api_endpoint

name, mtls, sandbox, googledomain = m.groups()
if mtls or not googledomain:
return api_endpoint
Expand Down Expand Up @@ -387,7 +391,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
return client_cert_source

@staticmethod
def _get_api_endpoint(api_override, client_cert_source, universe_domain, use_mtls_endpoint):
def _get_api_endpoint(api_override, client_cert_source, universe_domain, use_mtls_endpoint) -> str:
"""Return the API endpoint used by the client.

Args:
Expand Down Expand Up @@ -473,7 +477,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
error._details.append(json.dumps(cred_info))

@property
def api_endpoint(self):
def api_endpoint(self) -> str:
"""Return the API endpoint used by the client instance.

Returns:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class _LoggingClientInterceptor(grpc.UnaryUnaryClientInterceptor): # pragma: NO
elif isinstance(result, google.protobuf.message.Message):
response_payload = MessageToJson(result)
else:
response_payload = f"{type(result).__name__}: {pickle.dumps(result)}"
response_payload = f"{type(result).__name__}: {pickle.dumps(result)!r}"
grpc_response = {
"payload": response_payload,
"metadata": metadata,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class _LoggingClientAIOInterceptor(grpc.aio.UnaryUnaryClientInterceptor): # pra
elif isinstance(result, google.protobuf.message.Message):
response_payload = MessageToJson(result)
else:
response_payload = f"{type(result).__name__}: {pickle.dumps(result)}"
response_payload = f"{type(result).__name__}: {pickle.dumps(result)!r}"
grpc_response = {
"payload": response_payload,
"metadata": metadata,
Expand Down
5 changes: 3 additions & 2 deletions gapic/templates/noxfile.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ nox.options.error_on_missing_interpreters = True
def mypy(session):
"""Run the type checker."""
session.install(
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2410): Use the latest version of mypy
"mypy<1.16.0",
"mypy",
"types-requests",
"types-protobuf",
)
Expand All @@ -105,6 +104,8 @@ def mypy(session):
{% else %}
"{{ api.naming.versioned_module_name }}",
{% endif %}
"--check-untyped-defs",
*session.posargs,
Comment on lines +104 to +105
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding --check-untyped-defs to the mypy command enforces stricter type checking, which is a good practice for maintaining high code quality and catching potential type-related bugs early. Including *session.posargs also makes the nox session more flexible for custom mypy runs.

)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,15 @@ def test__get_default_mtls_endpoint():
sandbox_endpoint = "example.sandbox.googleapis.com"
sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com"
non_googleapi = "api.example.com"
custom_endpoint = ".custom"

assert {{ service.client_name }}._get_default_mtls_endpoint(None) is None
assert {{ service.client_name }}._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint
assert {{ service.client_name }}._get_default_mtls_endpoint(api_mtls_endpoint) == api_mtls_endpoint
assert {{ service.client_name }}._get_default_mtls_endpoint(sandbox_endpoint) == sandbox_mtls_endpoint
assert {{ service.client_name }}._get_default_mtls_endpoint(sandbox_mtls_endpoint) == sandbox_mtls_endpoint
assert {{ service.client_name }}._get_default_mtls_endpoint(non_googleapi) == non_googleapi
assert {{ service.client_name }}._get_default_mtls_endpoint(custom_endpoint) == custom_endpoint

def test__read_environment_variables():
assert {{ service.client_name }}._read_environment_variables() == (False, "auto", None)
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/goldens/asset/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
def mypy(session):
"""Run the type checker."""
session.install(
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2410): Use the latest version of mypy
"mypy<1.16.0",
"mypy",
"types-requests",
"types-protobuf",
)
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/goldens/credentials/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
def mypy(session):
"""Run the type checker."""
session.install(
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2410): Use the latest version of mypy
"mypy<1.16.0",
"mypy",
"types-requests",
"types-protobuf",
)
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/goldens/eventarc/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
def mypy(session):
"""Run the type checker."""
session.install(
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2410): Use the latest version of mypy
"mypy<1.16.0",
"mypy",
"types-requests",
"types-protobuf",
)
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/goldens/logging/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
def mypy(session):
"""Run the type checker."""
session.install(
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2410): Use the latest version of mypy
"mypy<1.16.0",
"mypy",
"types-requests",
"types-protobuf",
)
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/goldens/logging_internal/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
def mypy(session):
"""Run the type checker."""
session.install(
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2410): Use the latest version of mypy
"mypy<1.16.0",
"mypy",
"types-requests",
"types-protobuf",
)
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/goldens/redis/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
def mypy(session):
"""Run the type checker."""
session.install(
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2410): Use the latest version of mypy
"mypy<1.16.0",
"mypy",
"types-requests",
"types-protobuf",
)
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/goldens/redis_selective/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
def mypy(session):
"""Run the type checker."""
session.install(
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2410): Use the latest version of mypy
"mypy<1.16.0",
"mypy",
"types-requests",
"types-protobuf",
)
Expand Down
Loading