google-maps-routeoptimization 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.
- {google_maps_routeoptimization-0.2.0/google_maps_routeoptimization.egg-info → google_maps_routeoptimization-0.3.0}/PKG-INFO +1 -1
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization/gapic_version.py +1 -1
- google_maps_routeoptimization-0.3.0/google/maps/routeoptimization_v1/__init__.py +201 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/gapic_version.py +1 -1
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/client.py +32 -14
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0/google_maps_routeoptimization.egg-info}/PKG-INFO +1 -1
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/tests/unit/gapic/routeoptimization_v1/test_route_optimization.py +226 -29
- google_maps_routeoptimization-0.2.0/google/maps/routeoptimization_v1/__init__.py +0 -97
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/LICENSE +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/MANIFEST.in +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/README.rst +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization/__init__.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization/py.typed +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/gapic_metadata.json +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/py.typed +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/__init__.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/__init__.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/async_client.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/transports/__init__.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/transports/base.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/transports/grpc.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/transports/grpc_asyncio.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/transports/rest.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/services/route_optimization/transports/rest_base.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/types/__init__.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google/maps/routeoptimization_v1/types/route_optimization_service.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google_maps_routeoptimization.egg-info/SOURCES.txt +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google_maps_routeoptimization.egg-info/dependency_links.txt +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google_maps_routeoptimization.egg-info/not-zip-safe +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google_maps_routeoptimization.egg-info/requires.txt +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/google_maps_routeoptimization.egg-info/top_level.txt +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/setup.cfg +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/setup.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/tests/__init__.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/tests/unit/__init__.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/tests/unit/gapic/__init__.py +0 -0
- {google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/tests/unit/gapic/routeoptimization_v1/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: google-maps-routeoptimization
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Google Maps Routeoptimization API client library
|
|
5
5
|
Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-maps-routeoptimization
|
|
6
6
|
Author: Google LLC
|
|
@@ -0,0 +1,201 @@
|
|
|
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.maps.routeoptimization_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.route_optimization import (
|
|
32
|
+
RouteOptimizationAsyncClient,
|
|
33
|
+
RouteOptimizationClient,
|
|
34
|
+
)
|
|
35
|
+
from .types.route_optimization_service import (
|
|
36
|
+
AggregatedMetrics,
|
|
37
|
+
BatchOptimizeToursMetadata,
|
|
38
|
+
BatchOptimizeToursRequest,
|
|
39
|
+
BatchOptimizeToursResponse,
|
|
40
|
+
BreakRule,
|
|
41
|
+
DataFormat,
|
|
42
|
+
DistanceLimit,
|
|
43
|
+
GcsDestination,
|
|
44
|
+
GcsSource,
|
|
45
|
+
InjectedSolutionConstraint,
|
|
46
|
+
InputConfig,
|
|
47
|
+
Location,
|
|
48
|
+
OptimizeToursLongRunningMetadata,
|
|
49
|
+
OptimizeToursRequest,
|
|
50
|
+
OptimizeToursResponse,
|
|
51
|
+
OptimizeToursUriMetadata,
|
|
52
|
+
OptimizeToursUriRequest,
|
|
53
|
+
OptimizeToursUriResponse,
|
|
54
|
+
OptimizeToursValidationError,
|
|
55
|
+
OutputConfig,
|
|
56
|
+
RouteModifiers,
|
|
57
|
+
Shipment,
|
|
58
|
+
ShipmentModel,
|
|
59
|
+
ShipmentRoute,
|
|
60
|
+
ShipmentTypeIncompatibility,
|
|
61
|
+
ShipmentTypeRequirement,
|
|
62
|
+
SkippedShipment,
|
|
63
|
+
TimeWindow,
|
|
64
|
+
TransitionAttributes,
|
|
65
|
+
Uri,
|
|
66
|
+
Vehicle,
|
|
67
|
+
VehicleFullness,
|
|
68
|
+
Waypoint,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
if hasattr(api_core, "check_python_version") and hasattr(
|
|
72
|
+
api_core, "check_dependency_versions"
|
|
73
|
+
): # pragma: NO COVER
|
|
74
|
+
api_core.check_python_version("google.maps.routeoptimization_v1") # type: ignore
|
|
75
|
+
api_core.check_dependency_versions("google.maps.routeoptimization_v1") # type: ignore
|
|
76
|
+
else: # pragma: NO COVER
|
|
77
|
+
# An older version of api_core is installed which does not define the
|
|
78
|
+
# functions above. We do equivalent checks manually.
|
|
79
|
+
try:
|
|
80
|
+
import sys
|
|
81
|
+
import warnings
|
|
82
|
+
|
|
83
|
+
_py_version_str = sys.version.split()[0]
|
|
84
|
+
_package_label = "google.maps.routeoptimization_v1"
|
|
85
|
+
if sys.version_info < (3, 9):
|
|
86
|
+
warnings.warn(
|
|
87
|
+
"You are using a non-supported Python version "
|
|
88
|
+
+ f"({_py_version_str}). Google will not post any further "
|
|
89
|
+
+ f"updates to {_package_label} supporting this Python version. "
|
|
90
|
+
+ "Please upgrade to the latest Python version, or at "
|
|
91
|
+
+ f"least to Python 3.9, and then update {_package_label}.",
|
|
92
|
+
FutureWarning,
|
|
93
|
+
)
|
|
94
|
+
if sys.version_info[:2] == (3, 9):
|
|
95
|
+
warnings.warn(
|
|
96
|
+
f"You are using a Python version ({_py_version_str}) "
|
|
97
|
+
+ f"which Google will stop supporting in {_package_label} in "
|
|
98
|
+
+ "January 2026. Please "
|
|
99
|
+
+ "upgrade to the latest Python version, or at "
|
|
100
|
+
+ "least to Python 3.10, before then, and "
|
|
101
|
+
+ f"then update {_package_label}.",
|
|
102
|
+
FutureWarning,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
def parse_version_to_tuple(version_string: str):
|
|
106
|
+
"""Safely converts a semantic version string to a comparable tuple of integers.
|
|
107
|
+
Example: "4.25.8" -> (4, 25, 8)
|
|
108
|
+
Ignores non-numeric parts and handles common version formats.
|
|
109
|
+
Args:
|
|
110
|
+
version_string: Version string in the format "x.y.z" or "x.y.z<suffix>"
|
|
111
|
+
Returns:
|
|
112
|
+
Tuple of integers for the parsed version string.
|
|
113
|
+
"""
|
|
114
|
+
parts = []
|
|
115
|
+
for part in version_string.split("."):
|
|
116
|
+
try:
|
|
117
|
+
parts.append(int(part))
|
|
118
|
+
except ValueError:
|
|
119
|
+
# If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here.
|
|
120
|
+
# This is a simplification compared to 'packaging.parse_version', but sufficient
|
|
121
|
+
# for comparing strictly numeric semantic versions.
|
|
122
|
+
break
|
|
123
|
+
return tuple(parts)
|
|
124
|
+
|
|
125
|
+
def _get_version(dependency_name):
|
|
126
|
+
try:
|
|
127
|
+
version_string: str = metadata.version(dependency_name)
|
|
128
|
+
parsed_version = parse_version_to_tuple(version_string)
|
|
129
|
+
return (parsed_version, version_string)
|
|
130
|
+
except Exception:
|
|
131
|
+
# Catch exceptions from metadata.version() (e.g., PackageNotFoundError)
|
|
132
|
+
# or errors during parse_version_to_tuple
|
|
133
|
+
return (None, "--")
|
|
134
|
+
|
|
135
|
+
_dependency_package = "google.protobuf"
|
|
136
|
+
_next_supported_version = "4.25.8"
|
|
137
|
+
_next_supported_version_tuple = (4, 25, 8)
|
|
138
|
+
_recommendation = " (we recommend 6.x)"
|
|
139
|
+
(_version_used, _version_used_string) = _get_version(_dependency_package)
|
|
140
|
+
if _version_used and _version_used < _next_supported_version_tuple:
|
|
141
|
+
warnings.warn(
|
|
142
|
+
f"Package {_package_label} depends on "
|
|
143
|
+
+ f"{_dependency_package}, currently installed at version "
|
|
144
|
+
+ f"{_version_used_string}. Future updates to "
|
|
145
|
+
+ f"{_package_label} will require {_dependency_package} at "
|
|
146
|
+
+ f"version {_next_supported_version} or higher{_recommendation}."
|
|
147
|
+
+ " Please ensure "
|
|
148
|
+
+ "that either (a) your Python environment doesn't pin the "
|
|
149
|
+
+ f"version of {_dependency_package}, so that updates to "
|
|
150
|
+
+ f"{_package_label} can require the higher version, or "
|
|
151
|
+
+ "(b) you manually update your Python environment to use at "
|
|
152
|
+
+ f"least version {_next_supported_version} of "
|
|
153
|
+
+ f"{_dependency_package}.",
|
|
154
|
+
FutureWarning,
|
|
155
|
+
)
|
|
156
|
+
except Exception:
|
|
157
|
+
warnings.warn(
|
|
158
|
+
"Could not determine the version of Python "
|
|
159
|
+
+ "currently being used. To continue receiving "
|
|
160
|
+
+ "updates for {_package_label}, ensure you are "
|
|
161
|
+
+ "using a supported version of Python; see "
|
|
162
|
+
+ "https://devguide.python.org/versions/"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
__all__ = (
|
|
166
|
+
"RouteOptimizationAsyncClient",
|
|
167
|
+
"AggregatedMetrics",
|
|
168
|
+
"BatchOptimizeToursMetadata",
|
|
169
|
+
"BatchOptimizeToursRequest",
|
|
170
|
+
"BatchOptimizeToursResponse",
|
|
171
|
+
"BreakRule",
|
|
172
|
+
"DataFormat",
|
|
173
|
+
"DistanceLimit",
|
|
174
|
+
"GcsDestination",
|
|
175
|
+
"GcsSource",
|
|
176
|
+
"InjectedSolutionConstraint",
|
|
177
|
+
"InputConfig",
|
|
178
|
+
"Location",
|
|
179
|
+
"OptimizeToursLongRunningMetadata",
|
|
180
|
+
"OptimizeToursRequest",
|
|
181
|
+
"OptimizeToursResponse",
|
|
182
|
+
"OptimizeToursUriMetadata",
|
|
183
|
+
"OptimizeToursUriRequest",
|
|
184
|
+
"OptimizeToursUriResponse",
|
|
185
|
+
"OptimizeToursValidationError",
|
|
186
|
+
"OutputConfig",
|
|
187
|
+
"RouteModifiers",
|
|
188
|
+
"RouteOptimizationClient",
|
|
189
|
+
"Shipment",
|
|
190
|
+
"ShipmentModel",
|
|
191
|
+
"ShipmentRoute",
|
|
192
|
+
"ShipmentTypeIncompatibility",
|
|
193
|
+
"ShipmentTypeRequirement",
|
|
194
|
+
"SkippedShipment",
|
|
195
|
+
"TimeWindow",
|
|
196
|
+
"TransitionAttributes",
|
|
197
|
+
"Uri",
|
|
198
|
+
"Vehicle",
|
|
199
|
+
"VehicleFullness",
|
|
200
|
+
"Waypoint",
|
|
201
|
+
)
|
|
@@ -174,6 +174,34 @@ class RouteOptimizationClient(metaclass=RouteOptimizationClientMeta):
|
|
|
174
174
|
_DEFAULT_ENDPOINT_TEMPLATE = "routeoptimization.{UNIVERSE_DOMAIN}"
|
|
175
175
|
_DEFAULT_UNIVERSE = "googleapis.com"
|
|
176
176
|
|
|
177
|
+
@staticmethod
|
|
178
|
+
def _use_client_cert_effective():
|
|
179
|
+
"""Returns whether client certificate should be used for mTLS if the
|
|
180
|
+
google-auth version supports should_use_client_cert automatic mTLS enablement.
|
|
181
|
+
|
|
182
|
+
Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
bool: whether client certificate should be used for mTLS
|
|
186
|
+
Raises:
|
|
187
|
+
ValueError: (If using a version of google-auth without should_use_client_cert and
|
|
188
|
+
GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
|
|
189
|
+
"""
|
|
190
|
+
# check if google-auth version supports should_use_client_cert for automatic mTLS enablement
|
|
191
|
+
if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER
|
|
192
|
+
return mtls.should_use_client_cert()
|
|
193
|
+
else: # pragma: NO COVER
|
|
194
|
+
# if unsupported, fallback to reading from env var
|
|
195
|
+
use_client_cert_str = os.getenv(
|
|
196
|
+
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
|
|
197
|
+
).lower()
|
|
198
|
+
if use_client_cert_str not in ("true", "false"):
|
|
199
|
+
raise ValueError(
|
|
200
|
+
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be"
|
|
201
|
+
" either `true` or `false`"
|
|
202
|
+
)
|
|
203
|
+
return use_client_cert_str == "true"
|
|
204
|
+
|
|
177
205
|
@classmethod
|
|
178
206
|
def from_service_account_info(cls, info: dict, *args, **kwargs):
|
|
179
207
|
"""Creates an instance of this client using the provided credentials
|
|
@@ -339,12 +367,8 @@ class RouteOptimizationClient(metaclass=RouteOptimizationClientMeta):
|
|
|
339
367
|
)
|
|
340
368
|
if client_options is None:
|
|
341
369
|
client_options = client_options_lib.ClientOptions()
|
|
342
|
-
use_client_cert =
|
|
370
|
+
use_client_cert = RouteOptimizationClient._use_client_cert_effective()
|
|
343
371
|
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
|
|
344
|
-
if use_client_cert not in ("true", "false"):
|
|
345
|
-
raise ValueError(
|
|
346
|
-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
|
|
347
|
-
)
|
|
348
372
|
if use_mtls_endpoint not in ("auto", "never", "always"):
|
|
349
373
|
raise MutualTLSChannelError(
|
|
350
374
|
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
|
|
@@ -352,7 +376,7 @@ class RouteOptimizationClient(metaclass=RouteOptimizationClientMeta):
|
|
|
352
376
|
|
|
353
377
|
# Figure out the client cert source to use.
|
|
354
378
|
client_cert_source = None
|
|
355
|
-
if use_client_cert
|
|
379
|
+
if use_client_cert:
|
|
356
380
|
if client_options.client_cert_source:
|
|
357
381
|
client_cert_source = client_options.client_cert_source
|
|
358
382
|
elif mtls.has_default_client_cert_source():
|
|
@@ -384,20 +408,14 @@ class RouteOptimizationClient(metaclass=RouteOptimizationClientMeta):
|
|
|
384
408
|
google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
|
|
385
409
|
is not any of ["auto", "never", "always"].
|
|
386
410
|
"""
|
|
387
|
-
use_client_cert =
|
|
388
|
-
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
|
|
389
|
-
).lower()
|
|
411
|
+
use_client_cert = RouteOptimizationClient._use_client_cert_effective()
|
|
390
412
|
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
|
|
391
413
|
universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
|
|
392
|
-
if use_client_cert not in ("true", "false"):
|
|
393
|
-
raise ValueError(
|
|
394
|
-
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
|
|
395
|
-
)
|
|
396
414
|
if use_mtls_endpoint not in ("auto", "never", "always"):
|
|
397
415
|
raise MutualTLSChannelError(
|
|
398
416
|
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
|
|
399
417
|
)
|
|
400
|
-
return use_client_cert
|
|
418
|
+
return use_client_cert, use_mtls_endpoint, universe_domain_env
|
|
401
419
|
|
|
402
420
|
@staticmethod
|
|
403
421
|
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-maps-routeoptimization
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Google Maps Routeoptimization API client library
|
|
5
5
|
Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-maps-routeoptimization
|
|
6
6
|
Author: Google LLC
|
|
@@ -174,12 +174,19 @@ def test__read_environment_variables():
|
|
|
174
174
|
with mock.patch.dict(
|
|
175
175
|
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
|
|
176
176
|
):
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
178
|
+
with pytest.raises(ValueError) as excinfo:
|
|
179
|
+
RouteOptimizationClient._read_environment_variables()
|
|
180
|
+
assert (
|
|
181
|
+
str(excinfo.value)
|
|
182
|
+
== "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
|
|
183
|
+
)
|
|
184
|
+
else:
|
|
185
|
+
assert RouteOptimizationClient._read_environment_variables() == (
|
|
186
|
+
False,
|
|
187
|
+
"auto",
|
|
188
|
+
None,
|
|
189
|
+
)
|
|
183
190
|
|
|
184
191
|
with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
|
|
185
192
|
assert RouteOptimizationClient._read_environment_variables() == (
|
|
@@ -218,6 +225,105 @@ def test__read_environment_variables():
|
|
|
218
225
|
)
|
|
219
226
|
|
|
220
227
|
|
|
228
|
+
def test_use_client_cert_effective():
|
|
229
|
+
# Test case 1: Test when `should_use_client_cert` returns True.
|
|
230
|
+
# We mock the `should_use_client_cert` function to simulate a scenario where
|
|
231
|
+
# the google-auth library supports automatic mTLS and determines that a
|
|
232
|
+
# client certificate should be used.
|
|
233
|
+
if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
234
|
+
with mock.patch(
|
|
235
|
+
"google.auth.transport.mtls.should_use_client_cert", return_value=True
|
|
236
|
+
):
|
|
237
|
+
assert RouteOptimizationClient._use_client_cert_effective() is True
|
|
238
|
+
|
|
239
|
+
# Test case 2: Test when `should_use_client_cert` returns False.
|
|
240
|
+
# We mock the `should_use_client_cert` function to simulate a scenario where
|
|
241
|
+
# the google-auth library supports automatic mTLS and determines that a
|
|
242
|
+
# client certificate should NOT be used.
|
|
243
|
+
if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
244
|
+
with mock.patch(
|
|
245
|
+
"google.auth.transport.mtls.should_use_client_cert", return_value=False
|
|
246
|
+
):
|
|
247
|
+
assert RouteOptimizationClient._use_client_cert_effective() is False
|
|
248
|
+
|
|
249
|
+
# Test case 3: Test when `should_use_client_cert` is unavailable and the
|
|
250
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true".
|
|
251
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
252
|
+
with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}):
|
|
253
|
+
assert RouteOptimizationClient._use_client_cert_effective() is True
|
|
254
|
+
|
|
255
|
+
# Test case 4: Test when `should_use_client_cert` is unavailable and the
|
|
256
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "false".
|
|
257
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
258
|
+
with mock.patch.dict(
|
|
259
|
+
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}
|
|
260
|
+
):
|
|
261
|
+
assert RouteOptimizationClient._use_client_cert_effective() is False
|
|
262
|
+
|
|
263
|
+
# Test case 5: Test when `should_use_client_cert` is unavailable and the
|
|
264
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "True".
|
|
265
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
266
|
+
with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "True"}):
|
|
267
|
+
assert RouteOptimizationClient._use_client_cert_effective() is True
|
|
268
|
+
|
|
269
|
+
# Test case 6: Test when `should_use_client_cert` is unavailable and the
|
|
270
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "False".
|
|
271
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
272
|
+
with mock.patch.dict(
|
|
273
|
+
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "False"}
|
|
274
|
+
):
|
|
275
|
+
assert RouteOptimizationClient._use_client_cert_effective() is False
|
|
276
|
+
|
|
277
|
+
# Test case 7: Test when `should_use_client_cert` is unavailable and the
|
|
278
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "TRUE".
|
|
279
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
280
|
+
with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "TRUE"}):
|
|
281
|
+
assert RouteOptimizationClient._use_client_cert_effective() is True
|
|
282
|
+
|
|
283
|
+
# Test case 8: Test when `should_use_client_cert` is unavailable and the
|
|
284
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "FALSE".
|
|
285
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
286
|
+
with mock.patch.dict(
|
|
287
|
+
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "FALSE"}
|
|
288
|
+
):
|
|
289
|
+
assert RouteOptimizationClient._use_client_cert_effective() is False
|
|
290
|
+
|
|
291
|
+
# Test case 9: Test when `should_use_client_cert` is unavailable and the
|
|
292
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not set.
|
|
293
|
+
# In this case, the method should return False, which is the default value.
|
|
294
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
295
|
+
with mock.patch.dict(os.environ, clear=True):
|
|
296
|
+
assert RouteOptimizationClient._use_client_cert_effective() is False
|
|
297
|
+
|
|
298
|
+
# Test case 10: Test when `should_use_client_cert` is unavailable and the
|
|
299
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
|
|
300
|
+
# The method should raise a ValueError as the environment variable must be either
|
|
301
|
+
# "true" or "false".
|
|
302
|
+
if not hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
303
|
+
with mock.patch.dict(
|
|
304
|
+
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"}
|
|
305
|
+
):
|
|
306
|
+
with pytest.raises(ValueError):
|
|
307
|
+
RouteOptimizationClient._use_client_cert_effective()
|
|
308
|
+
|
|
309
|
+
# Test case 11: Test when `should_use_client_cert` is available and the
|
|
310
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value.
|
|
311
|
+
# The method should return False as the environment variable is set to an invalid value.
|
|
312
|
+
if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
313
|
+
with mock.patch.dict(
|
|
314
|
+
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"}
|
|
315
|
+
):
|
|
316
|
+
assert RouteOptimizationClient._use_client_cert_effective() is False
|
|
317
|
+
|
|
318
|
+
# Test case 12: Test when `should_use_client_cert` is available and the
|
|
319
|
+
# `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is unset. Also,
|
|
320
|
+
# the GOOGLE_API_CONFIG environment variable is unset.
|
|
321
|
+
if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
322
|
+
with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": ""}):
|
|
323
|
+
with mock.patch.dict(os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": ""}):
|
|
324
|
+
assert RouteOptimizationClient._use_client_cert_effective() is False
|
|
325
|
+
|
|
326
|
+
|
|
221
327
|
def test__get_client_cert_source():
|
|
222
328
|
mock_provided_cert_source = mock.Mock()
|
|
223
329
|
mock_default_cert_source = mock.Mock()
|
|
@@ -591,17 +697,6 @@ def test_route_optimization_client_client_options(
|
|
|
591
697
|
== "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
|
|
592
698
|
)
|
|
593
699
|
|
|
594
|
-
# Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
|
|
595
|
-
with mock.patch.dict(
|
|
596
|
-
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
|
|
597
|
-
):
|
|
598
|
-
with pytest.raises(ValueError) as excinfo:
|
|
599
|
-
client = client_class(transport=transport_name)
|
|
600
|
-
assert (
|
|
601
|
-
str(excinfo.value)
|
|
602
|
-
== "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
|
|
603
|
-
)
|
|
604
|
-
|
|
605
700
|
# Check the case quota_project_id is provided
|
|
606
701
|
options = client_options.ClientOptions(quota_project_id="octopus")
|
|
607
702
|
with mock.patch.object(transport_class, "__init__") as patched:
|
|
@@ -837,6 +932,119 @@ def test_route_optimization_client_get_mtls_endpoint_and_cert_source(client_clas
|
|
|
837
932
|
assert api_endpoint == mock_api_endpoint
|
|
838
933
|
assert cert_source is None
|
|
839
934
|
|
|
935
|
+
# Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "Unsupported".
|
|
936
|
+
with mock.patch.dict(
|
|
937
|
+
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
|
|
938
|
+
):
|
|
939
|
+
if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
940
|
+
mock_client_cert_source = mock.Mock()
|
|
941
|
+
mock_api_endpoint = "foo"
|
|
942
|
+
options = client_options.ClientOptions(
|
|
943
|
+
client_cert_source=mock_client_cert_source,
|
|
944
|
+
api_endpoint=mock_api_endpoint,
|
|
945
|
+
)
|
|
946
|
+
api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source(
|
|
947
|
+
options
|
|
948
|
+
)
|
|
949
|
+
assert api_endpoint == mock_api_endpoint
|
|
950
|
+
assert cert_source is None
|
|
951
|
+
|
|
952
|
+
# Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset.
|
|
953
|
+
test_cases = [
|
|
954
|
+
(
|
|
955
|
+
# With workloads present in config, mTLS is enabled.
|
|
956
|
+
{
|
|
957
|
+
"version": 1,
|
|
958
|
+
"cert_configs": {
|
|
959
|
+
"workload": {
|
|
960
|
+
"cert_path": "path/to/cert/file",
|
|
961
|
+
"key_path": "path/to/key/file",
|
|
962
|
+
}
|
|
963
|
+
},
|
|
964
|
+
},
|
|
965
|
+
mock_client_cert_source,
|
|
966
|
+
),
|
|
967
|
+
(
|
|
968
|
+
# With workloads not present in config, mTLS is disabled.
|
|
969
|
+
{
|
|
970
|
+
"version": 1,
|
|
971
|
+
"cert_configs": {},
|
|
972
|
+
},
|
|
973
|
+
None,
|
|
974
|
+
),
|
|
975
|
+
]
|
|
976
|
+
if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
977
|
+
for config_data, expected_cert_source in test_cases:
|
|
978
|
+
env = os.environ.copy()
|
|
979
|
+
env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", None)
|
|
980
|
+
with mock.patch.dict(os.environ, env, clear=True):
|
|
981
|
+
config_filename = "mock_certificate_config.json"
|
|
982
|
+
config_file_content = json.dumps(config_data)
|
|
983
|
+
m = mock.mock_open(read_data=config_file_content)
|
|
984
|
+
with mock.patch("builtins.open", m):
|
|
985
|
+
with mock.patch.dict(
|
|
986
|
+
os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename}
|
|
987
|
+
):
|
|
988
|
+
mock_api_endpoint = "foo"
|
|
989
|
+
options = client_options.ClientOptions(
|
|
990
|
+
client_cert_source=mock_client_cert_source,
|
|
991
|
+
api_endpoint=mock_api_endpoint,
|
|
992
|
+
)
|
|
993
|
+
(
|
|
994
|
+
api_endpoint,
|
|
995
|
+
cert_source,
|
|
996
|
+
) = client_class.get_mtls_endpoint_and_cert_source(options)
|
|
997
|
+
assert api_endpoint == mock_api_endpoint
|
|
998
|
+
assert cert_source is expected_cert_source
|
|
999
|
+
|
|
1000
|
+
# Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset(empty).
|
|
1001
|
+
test_cases = [
|
|
1002
|
+
(
|
|
1003
|
+
# With workloads present in config, mTLS is enabled.
|
|
1004
|
+
{
|
|
1005
|
+
"version": 1,
|
|
1006
|
+
"cert_configs": {
|
|
1007
|
+
"workload": {
|
|
1008
|
+
"cert_path": "path/to/cert/file",
|
|
1009
|
+
"key_path": "path/to/key/file",
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
1012
|
+
},
|
|
1013
|
+
mock_client_cert_source,
|
|
1014
|
+
),
|
|
1015
|
+
(
|
|
1016
|
+
# With workloads not present in config, mTLS is disabled.
|
|
1017
|
+
{
|
|
1018
|
+
"version": 1,
|
|
1019
|
+
"cert_configs": {},
|
|
1020
|
+
},
|
|
1021
|
+
None,
|
|
1022
|
+
),
|
|
1023
|
+
]
|
|
1024
|
+
if hasattr(google.auth.transport.mtls, "should_use_client_cert"):
|
|
1025
|
+
for config_data, expected_cert_source in test_cases:
|
|
1026
|
+
env = os.environ.copy()
|
|
1027
|
+
env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", "")
|
|
1028
|
+
with mock.patch.dict(os.environ, env, clear=True):
|
|
1029
|
+
config_filename = "mock_certificate_config.json"
|
|
1030
|
+
config_file_content = json.dumps(config_data)
|
|
1031
|
+
m = mock.mock_open(read_data=config_file_content)
|
|
1032
|
+
with mock.patch("builtins.open", m):
|
|
1033
|
+
with mock.patch.dict(
|
|
1034
|
+
os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename}
|
|
1035
|
+
):
|
|
1036
|
+
mock_api_endpoint = "foo"
|
|
1037
|
+
options = client_options.ClientOptions(
|
|
1038
|
+
client_cert_source=mock_client_cert_source,
|
|
1039
|
+
api_endpoint=mock_api_endpoint,
|
|
1040
|
+
)
|
|
1041
|
+
(
|
|
1042
|
+
api_endpoint,
|
|
1043
|
+
cert_source,
|
|
1044
|
+
) = client_class.get_mtls_endpoint_and_cert_source(options)
|
|
1045
|
+
assert api_endpoint == mock_api_endpoint
|
|
1046
|
+
assert cert_source is expected_cert_source
|
|
1047
|
+
|
|
840
1048
|
# Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never".
|
|
841
1049
|
with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
|
|
842
1050
|
api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source()
|
|
@@ -887,18 +1095,6 @@ def test_route_optimization_client_get_mtls_endpoint_and_cert_source(client_clas
|
|
|
887
1095
|
== "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
|
|
888
1096
|
)
|
|
889
1097
|
|
|
890
|
-
# Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
|
|
891
|
-
with mock.patch.dict(
|
|
892
|
-
os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
|
|
893
|
-
):
|
|
894
|
-
with pytest.raises(ValueError) as excinfo:
|
|
895
|
-
client_class.get_mtls_endpoint_and_cert_source()
|
|
896
|
-
|
|
897
|
-
assert (
|
|
898
|
-
str(excinfo.value)
|
|
899
|
-
== "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
|
|
900
|
-
)
|
|
901
|
-
|
|
902
1098
|
|
|
903
1099
|
@pytest.mark.parametrize(
|
|
904
1100
|
"client_class", [RouteOptimizationClient, RouteOptimizationAsyncClient]
|
|
@@ -4050,6 +4246,7 @@ def test_route_optimization_grpc_asyncio_transport_channel():
|
|
|
4050
4246
|
|
|
4051
4247
|
# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are
|
|
4052
4248
|
# removed from grpc/grpc_asyncio transport constructor.
|
|
4249
|
+
@pytest.mark.filterwarnings("ignore::FutureWarning")
|
|
4053
4250
|
@pytest.mark.parametrize(
|
|
4054
4251
|
"transport_class",
|
|
4055
4252
|
[
|
|
@@ -1,97 +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.maps.routeoptimization_v1 import gapic_version as package_version
|
|
17
|
-
|
|
18
|
-
__version__ = package_version.__version__
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
from .services.route_optimization import (
|
|
22
|
-
RouteOptimizationAsyncClient,
|
|
23
|
-
RouteOptimizationClient,
|
|
24
|
-
)
|
|
25
|
-
from .types.route_optimization_service import (
|
|
26
|
-
AggregatedMetrics,
|
|
27
|
-
BatchOptimizeToursMetadata,
|
|
28
|
-
BatchOptimizeToursRequest,
|
|
29
|
-
BatchOptimizeToursResponse,
|
|
30
|
-
BreakRule,
|
|
31
|
-
DataFormat,
|
|
32
|
-
DistanceLimit,
|
|
33
|
-
GcsDestination,
|
|
34
|
-
GcsSource,
|
|
35
|
-
InjectedSolutionConstraint,
|
|
36
|
-
InputConfig,
|
|
37
|
-
Location,
|
|
38
|
-
OptimizeToursLongRunningMetadata,
|
|
39
|
-
OptimizeToursRequest,
|
|
40
|
-
OptimizeToursResponse,
|
|
41
|
-
OptimizeToursUriMetadata,
|
|
42
|
-
OptimizeToursUriRequest,
|
|
43
|
-
OptimizeToursUriResponse,
|
|
44
|
-
OptimizeToursValidationError,
|
|
45
|
-
OutputConfig,
|
|
46
|
-
RouteModifiers,
|
|
47
|
-
Shipment,
|
|
48
|
-
ShipmentModel,
|
|
49
|
-
ShipmentRoute,
|
|
50
|
-
ShipmentTypeIncompatibility,
|
|
51
|
-
ShipmentTypeRequirement,
|
|
52
|
-
SkippedShipment,
|
|
53
|
-
TimeWindow,
|
|
54
|
-
TransitionAttributes,
|
|
55
|
-
Uri,
|
|
56
|
-
Vehicle,
|
|
57
|
-
VehicleFullness,
|
|
58
|
-
Waypoint,
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
__all__ = (
|
|
62
|
-
"RouteOptimizationAsyncClient",
|
|
63
|
-
"AggregatedMetrics",
|
|
64
|
-
"BatchOptimizeToursMetadata",
|
|
65
|
-
"BatchOptimizeToursRequest",
|
|
66
|
-
"BatchOptimizeToursResponse",
|
|
67
|
-
"BreakRule",
|
|
68
|
-
"DataFormat",
|
|
69
|
-
"DistanceLimit",
|
|
70
|
-
"GcsDestination",
|
|
71
|
-
"GcsSource",
|
|
72
|
-
"InjectedSolutionConstraint",
|
|
73
|
-
"InputConfig",
|
|
74
|
-
"Location",
|
|
75
|
-
"OptimizeToursLongRunningMetadata",
|
|
76
|
-
"OptimizeToursRequest",
|
|
77
|
-
"OptimizeToursResponse",
|
|
78
|
-
"OptimizeToursUriMetadata",
|
|
79
|
-
"OptimizeToursUriRequest",
|
|
80
|
-
"OptimizeToursUriResponse",
|
|
81
|
-
"OptimizeToursValidationError",
|
|
82
|
-
"OutputConfig",
|
|
83
|
-
"RouteModifiers",
|
|
84
|
-
"RouteOptimizationClient",
|
|
85
|
-
"Shipment",
|
|
86
|
-
"ShipmentModel",
|
|
87
|
-
"ShipmentRoute",
|
|
88
|
-
"ShipmentTypeIncompatibility",
|
|
89
|
-
"ShipmentTypeRequirement",
|
|
90
|
-
"SkippedShipment",
|
|
91
|
-
"TimeWindow",
|
|
92
|
-
"TransitionAttributes",
|
|
93
|
-
"Uri",
|
|
94
|
-
"Vehicle",
|
|
95
|
-
"VehicleFullness",
|
|
96
|
-
"Waypoint",
|
|
97
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/tests/__init__.py
RENAMED
|
File without changes
|
{google_maps_routeoptimization-0.2.0 → google_maps_routeoptimization-0.3.0}/tests/unit/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|