Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 24761a2

Browse filesBrowse files
authored
feat(gapic): support mTLS certificates when available (#1566)
chore: librarian update image pull request: 20251216T203515Z
1 parent bea7f78 commit 24761a2
Copy full SHA for 24761a2

File tree

Expand file treeCollapse file tree

15 files changed

+896
-342
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

15 files changed

+896
-342
lines changed
Open diff view settings
Collapse file

‎.librarian/generator-input/setup.py‎

Copy file name to clipboardExpand all lines: .librarian/generator-input/setup.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@
9898
install_requires=dependencies,
9999
extras_require=extras,
100100
python_requires=">=3.7",
101-
scripts=["scripts/fixup_pubsub_v1_keywords.py"],
102101
include_package_data=True,
103102
zip_safe=False,
104103
)
Collapse file

‎.librarian/state.yaml‎

Copy file name to clipboardExpand all lines: .librarian/state.yaml
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
image: us-central1-docker.pkg.dev/cloud-sdk-librarian-prod/images-prod/python-librarian-generator@sha256:ce48ed695c727f7e13efd1fd68f466a55a0d772c87b69158720cec39965bc8b2
1+
image: us-central1-docker.pkg.dev/cloud-sdk-librarian-prod/images-prod/python-librarian-generator@sha256:b8058df4c45e9a6e07f6b4d65b458d0d059241dd34c814f151c8bf6b89211209
22
libraries:
33
- id: google-cloud-pubsub
44
version: 2.33.0
Collapse file

‎google/pubsub_v1/__init__.py‎

Copy file name to clipboardExpand all lines: google/pubsub_v1/__init__.py
+104Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,18 @@
1515
#
1616
from google.pubsub_v1 import gapic_version as package_version
1717

18+
import google.api_core as api_core
19+
import sys
20+
1821
__version__ = package_version.__version__
1922

23+
if sys.version_info >= (3, 8): # pragma: NO COVER
24+
from importlib import metadata
25+
else: # pragma: NO COVER
26+
# TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
27+
# this code path once we drop support for Python 3.7
28+
import importlib_metadata as metadata
29+
2030

2131
from .services.publisher import PublisherClient
2232
from .services.publisher import PublisherAsyncClient
@@ -94,6 +104,100 @@
94104
from .types.schema import Encoding
95105
from .types.schema import SchemaView
96106

107+
if hasattr(api_core, "check_python_version") and hasattr(
108+
api_core, "check_dependency_versions"
109+
): # pragma: NO COVER
110+
api_core.check_python_version("google.pubsub_v1") # type: ignore
111+
api_core.check_dependency_versions("google.pubsub_v1") # type: ignore
112+
else: # pragma: NO COVER
113+
# An older version of api_core is installed which does not define the
114+
# functions above. We do equivalent checks manually.
115+
try:
116+
import warnings
117+
import sys
118+
119+
_py_version_str = sys.version.split()[0]
120+
_package_label = "google.pubsub_v1"
121+
if sys.version_info < (3, 9):
122+
warnings.warn(
123+
"You are using a non-supported Python version "
124+
+ f"({_py_version_str}). Google will not post any further "
125+
+ f"updates to {_package_label} supporting this Python version. "
126+
+ "Please upgrade to the latest Python version, or at "
127+
+ f"least to Python 3.9, and then update {_package_label}.",
128+
FutureWarning,
129+
)
130+
if sys.version_info[:2] == (3, 9):
131+
warnings.warn(
132+
f"You are using a Python version ({_py_version_str}) "
133+
+ f"which Google will stop supporting in {_package_label} in "
134+
+ "January 2026. Please "
135+
+ "upgrade to the latest Python version, or at "
136+
+ "least to Python 3.10, before then, and "
137+
+ f"then update {_package_label}.",
138+
FutureWarning,
139+
)
140+
141+
def parse_version_to_tuple(version_string: str):
142+
"""Safely converts a semantic version string to a comparable tuple of integers.
143+
Example: "4.25.8" -> (4, 25, 8)
144+
Ignores non-numeric parts and handles common version formats.
145+
Args:
146+
version_string: Version string in the format "x.y.z" or "x.y.z<suffix>"
147+
Returns:
148+
Tuple of integers for the parsed version string.
149+
"""
150+
parts = []
151+
for part in version_string.split("."):
152+
try:
153+
parts.append(int(part))
154+
except ValueError:
155+
# If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here.
156+
# This is a simplification compared to 'packaging.parse_version', but sufficient
157+
# for comparing strictly numeric semantic versions.
158+
break
159+
return tuple(parts)
160+
161+
def _get_version(dependency_name):
162+
try:
163+
version_string: str = metadata.version(dependency_name)
164+
parsed_version = parse_version_to_tuple(version_string)
165+
return (parsed_version, version_string)
166+
except Exception:
167+
# Catch exceptions from metadata.version() (e.g., PackageNotFoundError)
168+
# or errors during parse_version_to_tuple
169+
return (None, "--")
170+
171+
_dependency_package = "google.protobuf"
172+
_next_supported_version = "4.25.8"
173+
_next_supported_version_tuple = (4, 25, 8)
174+
_recommendation = " (we recommend 6.x)"
175+
(_version_used, _version_used_string) = _get_version(_dependency_package)
176+
if _version_used and _version_used < _next_supported_version_tuple:
177+
warnings.warn(
178+
f"Package {_package_label} depends on "
179+
+ f"{_dependency_package}, currently installed at version "
180+
+ f"{_version_used_string}. Future updates to "
181+
+ f"{_package_label} will require {_dependency_package} at "
182+
+ f"version {_next_supported_version} or higher{_recommendation}."
183+
+ " Please ensure "
184+
+ "that either (a) your Python environment doesn't pin the "
185+
+ f"version of {_dependency_package}, so that updates to "
186+
+ f"{_package_label} can require the higher version, or "
187+
+ "(b) you manually update your Python environment to use at "
188+
+ f"least version {_next_supported_version} of "
189+
+ f"{_dependency_package}.",
190+
FutureWarning,
191+
)
192+
except Exception:
193+
warnings.warn(
194+
"Could not determine the version of Python "
195+
+ "currently being used. To continue receiving "
196+
+ "updates for {_package_label}, ensure you are "
197+
+ "using a supported version of Python; see "
198+
+ "https://devguide.python.org/versions/"
199+
)
200+
97201
__all__ = (
98202
"PublisherAsyncClient",
99203
"SchemaServiceAsyncClient",
Collapse file

‎google/pubsub_v1/services/publisher/client.py‎

Copy file name to clipboardExpand all lines: google/pubsub_v1/services/publisher/client.py
+32-14Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,34 @@ def _get_default_mtls_endpoint(api_endpoint):
168168
_DEFAULT_ENDPOINT_TEMPLATE = "pubsub.{UNIVERSE_DOMAIN}"
169169
_DEFAULT_UNIVERSE = "googleapis.com"
170170

171+
@staticmethod
172+
def _use_client_cert_effective():
173+
"""Returns whether client certificate should be used for mTLS if the
174+
google-auth version supports should_use_client_cert automatic mTLS enablement.
175+
176+
Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
177+
178+
Returns:
179+
bool: whether client certificate should be used for mTLS
180+
Raises:
181+
ValueError: (If using a version of google-auth without should_use_client_cert and
182+
GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
183+
"""
184+
# check if google-auth version supports should_use_client_cert for automatic mTLS enablement
185+
if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER
186+
return mtls.should_use_client_cert()
187+
else: # pragma: NO COVER
188+
# if unsupported, fallback to reading from env var
189+
use_client_cert_str = os.getenv(
190+
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
191+
).lower()
192+
if use_client_cert_str not in ("true", "false"):
193+
raise ValueError(
194+
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be"
195+
" either `true` or `false`"
196+
)
197+
return use_client_cert_str == "true"
198+
171199
@classmethod
172200
def from_service_account_info(cls, info: dict, *args, **kwargs):
173201
"""Creates an instance of this client using the provided credentials
@@ -427,20 +455,16 @@ def get_mtls_endpoint_and_cert_source(
427455
)
428456
if client_options is None:
429457
client_options = client_options_lib.ClientOptions()
430-
use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
458+
use_client_cert = PublisherClient._use_client_cert_effective()
431459
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
432-
if use_client_cert not in ("true", "false"):
433-
raise ValueError(
434-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
435-
)
436460
if use_mtls_endpoint not in ("auto", "never", "always"):
437461
raise MutualTLSChannelError(
438462
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
439463
)
440464

441465
# Figure out the client cert source to use.
442466
client_cert_source = None
443-
if use_client_cert == "true":
467+
if use_client_cert:
444468
if client_options.client_cert_source:
445469
client_cert_source = client_options.client_cert_source
446470
elif mtls.has_default_client_cert_source():
@@ -472,20 +496,14 @@ def _read_environment_variables():
472496
google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
473497
is not any of ["auto", "never", "always"].
474498
"""
475-
use_client_cert = os.getenv(
476-
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
477-
).lower()
499+
use_client_cert = PublisherClient._use_client_cert_effective()
478500
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
479501
universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
480-
if use_client_cert not in ("true", "false"):
481-
raise ValueError(
482-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
483-
)
484502
if use_mtls_endpoint not in ("auto", "never", "always"):
485503
raise MutualTLSChannelError(
486504
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
487505
)
488-
return use_client_cert == "true", use_mtls_endpoint, universe_domain_env
506+
return use_client_cert, use_mtls_endpoint, universe_domain_env
489507

490508
@staticmethod
491509
def _get_client_cert_source(provided_cert_source, use_cert_flag):
Collapse file

‎google/pubsub_v1/services/schema_service/client.py‎

Copy file name to clipboardExpand all lines: google/pubsub_v1/services/schema_service/client.py
+32-14Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,34 @@ def _get_default_mtls_endpoint(api_endpoint):
153153
_DEFAULT_ENDPOINT_TEMPLATE = "pubsub.{UNIVERSE_DOMAIN}"
154154
_DEFAULT_UNIVERSE = "googleapis.com"
155155

156+
@staticmethod
157+
def _use_client_cert_effective():
158+
"""Returns whether client certificate should be used for mTLS if the
159+
google-auth version supports should_use_client_cert automatic mTLS enablement.
160+
161+
Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
162+
163+
Returns:
164+
bool: whether client certificate should be used for mTLS
165+
Raises:
166+
ValueError: (If using a version of google-auth without should_use_client_cert and
167+
GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
168+
"""
169+
# check if google-auth version supports should_use_client_cert for automatic mTLS enablement
170+
if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER
171+
return mtls.should_use_client_cert()
172+
else: # pragma: NO COVER
173+
# if unsupported, fallback to reading from env var
174+
use_client_cert_str = os.getenv(
175+
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
176+
).lower()
177+
if use_client_cert_str not in ("true", "false"):
178+
raise ValueError(
179+
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be"
180+
" either `true` or `false`"
181+
)
182+
return use_client_cert_str == "true"
183+
156184
@classmethod
157185
def from_service_account_info(cls, info: dict, *args, **kwargs):
158186
"""Creates an instance of this client using the provided credentials
@@ -335,20 +363,16 @@ def get_mtls_endpoint_and_cert_source(
335363
)
336364
if client_options is None:
337365
client_options = client_options_lib.ClientOptions()
338-
use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
366+
use_client_cert = SchemaServiceClient._use_client_cert_effective()
339367
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
340-
if use_client_cert not in ("true", "false"):
341-
raise ValueError(
342-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
343-
)
344368
if use_mtls_endpoint not in ("auto", "never", "always"):
345369
raise MutualTLSChannelError(
346370
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
347371
)
348372

349373
# Figure out the client cert source to use.
350374
client_cert_source = None
351-
if use_client_cert == "true":
375+
if use_client_cert:
352376
if client_options.client_cert_source:
353377
client_cert_source = client_options.client_cert_source
354378
elif mtls.has_default_client_cert_source():
@@ -380,20 +404,14 @@ def _read_environment_variables():
380404
google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
381405
is not any of ["auto", "never", "always"].
382406
"""
383-
use_client_cert = os.getenv(
384-
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
385-
).lower()
407+
use_client_cert = SchemaServiceClient._use_client_cert_effective()
386408
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
387409
universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
388-
if use_client_cert not in ("true", "false"):
389-
raise ValueError(
390-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
391-
)
392410
if use_mtls_endpoint not in ("auto", "never", "always"):
393411
raise MutualTLSChannelError(
394412
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
395413
)
396-
return use_client_cert == "true", use_mtls_endpoint, universe_domain_env
414+
return use_client_cert, use_mtls_endpoint, universe_domain_env
397415

398416
@staticmethod
399417
def _get_client_cert_source(provided_cert_source, use_cert_flag):
Collapse file

‎google/pubsub_v1/services/subscriber/client.py‎

Copy file name to clipboardExpand all lines: google/pubsub_v1/services/subscriber/client.py
+32-14Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,34 @@ def _get_default_mtls_endpoint(api_endpoint):
172172
_DEFAULT_ENDPOINT_TEMPLATE = "pubsub.{UNIVERSE_DOMAIN}"
173173
_DEFAULT_UNIVERSE = "googleapis.com"
174174

175+
@staticmethod
176+
def _use_client_cert_effective():
177+
"""Returns whether client certificate should be used for mTLS if the
178+
google-auth version supports should_use_client_cert automatic mTLS enablement.
179+
180+
Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
181+
182+
Returns:
183+
bool: whether client certificate should be used for mTLS
184+
Raises:
185+
ValueError: (If using a version of google-auth without should_use_client_cert and
186+
GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
187+
"""
188+
# check if google-auth version supports should_use_client_cert for automatic mTLS enablement
189+
if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER
190+
return mtls.should_use_client_cert()
191+
else: # pragma: NO COVER
192+
# if unsupported, fallback to reading from env var
193+
use_client_cert_str = os.getenv(
194+
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
195+
).lower()
196+
if use_client_cert_str not in ("true", "false"):
197+
raise ValueError(
198+
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be"
199+
" either `true` or `false`"
200+
)
201+
return use_client_cert_str == "true"
202+
175203
@classmethod
176204
def from_service_account_info(cls, info: dict, *args, **kwargs):
177205
"""Creates an instance of this client using the provided credentials
@@ -414,20 +442,16 @@ def get_mtls_endpoint_and_cert_source(
414442
)
415443
if client_options is None:
416444
client_options = client_options_lib.ClientOptions()
417-
use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
445+
use_client_cert = SubscriberClient._use_client_cert_effective()
418446
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
419-
if use_client_cert not in ("true", "false"):
420-
raise ValueError(
421-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
422-
)
423447
if use_mtls_endpoint not in ("auto", "never", "always"):
424448
raise MutualTLSChannelError(
425449
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
426450
)
427451

428452
# Figure out the client cert source to use.
429453
client_cert_source = None
430-
if use_client_cert == "true":
454+
if use_client_cert:
431455
if client_options.client_cert_source:
432456
client_cert_source = client_options.client_cert_source
433457
elif mtls.has_default_client_cert_source():
@@ -459,20 +483,14 @@ def _read_environment_variables():
459483
google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
460484
is not any of ["auto", "never", "always"].
461485
"""
462-
use_client_cert = os.getenv(
463-
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
464-
).lower()
486+
use_client_cert = SubscriberClient._use_client_cert_effective()
465487
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
466488
universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
467-
if use_client_cert not in ("true", "false"):
468-
raise ValueError(
469-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
470-
)
471489
if use_mtls_endpoint not in ("auto", "never", "always"):
472490
raise MutualTLSChannelError(
473491
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
474492
)
475-
return use_client_cert == "true", use_mtls_endpoint, universe_domain_env
493+
return use_client_cert, use_mtls_endpoint, universe_domain_env
476494

477495
@staticmethod
478496
def _get_client_cert_source(provided_cert_source, use_cert_flag):
File renamed without changes.
Collapse file

‎noxfile.py‎

Copy file name to clipboardExpand all lines: noxfile.py
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
# DO NOT EDIT THIS FILE OUTSIDE OF `.librarian/generator-input`
18+
# The source of truth for this file is `.librarian/generator-input`
19+
20+
1721
# Generated by synthtool. DO NOT EDIT!
1822

1923
from __future__ import absolute_import

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.