google-cloud-devicestreaming 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {google_cloud_devicestreaming-0.2.0/google_cloud_devicestreaming.egg-info → google_cloud_devicestreaming-0.3.0}/PKG-INFO +1 -1
  2. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming/gapic_version.py +1 -1
  3. google_cloud_devicestreaming-0.3.0/google/cloud/devicestreaming_v1/__init__.py +171 -0
  4. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/gapic_version.py +1 -1
  5. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/client.py +32 -14
  6. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0/google_cloud_devicestreaming.egg-info}/PKG-INFO +1 -1
  7. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/tests/unit/gapic/devicestreaming_v1/test_direct_access_service.py +226 -29
  8. google_cloud_devicestreaming-0.2.0/google/cloud/devicestreaming_v1/__init__.py +0 -67
  9. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/LICENSE +0 -0
  10. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/MANIFEST.in +0 -0
  11. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/README.rst +0 -0
  12. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming/__init__.py +0 -0
  13. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming/py.typed +0 -0
  14. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/gapic_metadata.json +0 -0
  15. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/py.typed +0 -0
  16. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/__init__.py +0 -0
  17. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/__init__.py +0 -0
  18. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/async_client.py +0 -0
  19. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/pagers.py +0 -0
  20. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/transports/__init__.py +0 -0
  21. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/transports/base.py +0 -0
  22. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/transports/grpc.py +0 -0
  23. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/transports/grpc_asyncio.py +0 -0
  24. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/transports/rest.py +0 -0
  25. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/services/direct_access_service/transports/rest_base.py +0 -0
  26. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/types/__init__.py +0 -0
  27. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/types/adb_service.py +0 -0
  28. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google/cloud/devicestreaming_v1/types/service.py +0 -0
  29. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google_cloud_devicestreaming.egg-info/SOURCES.txt +0 -0
  30. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google_cloud_devicestreaming.egg-info/dependency_links.txt +0 -0
  31. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google_cloud_devicestreaming.egg-info/not-zip-safe +0 -0
  32. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google_cloud_devicestreaming.egg-info/requires.txt +0 -0
  33. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/google_cloud_devicestreaming.egg-info/top_level.txt +0 -0
  34. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/setup.cfg +0 -0
  35. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/setup.py +0 -0
  36. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/tests/__init__.py +0 -0
  37. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/tests/unit/__init__.py +0 -0
  38. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/tests/unit/gapic/__init__.py +0 -0
  39. {google_cloud_devicestreaming-0.2.0 → google_cloud_devicestreaming-0.3.0}/tests/unit/gapic/devicestreaming_v1/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-cloud-devicestreaming
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Google Cloud Devicestreaming API client library
5
5
  Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-devicestreaming
6
6
  Author: Google LLC
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "0.2.0" # {x-release-please-version}
16
+ __version__ = "0.3.0" # {x-release-please-version}
@@ -0,0 +1,171 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2025 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ import sys
17
+
18
+ import google.api_core as api_core
19
+
20
+ from google.cloud.devicestreaming_v1 import gapic_version as package_version
21
+
22
+ __version__ = package_version.__version__
23
+
24
+ if sys.version_info >= (3, 8): # pragma: NO COVER
25
+ from importlib import metadata
26
+ else: # pragma: NO COVER
27
+ # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
28
+ # this code path once we drop support for Python 3.7
29
+ import importlib_metadata as metadata
30
+
31
+ from .services.direct_access_service import (
32
+ DirectAccessServiceAsyncClient,
33
+ DirectAccessServiceClient,
34
+ )
35
+ from .types.adb_service import (
36
+ AdbMessage,
37
+ Close,
38
+ DeviceMessage,
39
+ Fail,
40
+ Okay,
41
+ Open,
42
+ StatusUpdate,
43
+ StreamData,
44
+ StreamStatus,
45
+ )
46
+ from .types.service import (
47
+ AndroidDevice,
48
+ CancelDeviceSessionRequest,
49
+ CreateDeviceSessionRequest,
50
+ DeviceSession,
51
+ GetDeviceSessionRequest,
52
+ ListDeviceSessionsRequest,
53
+ ListDeviceSessionsResponse,
54
+ UpdateDeviceSessionRequest,
55
+ )
56
+
57
+ if hasattr(api_core, "check_python_version") and hasattr(
58
+ api_core, "check_dependency_versions"
59
+ ): # pragma: NO COVER
60
+ api_core.check_python_version("google.cloud.devicestreaming_v1") # type: ignore
61
+ api_core.check_dependency_versions("google.cloud.devicestreaming_v1") # type: ignore
62
+ else: # pragma: NO COVER
63
+ # An older version of api_core is installed which does not define the
64
+ # functions above. We do equivalent checks manually.
65
+ try:
66
+ import sys
67
+ import warnings
68
+
69
+ _py_version_str = sys.version.split()[0]
70
+ _package_label = "google.cloud.devicestreaming_v1"
71
+ if sys.version_info < (3, 9):
72
+ warnings.warn(
73
+ "You are using a non-supported Python version "
74
+ + f"({_py_version_str}). Google will not post any further "
75
+ + f"updates to {_package_label} supporting this Python version. "
76
+ + "Please upgrade to the latest Python version, or at "
77
+ + f"least to Python 3.9, and then update {_package_label}.",
78
+ FutureWarning,
79
+ )
80
+ if sys.version_info[:2] == (3, 9):
81
+ warnings.warn(
82
+ f"You are using a Python version ({_py_version_str}) "
83
+ + f"which Google will stop supporting in {_package_label} in "
84
+ + "January 2026. Please "
85
+ + "upgrade to the latest Python version, or at "
86
+ + "least to Python 3.10, before then, and "
87
+ + f"then update {_package_label}.",
88
+ FutureWarning,
89
+ )
90
+
91
+ def parse_version_to_tuple(version_string: str):
92
+ """Safely converts a semantic version string to a comparable tuple of integers.
93
+ Example: "4.25.8" -> (4, 25, 8)
94
+ Ignores non-numeric parts and handles common version formats.
95
+ Args:
96
+ version_string: Version string in the format "x.y.z" or "x.y.z<suffix>"
97
+ Returns:
98
+ Tuple of integers for the parsed version string.
99
+ """
100
+ parts = []
101
+ for part in version_string.split("."):
102
+ try:
103
+ parts.append(int(part))
104
+ except ValueError:
105
+ # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here.
106
+ # This is a simplification compared to 'packaging.parse_version', but sufficient
107
+ # for comparing strictly numeric semantic versions.
108
+ break
109
+ return tuple(parts)
110
+
111
+ def _get_version(dependency_name):
112
+ try:
113
+ version_string: str = metadata.version(dependency_name)
114
+ parsed_version = parse_version_to_tuple(version_string)
115
+ return (parsed_version, version_string)
116
+ except Exception:
117
+ # Catch exceptions from metadata.version() (e.g., PackageNotFoundError)
118
+ # or errors during parse_version_to_tuple
119
+ return (None, "--")
120
+
121
+ _dependency_package = "google.protobuf"
122
+ _next_supported_version = "4.25.8"
123
+ _next_supported_version_tuple = (4, 25, 8)
124
+ _recommendation = " (we recommend 6.x)"
125
+ (_version_used, _version_used_string) = _get_version(_dependency_package)
126
+ if _version_used and _version_used < _next_supported_version_tuple:
127
+ warnings.warn(
128
+ f"Package {_package_label} depends on "
129
+ + f"{_dependency_package}, currently installed at version "
130
+ + f"{_version_used_string}. Future updates to "
131
+ + f"{_package_label} will require {_dependency_package} at "
132
+ + f"version {_next_supported_version} or higher{_recommendation}."
133
+ + " Please ensure "
134
+ + "that either (a) your Python environment doesn't pin the "
135
+ + f"version of {_dependency_package}, so that updates to "
136
+ + f"{_package_label} can require the higher version, or "
137
+ + "(b) you manually update your Python environment to use at "
138
+ + f"least version {_next_supported_version} of "
139
+ + f"{_dependency_package}.",
140
+ FutureWarning,
141
+ )
142
+ except Exception:
143
+ warnings.warn(
144
+ "Could not determine the version of Python "
145
+ + "currently being used. To continue receiving "
146
+ + "updates for {_package_label}, ensure you are "
147
+ + "using a supported version of Python; see "
148
+ + "https://devguide.python.org/versions/"
149
+ )
150
+
151
+ __all__ = (
152
+ "DirectAccessServiceAsyncClient",
153
+ "AdbMessage",
154
+ "AndroidDevice",
155
+ "CancelDeviceSessionRequest",
156
+ "Close",
157
+ "CreateDeviceSessionRequest",
158
+ "DeviceMessage",
159
+ "DeviceSession",
160
+ "DirectAccessServiceClient",
161
+ "Fail",
162
+ "GetDeviceSessionRequest",
163
+ "ListDeviceSessionsRequest",
164
+ "ListDeviceSessionsResponse",
165
+ "Okay",
166
+ "Open",
167
+ "StatusUpdate",
168
+ "StreamData",
169
+ "StreamStatus",
170
+ "UpdateDeviceSessionRequest",
171
+ )
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "0.2.0" # {x-release-please-version}
16
+ __version__ = "0.3.0" # {x-release-please-version}
@@ -166,6 +166,34 @@ class DirectAccessServiceClient(metaclass=DirectAccessServiceClientMeta):
166
166
  _DEFAULT_ENDPOINT_TEMPLATE = "devicestreaming.{UNIVERSE_DOMAIN}"
167
167
  _DEFAULT_UNIVERSE = "googleapis.com"
168
168
 
169
+ @staticmethod
170
+ def _use_client_cert_effective():
171
+ """Returns whether client certificate should be used for mTLS if the
172
+ google-auth version supports should_use_client_cert automatic mTLS enablement.
173
+
174
+ Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
175
+
176
+ Returns:
177
+ bool: whether client certificate should be used for mTLS
178
+ Raises:
179
+ ValueError: (If using a version of google-auth without should_use_client_cert and
180
+ GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
181
+ """
182
+ # check if google-auth version supports should_use_client_cert for automatic mTLS enablement
183
+ if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER
184
+ return mtls.should_use_client_cert()
185
+ else: # pragma: NO COVER
186
+ # if unsupported, fallback to reading from env var
187
+ use_client_cert_str = os.getenv(
188
+ "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
189
+ ).lower()
190
+ if use_client_cert_str not in ("true", "false"):
191
+ raise ValueError(
192
+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be"
193
+ " either `true` or `false`"
194
+ )
195
+ return use_client_cert_str == "true"
196
+
169
197
  @classmethod
170
198
  def from_service_account_info(cls, info: dict, *args, **kwargs):
171
199
  """Creates an instance of this client using the provided credentials
@@ -350,12 +378,8 @@ class DirectAccessServiceClient(metaclass=DirectAccessServiceClientMeta):
350
378
  )
351
379
  if client_options is None:
352
380
  client_options = client_options_lib.ClientOptions()
353
- use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
381
+ use_client_cert = DirectAccessServiceClient._use_client_cert_effective()
354
382
  use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
355
- if use_client_cert not in ("true", "false"):
356
- raise ValueError(
357
- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
358
- )
359
383
  if use_mtls_endpoint not in ("auto", "never", "always"):
360
384
  raise MutualTLSChannelError(
361
385
  "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
@@ -363,7 +387,7 @@ class DirectAccessServiceClient(metaclass=DirectAccessServiceClientMeta):
363
387
 
364
388
  # Figure out the client cert source to use.
365
389
  client_cert_source = None
366
- if use_client_cert == "true":
390
+ if use_client_cert:
367
391
  if client_options.client_cert_source:
368
392
  client_cert_source = client_options.client_cert_source
369
393
  elif mtls.has_default_client_cert_source():
@@ -395,20 +419,14 @@ class DirectAccessServiceClient(metaclass=DirectAccessServiceClientMeta):
395
419
  google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
396
420
  is not any of ["auto", "never", "always"].
397
421
  """
398
- use_client_cert = os.getenv(
399
- "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
400
- ).lower()
422
+ use_client_cert = DirectAccessServiceClient._use_client_cert_effective()
401
423
  use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
402
424
  universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
403
- if use_client_cert not in ("true", "false"):
404
- raise ValueError(
405
- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
406
- )
407
425
  if use_mtls_endpoint not in ("auto", "never", "always"):
408
426
  raise MutualTLSChannelError(
409
427
  "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
410
428
  )
411
- return use_client_cert == "true", use_mtls_endpoint, universe_domain_env
429
+ return use_client_cert, use_mtls_endpoint, universe_domain_env
412
430
 
413
431
  @staticmethod
414
432
  def _get_client_cert_source(provided_cert_source, use_cert_flag):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-cloud-devicestreaming
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Google Cloud Devicestreaming API client library
5
5
  Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-devicestreaming
6
6
  Author: Google LLC
@@ -165,12 +165,19 @@ def test__read_environment_variables():
165
165
  with mock.patch.dict(
166
166
  os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
167
167
  ):
168
- with pytest.raises(ValueError) as excinfo:
169
- DirectAccessServiceClient._read_environment_variables()
170
- assert (
171
- str(excinfo.value)
172
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
173
- )
168
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
169
+ with pytest.raises(ValueError) as excinfo:
170
+ DirectAccessServiceClient._read_environment_variables()
171
+ assert (
172
+ str(excinfo.value)
173
+ == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
174
+ )
175
+ else:
176
+ assert DirectAccessServiceClient._read_environment_variables() == (
177
+ False,
178
+ "auto",
179
+ None,
180
+ )
174
181
 
175
182
  with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
176
183
  assert DirectAccessServiceClient._read_environment_variables() == (
@@ -209,6 +216,105 @@ def test__read_environment_variables():
209
216
  )
210
217
 
211
218
 
219
+ def test_use_client_cert_effective():
220
+ # Test case 1: Test when `should_use_client_cert` returns True.
221
+ # We mock the `should_use_client_cert` function to simulate a scenario where
222
+ # the google-auth library supports automatic mTLS and determines that a
223
+ # client certificate should be used.
224
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
225
+ with mock.patch(
226
+ "google.auth.transport.mtls.should_use_client_cert", return_value=True
227
+ ):
228
+ assert DirectAccessServiceClient._use_client_cert_effective() is True
229
+
230
+ # Test case 2: Test when `should_use_client_cert` returns False.
231
+ # We mock the `should_use_client_cert` function to simulate a scenario where
232
+ # the google-auth library supports automatic mTLS and determines that a
233
+ # client certificate should NOT be used.
234
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
235
+ with mock.patch(
236
+ "google.auth.transport.mtls.should_use_client_cert", return_value=False
237
+ ):
238
+ assert DirectAccessServiceClient._use_client_cert_effective() is False
239
+
240
+ # Test case 3: Test when `should_use_client_cert` is unavailable and the
241
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true".
242
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
243
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}):
244
+ assert DirectAccessServiceClient._use_client_cert_effective() is True
245
+
246
+ # Test case 4: Test when `should_use_client_cert` is unavailable and the
247
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "false".
248
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
249
+ with mock.patch.dict(
250
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}
251
+ ):
252
+ assert DirectAccessServiceClient._use_client_cert_effective() is False
253
+
254
+ # Test case 5: Test when `should_use_client_cert` is unavailable and the
255
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "True".
256
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
257
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "True"}):
258
+ assert DirectAccessServiceClient._use_client_cert_effective() is True
259
+
260
+ # Test case 6: Test when `should_use_client_cert` is unavailable and the
261
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "False".
262
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
263
+ with mock.patch.dict(
264
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "False"}
265
+ ):
266
+ assert DirectAccessServiceClient._use_client_cert_effective() is False
267
+
268
+ # Test case 7: Test when `should_use_client_cert` is unavailable and the
269
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "TRUE".
270
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
271
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "TRUE"}):
272
+ assert DirectAccessServiceClient._use_client_cert_effective() is True
273
+
274
+ # Test case 8: Test when `should_use_client_cert` is unavailable and the
275
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "FALSE".
276
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
277
+ with mock.patch.dict(
278
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "FALSE"}
279
+ ):
280
+ assert DirectAccessServiceClient._use_client_cert_effective() is False
281
+
282
+ # Test case 9: Test when `should_use_client_cert` is unavailable and the
283
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not set.
284
+ # In this case, the method should return False, which is the default value.
285
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
286
+ with mock.patch.dict(os.environ, clear=True):
287
+ assert DirectAccessServiceClient._use_client_cert_effective() is False
288
+
289
+ # Test case 10: Test when `should_use_client_cert` is unavailable and the
290
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
291
+ # The method should raise a ValueError as the environment variable must be either
292
+ # "true" or "false".
293
+ if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
294
+ with mock.patch.dict(
295
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"}
296
+ ):
297
+ with pytest.raises(ValueError):
298
+ DirectAccessServiceClient._use_client_cert_effective()
299
+
300
+ # Test case 11: Test when `should_use_client_cert` is available and the
301
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
302
+ # The method should return False as the environment variable is set to an invalid value.
303
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
304
+ with mock.patch.dict(
305
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"}
306
+ ):
307
+ assert DirectAccessServiceClient._use_client_cert_effective() is False
308
+
309
+ # Test case 12: Test when `should_use_client_cert` is available and the
310
+ # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is unset. Also,
311
+ # the GOOGLE_API_CONFIG environment variable is unset.
312
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
313
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": ""}):
314
+ with mock.patch.dict(os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": ""}):
315
+ assert DirectAccessServiceClient._use_client_cert_effective() is False
316
+
317
+
212
318
  def test__get_client_cert_source():
213
319
  mock_provided_cert_source = mock.Mock()
214
320
  mock_default_cert_source = mock.Mock()
@@ -596,17 +702,6 @@ def test_direct_access_service_client_client_options(
596
702
  == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
597
703
  )
598
704
 
599
- # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
600
- with mock.patch.dict(
601
- os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
602
- ):
603
- with pytest.raises(ValueError) as excinfo:
604
- client = client_class(transport=transport_name)
605
- assert (
606
- str(excinfo.value)
607
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
608
- )
609
-
610
705
  # Check the case quota_project_id is provided
611
706
  options = client_options.ClientOptions(quota_project_id="octopus")
612
707
  with mock.patch.object(transport_class, "__init__") as patched:
@@ -842,6 +937,119 @@ def test_direct_access_service_client_get_mtls_endpoint_and_cert_source(client_c
842
937
  assert api_endpoint == mock_api_endpoint
843
938
  assert cert_source is None
844
939
 
940
+ # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "Unsupported".
941
+ with mock.patch.dict(
942
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
943
+ ):
944
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
945
+ mock_client_cert_source = mock.Mock()
946
+ mock_api_endpoint = "foo"
947
+ options = client_options.ClientOptions(
948
+ client_cert_source=mock_client_cert_source,
949
+ api_endpoint=mock_api_endpoint,
950
+ )
951
+ api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source(
952
+ options
953
+ )
954
+ assert api_endpoint == mock_api_endpoint
955
+ assert cert_source is None
956
+
957
+ # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset.
958
+ test_cases = [
959
+ (
960
+ # With workloads present in config, mTLS is enabled.
961
+ {
962
+ "version": 1,
963
+ "cert_configs": {
964
+ "workload": {
965
+ "cert_path": "path/to/cert/file",
966
+ "key_path": "path/to/key/file",
967
+ }
968
+ },
969
+ },
970
+ mock_client_cert_source,
971
+ ),
972
+ (
973
+ # With workloads not present in config, mTLS is disabled.
974
+ {
975
+ "version": 1,
976
+ "cert_configs": {},
977
+ },
978
+ None,
979
+ ),
980
+ ]
981
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
982
+ for config_data, expected_cert_source in test_cases:
983
+ env = os.environ.copy()
984
+ env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", None)
985
+ with mock.patch.dict(os.environ, env, clear=True):
986
+ config_filename = "mock_certificate_config.json"
987
+ config_file_content = json.dumps(config_data)
988
+ m = mock.mock_open(read_data=config_file_content)
989
+ with mock.patch("builtins.open", m):
990
+ with mock.patch.dict(
991
+ os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename}
992
+ ):
993
+ mock_api_endpoint = "foo"
994
+ options = client_options.ClientOptions(
995
+ client_cert_source=mock_client_cert_source,
996
+ api_endpoint=mock_api_endpoint,
997
+ )
998
+ (
999
+ api_endpoint,
1000
+ cert_source,
1001
+ ) = client_class.get_mtls_endpoint_and_cert_source(options)
1002
+ assert api_endpoint == mock_api_endpoint
1003
+ assert cert_source is expected_cert_source
1004
+
1005
+ # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset(empty).
1006
+ test_cases = [
1007
+ (
1008
+ # With workloads present in config, mTLS is enabled.
1009
+ {
1010
+ "version": 1,
1011
+ "cert_configs": {
1012
+ "workload": {
1013
+ "cert_path": "path/to/cert/file",
1014
+ "key_path": "path/to/key/file",
1015
+ }
1016
+ },
1017
+ },
1018
+ mock_client_cert_source,
1019
+ ),
1020
+ (
1021
+ # With workloads not present in config, mTLS is disabled.
1022
+ {
1023
+ "version": 1,
1024
+ "cert_configs": {},
1025
+ },
1026
+ None,
1027
+ ),
1028
+ ]
1029
+ if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
1030
+ for config_data, expected_cert_source in test_cases:
1031
+ env = os.environ.copy()
1032
+ env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", "")
1033
+ with mock.patch.dict(os.environ, env, clear=True):
1034
+ config_filename = "mock_certificate_config.json"
1035
+ config_file_content = json.dumps(config_data)
1036
+ m = mock.mock_open(read_data=config_file_content)
1037
+ with mock.patch("builtins.open", m):
1038
+ with mock.patch.dict(
1039
+ os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename}
1040
+ ):
1041
+ mock_api_endpoint = "foo"
1042
+ options = client_options.ClientOptions(
1043
+ client_cert_source=mock_client_cert_source,
1044
+ api_endpoint=mock_api_endpoint,
1045
+ )
1046
+ (
1047
+ api_endpoint,
1048
+ cert_source,
1049
+ ) = client_class.get_mtls_endpoint_and_cert_source(options)
1050
+ assert api_endpoint == mock_api_endpoint
1051
+ assert cert_source is expected_cert_source
1052
+
845
1053
  # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never".
846
1054
  with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
847
1055
  api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source()
@@ -892,18 +1100,6 @@ def test_direct_access_service_client_get_mtls_endpoint_and_cert_source(client_c
892
1100
  == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
893
1101
  )
894
1102
 
895
- # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
896
- with mock.patch.dict(
897
- os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
898
- ):
899
- with pytest.raises(ValueError) as excinfo:
900
- client_class.get_mtls_endpoint_and_cert_source()
901
-
902
- assert (
903
- str(excinfo.value)
904
- == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
905
- )
906
-
907
1103
 
908
1104
  @pytest.mark.parametrize(
909
1105
  "client_class", [DirectAccessServiceClient, DirectAccessServiceAsyncClient]
@@ -5844,6 +6040,7 @@ def test_direct_access_service_grpc_asyncio_transport_channel():
5844
6040
 
5845
6041
  # Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are
5846
6042
  # removed from grpc/grpc_asyncio transport constructor.
6043
+ @pytest.mark.filterwarnings("ignore::FutureWarning")
5847
6044
  @pytest.mark.parametrize(
5848
6045
  "transport_class",
5849
6046
  [
@@ -1,67 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # Copyright 2025 Google LLC
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- from google.cloud.devicestreaming_v1 import gapic_version as package_version
17
-
18
- __version__ = package_version.__version__
19
-
20
-
21
- from .services.direct_access_service import (
22
- DirectAccessServiceAsyncClient,
23
- DirectAccessServiceClient,
24
- )
25
- from .types.adb_service import (
26
- AdbMessage,
27
- Close,
28
- DeviceMessage,
29
- Fail,
30
- Okay,
31
- Open,
32
- StatusUpdate,
33
- StreamData,
34
- StreamStatus,
35
- )
36
- from .types.service import (
37
- AndroidDevice,
38
- CancelDeviceSessionRequest,
39
- CreateDeviceSessionRequest,
40
- DeviceSession,
41
- GetDeviceSessionRequest,
42
- ListDeviceSessionsRequest,
43
- ListDeviceSessionsResponse,
44
- UpdateDeviceSessionRequest,
45
- )
46
-
47
- __all__ = (
48
- "DirectAccessServiceAsyncClient",
49
- "AdbMessage",
50
- "AndroidDevice",
51
- "CancelDeviceSessionRequest",
52
- "Close",
53
- "CreateDeviceSessionRequest",
54
- "DeviceMessage",
55
- "DeviceSession",
56
- "DirectAccessServiceClient",
57
- "Fail",
58
- "GetDeviceSessionRequest",
59
- "ListDeviceSessionsRequest",
60
- "ListDeviceSessionsResponse",
61
- "Okay",
62
- "Open",
63
- "StatusUpdate",
64
- "StreamData",
65
- "StreamStatus",
66
- "UpdateDeviceSessionRequest",
67
- )