feat(gapic): support mTLS certificates when available (#1467) · googleapis/python-spanner@df87c3e

@@ -15,8 +15,18 @@

1515

#

1616

from google.cloud.spanner_admin_database_v1 import gapic_version as package_version

171718+

import google.api_core as api_core

19+

import sys

20+1821

__version__ = package_version.__version__

192223+

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+20302131

from .services.database_admin import DatabaseAdminClient

2232

from .services.database_admin import DatabaseAdminAsyncClient

8393

from .types.spanner_database_admin import UpdateDatabaseRequest

8494

from .types.spanner_database_admin import RestoreSourceType

859596+

if hasattr(api_core, "check_python_version") and hasattr(

97+

api_core, "check_dependency_versions"

98+

): # pragma: NO COVER

99+

api_core.check_python_version("google.cloud.spanner_admin_database_v1") # type: ignore

100+

api_core.check_dependency_versions("google.cloud.spanner_admin_database_v1") # type: ignore

101+

else: # pragma: NO COVER

102+

# An older version of api_core is installed which does not define the

103+

# functions above. We do equivalent checks manually.

104+

try:

105+

import warnings

106+

import sys

107+108+

_py_version_str = sys.version.split()[0]

109+

_package_label = "google.cloud.spanner_admin_database_v1"

110+

if sys.version_info < (3, 9):

111+

warnings.warn(

112+

"You are using a non-supported Python version "

113+

+ f"({_py_version_str}). Google will not post any further "

114+

+ f"updates to {_package_label} supporting this Python version. "

115+

+ "Please upgrade to the latest Python version, or at "

116+

+ f"least to Python 3.9, and then update {_package_label}.",

117+

FutureWarning,

118+

)

119+

if sys.version_info[:2] == (3, 9):

120+

warnings.warn(

121+

f"You are using a Python version ({_py_version_str}) "

122+

+ f"which Google will stop supporting in {_package_label} in "

123+

+ "January 2026. Please "

124+

+ "upgrade to the latest Python version, or at "

125+

+ "least to Python 3.10, before then, and "

126+

+ f"then update {_package_label}.",

127+

FutureWarning,

128+

)

129+130+

def parse_version_to_tuple(version_string: str):

131+

"""Safely converts a semantic version string to a comparable tuple of integers.

132+

Example: "4.25.8" -> (4, 25, 8)

133+

Ignores non-numeric parts and handles common version formats.

134+

Args:

135+

version_string: Version string in the format "x.y.z" or "x.y.z<suffix>"

136+

Returns:

137+

Tuple of integers for the parsed version string.

138+

"""

139+

parts = []

140+

for part in version_string.split("."):

141+

try:

142+

parts.append(int(part))

143+

except ValueError:

144+

# If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here.

145+

# This is a simplification compared to 'packaging.parse_version', but sufficient

146+

# for comparing strictly numeric semantic versions.

147+

break

148+

return tuple(parts)

149+150+

def _get_version(dependency_name):

151+

try:

152+

version_string: str = metadata.version(dependency_name)

153+

parsed_version = parse_version_to_tuple(version_string)

154+

return (parsed_version, version_string)

155+

except Exception:

156+

# Catch exceptions from metadata.version() (e.g., PackageNotFoundError)

157+

# or errors during parse_version_to_tuple

158+

return (None, "--")

159+160+

_dependency_package = "google.protobuf"

161+

_next_supported_version = "4.25.8"

162+

_next_supported_version_tuple = (4, 25, 8)

163+

_recommendation = " (we recommend 6.x)"

164+

(_version_used, _version_used_string) = _get_version(_dependency_package)

165+

if _version_used and _version_used < _next_supported_version_tuple:

166+

warnings.warn(

167+

f"Package {_package_label} depends on "

168+

+ f"{_dependency_package}, currently installed at version "

169+

+ f"{_version_used_string}. Future updates to "

170+

+ f"{_package_label} will require {_dependency_package} at "

171+

+ f"version {_next_supported_version} or higher{_recommendation}."

172+

+ " Please ensure "

173+

+ "that either (a) your Python environment doesn't pin the "

174+

+ f"version of {_dependency_package}, so that updates to "

175+

+ f"{_package_label} can require the higher version, or "

176+

+ "(b) you manually update your Python environment to use at "

177+

+ f"least version {_next_supported_version} of "

178+

+ f"{_dependency_package}.",

179+

FutureWarning,

180+

)

181+

except Exception:

182+

warnings.warn(

183+

"Could not determine the version of Python "

184+

+ "currently being used. To continue receiving "

185+

+ "updates for {_package_label}, ensure you are "

186+

+ "using a supported version of Python; see "

187+

+ "https://devguide.python.org/versions/"

188+

)

189+86190

__all__ = (

87191

"DatabaseAdminAsyncClient",

88192

"AddSplitPointsRequest",