diff --git a/packages/google-maps-places/CONTRIBUTING.rst b/packages/google-maps-places/CONTRIBUTING.rst index a81ae3485bec..5476e2350374 100644 --- a/packages/google-maps-places/CONTRIBUTING.rst +++ b/packages/google-maps-places/CONTRIBUTING.rst @@ -143,12 +143,12 @@ Running System Tests $ nox -s system # Run a single system test - $ nox -s system- -- -k + $ nox -s system-3.11 -- -k .. note:: - System tests are only configured to run under Python. + System tests are only configured to run under Python 3.8, 3.9, 3.10 and 3.11. For expediency, we do not run them in older versions of Python 3. This alone will not run the tests. You'll need to change some local diff --git a/packages/google-maps-places/docs/places_v1/services_.rst b/packages/google-maps-places/docs/places_v1/services_.rst new file mode 100644 index 000000000000..91337ff78a9a --- /dev/null +++ b/packages/google-maps-places/docs/places_v1/services_.rst @@ -0,0 +1,6 @@ +Services for Google Maps Places v1 API +====================================== +.. toctree:: + :maxdepth: 2 + + places diff --git a/packages/google-maps-places/docs/places_v1/types_.rst b/packages/google-maps-places/docs/places_v1/types_.rst new file mode 100644 index 000000000000..d634d52d3f87 --- /dev/null +++ b/packages/google-maps-places/docs/places_v1/types_.rst @@ -0,0 +1,6 @@ +Types for Google Maps Places v1 API +=================================== + +.. automodule:: google.maps.places_v1.types + :members: + :show-inheritance: diff --git a/packages/google-maps-places/google/maps/places/__init__.py b/packages/google-maps-places/google/maps/places/__init__.py index c7ed5a79b6e9..7f7e35023e57 100644 --- a/packages/google-maps-places/google/maps/places/__init__.py +++ b/packages/google-maps-places/google/maps/places/__init__.py @@ -20,21 +20,40 @@ from google.maps.places_v1.services.places.async_client import PlacesAsyncClient from google.maps.places_v1.services.places.client import PlacesClient +from google.maps.places_v1.types.attribution import AuthorAttribution +from google.maps.places_v1.types.ev_charging import EVChargeOptions, EVConnectorType +from google.maps.places_v1.types.fuel_options import FuelOptions from google.maps.places_v1.types.geometry import Circle +from google.maps.places_v1.types.photo import Photo from google.maps.places_v1.types.place import Place, PriceLevel from google.maps.places_v1.types.places_service import ( - Int32Range, + GetPhotoMediaRequest, + GetPlaceRequest, + PhotoMedia, + SearchNearbyRequest, + SearchNearbyResponse, SearchTextRequest, SearchTextResponse, ) +from google.maps.places_v1.types.review import Review __all__ = ( "PlacesClient", "PlacesAsyncClient", + "AuthorAttribution", + "EVChargeOptions", + "EVConnectorType", + "FuelOptions", "Circle", + "Photo", "Place", "PriceLevel", - "Int32Range", + "GetPhotoMediaRequest", + "GetPlaceRequest", + "PhotoMedia", + "SearchNearbyRequest", + "SearchNearbyResponse", "SearchTextRequest", "SearchTextResponse", + "Review", ) diff --git a/packages/google-maps-places/google/maps/places/gapic_version.py b/packages/google-maps-places/google/maps/places/gapic_version.py index 536d6648a6f0..360a0d13ebdd 100644 --- a/packages/google-maps-places/google/maps/places/gapic_version.py +++ b/packages/google-maps-places/google/maps/places/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "0.1.3" # {x-release-please-version} +__version__ = "0.0.0" # {x-release-please-version} diff --git a/packages/google-maps-places/google/maps/places_v1/__init__.py b/packages/google-maps-places/google/maps/places_v1/__init__.py index 22b1cff82887..4cfffdef61bb 100644 --- a/packages/google-maps-places/google/maps/places_v1/__init__.py +++ b/packages/google-maps-places/google/maps/places_v1/__init__.py @@ -19,17 +19,40 @@ from .services.places import PlacesAsyncClient, PlacesClient +from .types.attribution import AuthorAttribution +from .types.ev_charging import EVChargeOptions, EVConnectorType +from .types.fuel_options import FuelOptions from .types.geometry import Circle +from .types.photo import Photo from .types.place import Place, PriceLevel -from .types.places_service import Int32Range, SearchTextRequest, SearchTextResponse +from .types.places_service import ( + GetPhotoMediaRequest, + GetPlaceRequest, + PhotoMedia, + SearchNearbyRequest, + SearchNearbyResponse, + SearchTextRequest, + SearchTextResponse, +) +from .types.review import Review __all__ = ( "PlacesAsyncClient", + "AuthorAttribution", "Circle", - "Int32Range", + "EVChargeOptions", + "EVConnectorType", + "FuelOptions", + "GetPhotoMediaRequest", + "GetPlaceRequest", + "Photo", + "PhotoMedia", "Place", "PlacesClient", "PriceLevel", + "Review", + "SearchNearbyRequest", + "SearchNearbyResponse", "SearchTextRequest", "SearchTextResponse", ) diff --git a/packages/google-maps-places/google/maps/places_v1/gapic_metadata.json b/packages/google-maps-places/google/maps/places_v1/gapic_metadata.json index 71bc26dea4ef..a6378e40f60f 100644 --- a/packages/google-maps-places/google/maps/places_v1/gapic_metadata.json +++ b/packages/google-maps-places/google/maps/places_v1/gapic_metadata.json @@ -10,6 +10,21 @@ "grpc": { "libraryClient": "PlacesClient", "rpcs": { + "GetPhotoMedia": { + "methods": [ + "get_photo_media" + ] + }, + "GetPlace": { + "methods": [ + "get_place" + ] + }, + "SearchNearby": { + "methods": [ + "search_nearby" + ] + }, "SearchText": { "methods": [ "search_text" @@ -20,6 +35,21 @@ "grpc-async": { "libraryClient": "PlacesAsyncClient", "rpcs": { + "GetPhotoMedia": { + "methods": [ + "get_photo_media" + ] + }, + "GetPlace": { + "methods": [ + "get_place" + ] + }, + "SearchNearby": { + "methods": [ + "search_nearby" + ] + }, "SearchText": { "methods": [ "search_text" @@ -30,6 +60,21 @@ "rest": { "libraryClient": "PlacesClient", "rpcs": { + "GetPhotoMedia": { + "methods": [ + "get_photo_media" + ] + }, + "GetPlace": { + "methods": [ + "get_place" + ] + }, + "SearchNearby": { + "methods": [ + "search_nearby" + ] + }, "SearchText": { "methods": [ "search_text" diff --git a/packages/google-maps-places/google/maps/places_v1/gapic_version.py b/packages/google-maps-places/google/maps/places_v1/gapic_version.py index 536d6648a6f0..360a0d13ebdd 100644 --- a/packages/google-maps-places/google/maps/places_v1/gapic_version.py +++ b/packages/google-maps-places/google/maps/places_v1/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "0.1.3" # {x-release-please-version} +__version__ = "0.0.0" # {x-release-please-version} diff --git a/packages/google-maps-places/google/maps/places_v1/services/places/async_client.py b/packages/google-maps-places/google/maps/places_v1/services/places/async_client.py index ffc300beccc6..1b974b759506 100644 --- a/packages/google-maps-places/google/maps/places_v1/services/places/async_client.py +++ b/packages/google-maps-places/google/maps/places_v1/services/places/async_client.py @@ -42,7 +42,18 @@ except AttributeError: # pragma: NO COVER OptionalRetry = Union[retries.Retry, object] # type: ignore -from google.maps.places_v1.types import place, places_service +from google.geo.type.types import viewport +from google.type import latlng_pb2 # type: ignore +from google.type import localized_text_pb2 # type: ignore + +from google.maps.places_v1.types import ( + ev_charging, + fuel_options, + photo, + place, + places_service, + review, +) from .client import PlacesClient from .transports.base import DEFAULT_CLIENT_INFO, PlacesTransport @@ -50,13 +61,26 @@ class PlacesAsyncClient: - """Service definition for the Places API.""" + """Service definition for the Places API. Note: every request actually + requires a field mask set outside of the request proto (all/'*' is + not assumed). That can be set via either a side channel + (SystemParameterContext) over RPC, or a header (X-Goog-FieldMask) + over HTTP. See: https://cloud.google.com/apis/docs/system-parameters + """ _client: PlacesClient DEFAULT_ENDPOINT = PlacesClient.DEFAULT_ENDPOINT DEFAULT_MTLS_ENDPOINT = PlacesClient.DEFAULT_MTLS_ENDPOINT + photo_path = staticmethod(PlacesClient.photo_path) + parse_photo_path = staticmethod(PlacesClient.parse_photo_path) + photo_media_path = staticmethod(PlacesClient.photo_media_path) + parse_photo_media_path = staticmethod(PlacesClient.parse_photo_media_path) + place_path = staticmethod(PlacesClient.place_path) + parse_place_path = staticmethod(PlacesClient.parse_place_path) + review_path = staticmethod(PlacesClient.review_path) + parse_review_path = staticmethod(PlacesClient.parse_review_path) common_billing_account_path = staticmethod(PlacesClient.common_billing_account_path) parse_common_billing_account_path = staticmethod( PlacesClient.parse_common_billing_account_path @@ -201,6 +225,80 @@ def __init__( client_info=client_info, ) + async def search_nearby( + self, + request: Optional[Union[places_service.SearchNearbyRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> places_service.SearchNearbyResponse: + r"""Search for places near locations. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.maps import places_v1 + + async def sample_search_nearby(): + # Create a client + client = places_v1.PlacesAsyncClient() + + # Initialize request argument(s) + location_restriction = places_v1.LocationRestriction() + location_restriction.circle.radius = 0.648 + + request = places_v1.SearchNearbyRequest( + location_restriction=location_restriction, + ) + + # Make the request + response = await client.search_nearby(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.maps.places_v1.types.SearchNearbyRequest, dict]]): + The request object. Request proto for Search Nearby. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.maps.places_v1.types.SearchNearbyResponse: + Response proto for Search Nearby. + """ + # Create or coerce a protobuf request object. + request = places_service.SearchNearbyRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.search_nearby, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + async def search_text( self, request: Optional[Union[places_service.SearchTextRequest, dict]] = None, @@ -239,8 +337,7 @@ async def sample_search_text(): Args: request (Optional[Union[google.maps.places_v1.types.SearchTextRequest, dict]]): - The request object. Request data structure for - SearchText. + The request object. Request proto for SearchText. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -273,6 +370,210 @@ async def sample_search_text(): # Done; return the response. return response + async def get_photo_media( + self, + request: Optional[Union[places_service.GetPhotoMediaRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> places_service.PhotoMedia: + r"""Get a photo media with a photo reference string. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.maps import places_v1 + + async def sample_get_photo_media(): + # Create a client + client = places_v1.PlacesAsyncClient() + + # Initialize request argument(s) + request = places_v1.GetPhotoMediaRequest( + name="name_value", + ) + + # Make the request + response = await client.get_photo_media(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.maps.places_v1.types.GetPhotoMediaRequest, dict]]): + The request object. Request for fetching a photo of a + place using a photo resource name. + name (:class:`str`): + Required. The resource name of a photo. It is returned + in Place's photos.name field. Format: + places//photos//media. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.maps.places_v1.types.PhotoMedia: + A photo media from Places API. + """ + # Create or coerce a protobuf request object. + # Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + request = places_service.GetPhotoMediaRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_photo_media, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_place( + self, + request: Optional[Union[places_service.GetPlaceRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> place.Place: + r"""Get a Place with a place id (in a name) string. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.maps import places_v1 + + async def sample_get_place(): + # Create a client + client = places_v1.PlacesAsyncClient() + + # Initialize request argument(s) + request = places_v1.GetPlaceRequest( + name="name_value", + ) + + # Make the request + response = await client.get_place(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.maps.places_v1.types.GetPlaceRequest, dict]]): + The request object. Request for fetching a Place with a + place id (in a name) string. + name (:class:`str`): + Required. A place_id returned in a Place (with "places/" + prefix), or equivalently the name in the same Place. + Format: places/. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.maps.places_v1.types.Place: + All the information representing a + Place. + + """ + # Create or coerce a protobuf request object. + # Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + request = places_service.GetPlaceRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_place, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + async def __aenter__(self) -> "PlacesAsyncClient": return self diff --git a/packages/google-maps-places/google/maps/places_v1/services/places/client.py b/packages/google-maps-places/google/maps/places_v1/services/places/client.py index 034f9f894077..eb8f13584a99 100644 --- a/packages/google-maps-places/google/maps/places_v1/services/places/client.py +++ b/packages/google-maps-places/google/maps/places_v1/services/places/client.py @@ -46,7 +46,18 @@ except AttributeError: # pragma: NO COVER OptionalRetry = Union[retries.Retry, object] # type: ignore -from google.maps.places_v1.types import place, places_service +from google.geo.type.types import viewport +from google.type import latlng_pb2 # type: ignore +from google.type import localized_text_pb2 # type: ignore + +from google.maps.places_v1.types import ( + ev_charging, + fuel_options, + photo, + place, + places_service, + review, +) from .transports.base import DEFAULT_CLIENT_INFO, PlacesTransport from .transports.grpc import PlacesGrpcTransport @@ -90,7 +101,12 @@ def get_transport_class( class PlacesClient(metaclass=PlacesClientMeta): - """Service definition for the Places API.""" + """Service definition for the Places API. Note: every request actually + requires a field mask set outside of the request proto (all/'*' is + not assumed). That can be set via either a side channel + (SystemParameterContext) over RPC, or a header (X-Goog-FieldMask) + over HTTP. See: https://cloud.google.com/apis/docs/system-parameters + """ @staticmethod def _get_default_mtls_endpoint(api_endpoint): @@ -174,6 +190,74 @@ def transport(self) -> PlacesTransport: """ return self._transport + @staticmethod + def photo_path( + place: str, + photo: str, + ) -> str: + """Returns a fully-qualified photo string.""" + return "places/{place}/photos/{photo}".format( + place=place, + photo=photo, + ) + + @staticmethod + def parse_photo_path(path: str) -> Dict[str, str]: + """Parses a photo path into its component segments.""" + m = re.match(r"^places/(?P.+?)/photos/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def photo_media_path( + place_id: str, + photo_reference: str, + ) -> str: + """Returns a fully-qualified photo_media string.""" + return "places/{place_id}/photos/{photo_reference}/media".format( + place_id=place_id, + photo_reference=photo_reference, + ) + + @staticmethod + def parse_photo_media_path(path: str) -> Dict[str, str]: + """Parses a photo_media path into its component segments.""" + m = re.match( + r"^places/(?P.+?)/photos/(?P.+?)/media$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def place_path( + place_id: str, + ) -> str: + """Returns a fully-qualified place string.""" + return "places/{place_id}".format( + place_id=place_id, + ) + + @staticmethod + def parse_place_path(path: str) -> Dict[str, str]: + """Parses a place path into its component segments.""" + m = re.match(r"^places/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def review_path( + place: str, + review: str, + ) -> str: + """Returns a fully-qualified review string.""" + return "places/{place}/reviews/{review}".format( + place=place, + review=review, + ) + + @staticmethod + def parse_review_path(path: str) -> Dict[str, str]: + """Parses a review path into its component segments.""" + m = re.match(r"^places/(?P.+?)/reviews/(?P.+?)$", path) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path( billing_account: str, @@ -418,6 +502,81 @@ def __init__( api_audience=client_options.api_audience, ) + def search_nearby( + self, + request: Optional[Union[places_service.SearchNearbyRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> places_service.SearchNearbyResponse: + r"""Search for places near locations. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.maps import places_v1 + + def sample_search_nearby(): + # Create a client + client = places_v1.PlacesClient() + + # Initialize request argument(s) + location_restriction = places_v1.LocationRestriction() + location_restriction.circle.radius = 0.648 + + request = places_v1.SearchNearbyRequest( + location_restriction=location_restriction, + ) + + # Make the request + response = client.search_nearby(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.maps.places_v1.types.SearchNearbyRequest, dict]): + The request object. Request proto for Search Nearby. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.maps.places_v1.types.SearchNearbyResponse: + Response proto for Search Nearby. + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a places_service.SearchNearbyRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, places_service.SearchNearbyRequest): + request = places_service.SearchNearbyRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.search_nearby] + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + def search_text( self, request: Optional[Union[places_service.SearchTextRequest, dict]] = None, @@ -456,8 +615,7 @@ def sample_search_text(): Args: request (Union[google.maps.places_v1.types.SearchTextRequest, dict]): - The request object. Request data structure for - SearchText. + The request object. Request proto for SearchText. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -491,6 +649,210 @@ def sample_search_text(): # Done; return the response. return response + def get_photo_media( + self, + request: Optional[Union[places_service.GetPhotoMediaRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> places_service.PhotoMedia: + r"""Get a photo media with a photo reference string. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.maps import places_v1 + + def sample_get_photo_media(): + # Create a client + client = places_v1.PlacesClient() + + # Initialize request argument(s) + request = places_v1.GetPhotoMediaRequest( + name="name_value", + ) + + # Make the request + response = client.get_photo_media(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.maps.places_v1.types.GetPhotoMediaRequest, dict]): + The request object. Request for fetching a photo of a + place using a photo resource name. + name (str): + Required. The resource name of a photo. It is returned + in Place's photos.name field. Format: + places//photos//media. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.maps.places_v1.types.PhotoMedia: + A photo media from Places API. + """ + # Create or coerce a protobuf request object. + # Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a places_service.GetPhotoMediaRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, places_service.GetPhotoMediaRequest): + request = places_service.GetPhotoMediaRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get_photo_media] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_place( + self, + request: Optional[Union[places_service.GetPlaceRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> place.Place: + r"""Get a Place with a place id (in a name) string. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.maps import places_v1 + + def sample_get_place(): + # Create a client + client = places_v1.PlacesClient() + + # Initialize request argument(s) + request = places_v1.GetPlaceRequest( + name="name_value", + ) + + # Make the request + response = client.get_place(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.maps.places_v1.types.GetPlaceRequest, dict]): + The request object. Request for fetching a Place with a + place id (in a name) string. + name (str): + Required. A place_id returned in a Place (with "places/" + prefix), or equivalently the name in the same Place. + Format: places/. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.maps.places_v1.types.Place: + All the information representing a + Place. + + """ + # Create or coerce a protobuf request object. + # Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a places_service.GetPlaceRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, places_service.GetPlaceRequest): + request = places_service.GetPlaceRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get_place] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + def __enter__(self) -> "PlacesClient": return self diff --git a/packages/google-maps-places/google/maps/places_v1/services/places/transports/base.py b/packages/google-maps-places/google/maps/places_v1/services/places/transports/base.py index f31b2ad32b94..9ee0fc559e65 100644 --- a/packages/google-maps-places/google/maps/places_v1/services/places/transports/base.py +++ b/packages/google-maps-places/google/maps/places_v1/services/places/transports/base.py @@ -25,7 +25,7 @@ from google.oauth2 import service_account # type: ignore from google.maps.places_v1 import gapic_version as package_version -from google.maps.places_v1.types import places_service +from google.maps.places_v1.types import place, places_service DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=package_version.__version__ @@ -122,11 +122,26 @@ def __init__( def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { + self.search_nearby: gapic_v1.method.wrap_method( + self.search_nearby, + default_timeout=None, + client_info=client_info, + ), self.search_text: gapic_v1.method.wrap_method( self.search_text, default_timeout=None, client_info=client_info, ), + self.get_photo_media: gapic_v1.method.wrap_method( + self.get_photo_media, + default_timeout=None, + client_info=client_info, + ), + self.get_place: gapic_v1.method.wrap_method( + self.get_place, + default_timeout=None, + client_info=client_info, + ), } def close(self): @@ -138,6 +153,18 @@ def close(self): """ raise NotImplementedError() + @property + def search_nearby( + self, + ) -> Callable[ + [places_service.SearchNearbyRequest], + Union[ + places_service.SearchNearbyResponse, + Awaitable[places_service.SearchNearbyResponse], + ], + ]: + raise NotImplementedError() + @property def search_text( self, @@ -150,6 +177,23 @@ def search_text( ]: raise NotImplementedError() + @property + def get_photo_media( + self, + ) -> Callable[ + [places_service.GetPhotoMediaRequest], + Union[places_service.PhotoMedia, Awaitable[places_service.PhotoMedia]], + ]: + raise NotImplementedError() + + @property + def get_place( + self, + ) -> Callable[ + [places_service.GetPlaceRequest], Union[place.Place, Awaitable[place.Place]] + ]: + raise NotImplementedError() + @property def kind(self) -> str: raise NotImplementedError() diff --git a/packages/google-maps-places/google/maps/places_v1/services/places/transports/grpc.py b/packages/google-maps-places/google/maps/places_v1/services/places/transports/grpc.py index 2e6ec7ebf581..dc682544c43b 100644 --- a/packages/google-maps-places/google/maps/places_v1/services/places/transports/grpc.py +++ b/packages/google-maps-places/google/maps/places_v1/services/places/transports/grpc.py @@ -22,7 +22,7 @@ from google.auth.transport.grpc import SslCredentials # type: ignore import grpc # type: ignore -from google.maps.places_v1.types import places_service +from google.maps.places_v1.types import place, places_service from .base import DEFAULT_CLIENT_INFO, PlacesTransport @@ -30,7 +30,11 @@ class PlacesGrpcTransport(PlacesTransport): """gRPC backend transport for Places. - Service definition for the Places API. + Service definition for the Places API. Note: every request actually + requires a field mask set outside of the request proto (all/'*' is + not assumed). That can be set via either a side channel + (SystemParameterContext) over RPC, or a header (X-Goog-FieldMask) + over HTTP. See: https://cloud.google.com/apis/docs/system-parameters This class defines the same methods as the primary client, so the primary client can load the underlying transport implementation @@ -228,6 +232,34 @@ def grpc_channel(self) -> grpc.Channel: """Return the channel designed to connect to this service.""" return self._grpc_channel + @property + def search_nearby( + self, + ) -> Callable[ + [places_service.SearchNearbyRequest], places_service.SearchNearbyResponse + ]: + r"""Return a callable for the search nearby method over gRPC. + + Search for places near locations. + + Returns: + Callable[[~.SearchNearbyRequest], + ~.SearchNearbyResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "search_nearby" not in self._stubs: + self._stubs["search_nearby"] = self.grpc_channel.unary_unary( + "/google.maps.places.v1.Places/SearchNearby", + request_serializer=places_service.SearchNearbyRequest.serialize, + response_deserializer=places_service.SearchNearbyResponse.deserialize, + ) + return self._stubs["search_nearby"] + @property def search_text( self, @@ -256,6 +288,56 @@ def search_text( ) return self._stubs["search_text"] + @property + def get_photo_media( + self, + ) -> Callable[[places_service.GetPhotoMediaRequest], places_service.PhotoMedia]: + r"""Return a callable for the get photo media method over gRPC. + + Get a photo media with a photo reference string. + + Returns: + Callable[[~.GetPhotoMediaRequest], + ~.PhotoMedia]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_photo_media" not in self._stubs: + self._stubs["get_photo_media"] = self.grpc_channel.unary_unary( + "/google.maps.places.v1.Places/GetPhotoMedia", + request_serializer=places_service.GetPhotoMediaRequest.serialize, + response_deserializer=places_service.PhotoMedia.deserialize, + ) + return self._stubs["get_photo_media"] + + @property + def get_place(self) -> Callable[[places_service.GetPlaceRequest], place.Place]: + r"""Return a callable for the get place method over gRPC. + + Get a Place with a place id (in a name) string. + + Returns: + Callable[[~.GetPlaceRequest], + ~.Place]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_place" not in self._stubs: + self._stubs["get_place"] = self.grpc_channel.unary_unary( + "/google.maps.places.v1.Places/GetPlace", + request_serializer=places_service.GetPlaceRequest.serialize, + response_deserializer=place.Place.deserialize, + ) + return self._stubs["get_place"] + def close(self): self.grpc_channel.close() diff --git a/packages/google-maps-places/google/maps/places_v1/services/places/transports/grpc_asyncio.py b/packages/google-maps-places/google/maps/places_v1/services/places/transports/grpc_asyncio.py index 280eee913beb..01c02171ec1e 100644 --- a/packages/google-maps-places/google/maps/places_v1/services/places/transports/grpc_asyncio.py +++ b/packages/google-maps-places/google/maps/places_v1/services/places/transports/grpc_asyncio.py @@ -22,7 +22,7 @@ import grpc # type: ignore from grpc.experimental import aio # type: ignore -from google.maps.places_v1.types import places_service +from google.maps.places_v1.types import place, places_service from .base import DEFAULT_CLIENT_INFO, PlacesTransport from .grpc import PlacesGrpcTransport @@ -31,7 +31,11 @@ class PlacesGrpcAsyncIOTransport(PlacesTransport): """gRPC AsyncIO backend transport for Places. - Service definition for the Places API. + Service definition for the Places API. Note: every request actually + requires a field mask set outside of the request proto (all/'*' is + not assumed). That can be set via either a side channel + (SystemParameterContext) over RPC, or a header (X-Goog-FieldMask) + over HTTP. See: https://cloud.google.com/apis/docs/system-parameters This class defines the same methods as the primary client, so the primary client can load the underlying transport implementation @@ -231,6 +235,35 @@ def grpc_channel(self) -> aio.Channel: # Return the channel from cache. return self._grpc_channel + @property + def search_nearby( + self, + ) -> Callable[ + [places_service.SearchNearbyRequest], + Awaitable[places_service.SearchNearbyResponse], + ]: + r"""Return a callable for the search nearby method over gRPC. + + Search for places near locations. + + Returns: + Callable[[~.SearchNearbyRequest], + Awaitable[~.SearchNearbyResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "search_nearby" not in self._stubs: + self._stubs["search_nearby"] = self.grpc_channel.unary_unary( + "/google.maps.places.v1.Places/SearchNearby", + request_serializer=places_service.SearchNearbyRequest.serialize, + response_deserializer=places_service.SearchNearbyResponse.deserialize, + ) + return self._stubs["search_nearby"] + @property def search_text( self, @@ -259,6 +292,60 @@ def search_text( ) return self._stubs["search_text"] + @property + def get_photo_media( + self, + ) -> Callable[ + [places_service.GetPhotoMediaRequest], Awaitable[places_service.PhotoMedia] + ]: + r"""Return a callable for the get photo media method over gRPC. + + Get a photo media with a photo reference string. + + Returns: + Callable[[~.GetPhotoMediaRequest], + Awaitable[~.PhotoMedia]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_photo_media" not in self._stubs: + self._stubs["get_photo_media"] = self.grpc_channel.unary_unary( + "/google.maps.places.v1.Places/GetPhotoMedia", + request_serializer=places_service.GetPhotoMediaRequest.serialize, + response_deserializer=places_service.PhotoMedia.deserialize, + ) + return self._stubs["get_photo_media"] + + @property + def get_place( + self, + ) -> Callable[[places_service.GetPlaceRequest], Awaitable[place.Place]]: + r"""Return a callable for the get place method over gRPC. + + Get a Place with a place id (in a name) string. + + Returns: + Callable[[~.GetPlaceRequest], + Awaitable[~.Place]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_place" not in self._stubs: + self._stubs["get_place"] = self.grpc_channel.unary_unary( + "/google.maps.places.v1.Places/GetPlace", + request_serializer=places_service.GetPlaceRequest.serialize, + response_deserializer=place.Place.deserialize, + ) + return self._stubs["get_place"] + def close(self): return self.grpc_channel.close() diff --git a/packages/google-maps-places/google/maps/places_v1/services/places/transports/rest.py b/packages/google-maps-places/google/maps/places_v1/services/places/transports/rest.py index f67c0c43e682..6d4ac27db97f 100644 --- a/packages/google-maps-places/google/maps/places_v1/services/places/transports/rest.py +++ b/packages/google-maps-places/google/maps/places_v1/services/places/transports/rest.py @@ -36,7 +36,7 @@ OptionalRetry = Union[retries.Retry, object] # type: ignore -from google.maps.places_v1.types import places_service +from google.maps.places_v1.types import place, places_service from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO from .base import PlacesTransport @@ -63,6 +63,30 @@ class PlacesRestInterceptor: .. code-block:: python class MyCustomPlacesInterceptor(PlacesRestInterceptor): + def pre_get_photo_media(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_photo_media(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_get_place(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_place(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_search_nearby(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_search_nearby(self, response): + logging.log(f"Received response: {response}") + return response + def pre_search_text(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -77,6 +101,73 @@ def post_search_text(self, response): """ + def pre_get_photo_media( + self, + request: places_service.GetPhotoMediaRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[places_service.GetPhotoMediaRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_photo_media + + Override in a subclass to manipulate the request or metadata + before they are sent to the Places server. + """ + return request, metadata + + def post_get_photo_media( + self, response: places_service.PhotoMedia + ) -> places_service.PhotoMedia: + """Post-rpc interceptor for get_photo_media + + Override in a subclass to manipulate the response + after it is returned by the Places server but before + it is returned to user code. + """ + return response + + def pre_get_place( + self, + request: places_service.GetPlaceRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[places_service.GetPlaceRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_place + + Override in a subclass to manipulate the request or metadata + before they are sent to the Places server. + """ + return request, metadata + + def post_get_place(self, response: place.Place) -> place.Place: + """Post-rpc interceptor for get_place + + Override in a subclass to manipulate the response + after it is returned by the Places server but before + it is returned to user code. + """ + return response + + def pre_search_nearby( + self, + request: places_service.SearchNearbyRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[places_service.SearchNearbyRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for search_nearby + + Override in a subclass to manipulate the request or metadata + before they are sent to the Places server. + """ + return request, metadata + + def post_search_nearby( + self, response: places_service.SearchNearbyResponse + ) -> places_service.SearchNearbyResponse: + """Post-rpc interceptor for search_nearby + + Override in a subclass to manipulate the response + after it is returned by the Places server but before + it is returned to user code. + """ + return response + def pre_search_text( self, request: places_service.SearchTextRequest, @@ -111,7 +202,11 @@ class PlacesRestStub: class PlacesRestTransport(PlacesTransport): """REST backend transport for Places. - Service definition for the Places API. + Service definition for the Places API. Note: every request actually + requires a field mask set outside of the request proto (all/'*' is + not assumed). That can be set via either a side channel + (SystemParameterContext) over RPC, or a header (X-Goog-FieldMask) + over HTTP. See: https://cloud.google.com/apis/docs/system-parameters This class defines the same methods as the primary client, so the primary client can load the underlying transport implementation @@ -197,6 +292,277 @@ def __init__( self._interceptor = interceptor or PlacesRestInterceptor() self._prep_wrapped_messages(client_info) + class _GetPhotoMedia(PlacesRestStub): + def __hash__(self): + return hash("GetPhotoMedia") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: places_service.GetPhotoMediaRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> places_service.PhotoMedia: + r"""Call the get photo media method over HTTP. + + Args: + request (~.places_service.GetPhotoMediaRequest): + The request object. Request for fetching a photo of a + place using a photo resource name. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.places_service.PhotoMedia: + A photo media from Places API. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=places/*/photos/*/media}", + }, + ] + request, metadata = self._interceptor.pre_get_photo_media(request, metadata) + pb_request = places_service.GetPhotoMediaRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = places_service.PhotoMedia() + pb_resp = places_service.PhotoMedia.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_photo_media(resp) + return resp + + class _GetPlace(PlacesRestStub): + def __hash__(self): + return hash("GetPlace") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: places_service.GetPlaceRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> place.Place: + r"""Call the get place method over HTTP. + + Args: + request (~.places_service.GetPlaceRequest): + The request object. Request for fetching a Place with a + place id (in a name) string. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.place.Place: + All the information representing a + Place. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=places/*}", + }, + ] + request, metadata = self._interceptor.pre_get_place(request, metadata) + pb_request = places_service.GetPlaceRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = place.Place() + pb_resp = place.Place.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_place(resp) + return resp + + class _SearchNearby(PlacesRestStub): + def __hash__(self): + return hash("SearchNearby") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: places_service.SearchNearbyRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> places_service.SearchNearbyResponse: + r"""Call the search nearby method over HTTP. + + Args: + request (~.places_service.SearchNearbyRequest): + The request object. Request proto for Search Nearby. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.places_service.SearchNearbyResponse: + Response proto for Search Nearby. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/places:searchNearby", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_search_nearby(request, metadata) + pb_request = places_service.SearchNearbyRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + including_default_value_fields=False, + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = places_service.SearchNearbyResponse() + pb_resp = places_service.SearchNearbyResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_search_nearby(resp) + return resp + class _SearchText(PlacesRestStub): def __hash__(self): return hash("SearchText") @@ -223,8 +589,7 @@ def __call__( Args: request (~.places_service.SearchTextRequest): - The request object. Request data structure for - SearchText. + The request object. Request proto for SearchText. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -239,7 +604,7 @@ def __call__( http_options: List[Dict[str, str]] = [ { "method": "post", - "uri": "/v1/Text:search", + "uri": "/v1/places:searchText", "body": "*", }, ] @@ -293,6 +658,30 @@ def __call__( resp = self._interceptor.post_search_text(resp) return resp + @property + def get_photo_media( + self, + ) -> Callable[[places_service.GetPhotoMediaRequest], places_service.PhotoMedia]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetPhotoMedia(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_place(self) -> Callable[[places_service.GetPlaceRequest], place.Place]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetPlace(self._session, self._host, self._interceptor) # type: ignore + + @property + def search_nearby( + self, + ) -> Callable[ + [places_service.SearchNearbyRequest], places_service.SearchNearbyResponse + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._SearchNearby(self._session, self._host, self._interceptor) # type: ignore + @property def search_text( self, diff --git a/packages/google-maps-places/google/maps/places_v1/types/__init__.py b/packages/google-maps-places/google/maps/places_v1/types/__init__.py index cbd87d842401..e201b72519c9 100644 --- a/packages/google-maps-places/google/maps/places_v1/types/__init__.py +++ b/packages/google-maps-places/google/maps/places_v1/types/__init__.py @@ -13,15 +13,38 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from .attribution import AuthorAttribution +from .ev_charging import EVChargeOptions, EVConnectorType +from .fuel_options import FuelOptions from .geometry import Circle +from .photo import Photo from .place import Place, PriceLevel -from .places_service import Int32Range, SearchTextRequest, SearchTextResponse +from .places_service import ( + GetPhotoMediaRequest, + GetPlaceRequest, + PhotoMedia, + SearchNearbyRequest, + SearchNearbyResponse, + SearchTextRequest, + SearchTextResponse, +) +from .review import Review __all__ = ( + "AuthorAttribution", + "EVChargeOptions", + "EVConnectorType", + "FuelOptions", "Circle", + "Photo", "Place", "PriceLevel", - "Int32Range", + "GetPhotoMediaRequest", + "GetPlaceRequest", + "PhotoMedia", + "SearchNearbyRequest", + "SearchNearbyResponse", "SearchTextRequest", "SearchTextResponse", + "Review", ) diff --git a/packages/google-maps-places/google/maps/places_v1/types/attribution.py b/packages/google-maps-places/google/maps/places_v1/types/attribution.py new file mode 100644 index 000000000000..6b56f07c539b --- /dev/null +++ b/packages/google-maps-places/google/maps/places_v1/types/attribution.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.maps.places.v1", + manifest={ + "AuthorAttribution", + }, +) + + +class AuthorAttribution(proto.Message): + r"""Information about the author of the UGC data. Used in + [Photo][google.maps.places.v1.Photo], and + [Review][google.maps.places.v1.Review]. + + Attributes: + display_name (str): + Output only. Name of the author of the + [Photo][google.maps.places.v1.Photo] or + [Review][google.maps.places.v1.Review]. + uri (str): + Output only. URI of the author of the + [Photo][google.maps.places.v1.Photo] or + [Review][google.maps.places.v1.Review]. + photo_uri (str): + Output only. Profile photo URI of the author of the + [Photo][google.maps.places.v1.Photo] or + [Review][google.maps.places.v1.Review]. + """ + + display_name: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + photo_uri: str = proto.Field( + proto.STRING, + number=3, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-maps-places/google/maps/places_v1/types/ev_charging.py b/packages/google-maps-places/google/maps/places_v1/types/ev_charging.py new file mode 100644 index 000000000000..d2a9baee01ac --- /dev/null +++ b/packages/google-maps-places/google/maps/places_v1/types/ev_charging.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +from google.protobuf import timestamp_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.maps.places.v1", + manifest={ + "EVConnectorType", + "EVChargeOptions", + }, +) + + +class EVConnectorType(proto.Enum): + r"""See + http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=6872107 for + additional information/context on EV charging connector types. + + Values: + EV_CONNECTOR_TYPE_UNSPECIFIED (0): + Unspecified connector. + EV_CONNECTOR_TYPE_OTHER (1): + Other connector types. + EV_CONNECTOR_TYPE_J1772 (2): + J1772 type 1 connector. + EV_CONNECTOR_TYPE_TYPE_2 (3): + IEC 62196 type 2 connector. Often referred to + as MENNEKES. + EV_CONNECTOR_TYPE_CHADEMO (4): + CHAdeMO type connector. + EV_CONNECTOR_TYPE_CCS_COMBO_1 (5): + Combined Charging System (AC and DC). Based + on SAE. Type-1 J-1772 connector + EV_CONNECTOR_TYPE_CCS_COMBO_2 (6): + Combined Charging System (AC and DC). Based + on Type-2 Mennekes connector + EV_CONNECTOR_TYPE_TESLA (7): + The generic TESLA connector. This is NACS in + the North America but can be non-NACS in other + parts of the world (e.g. CCS Combo 2 (CCS2) or + GB/T). This value is less representative of an + actual connector type, and more represents the + ability to charge a Tesla brand vehicle at a + Tesla owned charging station. + EV_CONNECTOR_TYPE_UNSPECIFIED_GB_T (8): + GB/T type corresponds to the GB/T standard in China. This + type covers all GB_T types. + EV_CONNECTOR_TYPE_UNSPECIFIED_WALL_OUTLET (9): + Unspecified wall outlet. + """ + EV_CONNECTOR_TYPE_UNSPECIFIED = 0 + EV_CONNECTOR_TYPE_OTHER = 1 + EV_CONNECTOR_TYPE_J1772 = 2 + EV_CONNECTOR_TYPE_TYPE_2 = 3 + EV_CONNECTOR_TYPE_CHADEMO = 4 + EV_CONNECTOR_TYPE_CCS_COMBO_1 = 5 + EV_CONNECTOR_TYPE_CCS_COMBO_2 = 6 + EV_CONNECTOR_TYPE_TESLA = 7 + EV_CONNECTOR_TYPE_UNSPECIFIED_GB_T = 8 + EV_CONNECTOR_TYPE_UNSPECIFIED_WALL_OUTLET = 9 + + +class EVChargeOptions(proto.Message): + r"""Information about the EV Charge Station hosted in Place. Terminology + follows + https://afdc.energy.gov/fuels/electricity_infrastructure.html One + port could charge one car at a time. One port has one or more + connectors. One station has one or more ports. + + Attributes: + connector_count (int): + Number of connectors at this station. + However, because some ports can have multiple + connectors but only be able to charge one car at + a time (e.g.) the number of connectors may be + greater than the total number of cars which can + charge simultaneously. + connector_aggregation (MutableSequence[google.maps.places_v1.types.EVChargeOptions.ConnectorAggregation]): + A list of EV charging connector aggregations + that contain connectors of the same type and + same charge rate. + """ + + class ConnectorAggregation(proto.Message): + r"""EV charging information grouped by [type, max_charge_rate_kw]. Shows + EV charge aggregation of connectors that have the same type and max + charge rate in kw. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + type_ (google.maps.places_v1.types.EVConnectorType): + The connector type of this aggregation. + max_charge_rate_kw (float): + The static max charging rate in kw of each + connector in the aggregation. + count (int): + Number of connectors in this aggregation. + available_count (int): + Number of connectors in this aggregation that + are currently available. + + This field is a member of `oneof`_ ``_available_count``. + out_of_service_count (int): + Number of connectors in this aggregation that + are currently out of service. + + This field is a member of `oneof`_ ``_out_of_service_count``. + availability_last_update_time (google.protobuf.timestamp_pb2.Timestamp): + The timestamp when the connector availability + information in this aggregation was last + updated. + """ + + type_: "EVConnectorType" = proto.Field( + proto.ENUM, + number=1, + enum="EVConnectorType", + ) + max_charge_rate_kw: float = proto.Field( + proto.DOUBLE, + number=2, + ) + count: int = proto.Field( + proto.INT32, + number=3, + ) + available_count: int = proto.Field( + proto.INT32, + number=4, + optional=True, + ) + out_of_service_count: int = proto.Field( + proto.INT32, + number=5, + optional=True, + ) + availability_last_update_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=6, + message=timestamp_pb2.Timestamp, + ) + + connector_count: int = proto.Field( + proto.INT32, + number=1, + ) + connector_aggregation: MutableSequence[ConnectorAggregation] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ConnectorAggregation, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-maps-places/google/maps/places_v1/types/fuel_options.py b/packages/google-maps-places/google/maps/places_v1/types/fuel_options.py new file mode 100644 index 000000000000..edbf237de028 --- /dev/null +++ b/packages/google-maps-places/google/maps/places_v1/types/fuel_options.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +from google.protobuf import timestamp_pb2 # type: ignore +from google.type import money_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.maps.places.v1", + manifest={ + "FuelOptions", + }, +) + + +class FuelOptions(proto.Message): + r"""The most recent information about fuel options in a gas + station. This information is updated regularly. + + Attributes: + fuel_prices (MutableSequence[google.maps.places_v1.types.FuelOptions.FuelPrice]): + The last known fuel price for each type of + fuel this station has. There is one entry per + fuel type this station has. Order is not + important. + """ + + class FuelPrice(proto.Message): + r"""Fuel price information for a given type. + + Attributes: + type_ (google.maps.places_v1.types.FuelOptions.FuelPrice.FuelType): + The type of fuel. + price (google.type.money_pb2.Money): + The price of the fuel. + update_time (google.protobuf.timestamp_pb2.Timestamp): + The time the fuel price was last updated. + """ + + class FuelType(proto.Enum): + r"""Types of fuel. + + Values: + FUEL_TYPE_UNSPECIFIED (0): + Unspecified fuel type. + DIESEL (1): + Diesel fuel. + REGULAR_UNLEADED (2): + Regular unleaded. + MIDGRADE (3): + Midgrade. + PREMIUM (4): + Premium. + SP91 (5): + SP 91. + SP91_E10 (6): + SP 91 E10. + SP92 (7): + SP 92. + SP95 (8): + SP 95. + SP95_E10 (9): + SP95 E10. + SP98 (10): + SP 98. + SP99 (11): + SP 99. + SP100 (12): + SP 100. + LPG (13): + LPG. + E80 (14): + E 80. + E85 (15): + E 85. + METHANE (16): + Methane. + BIO_DIESEL (17): + Bio-diesel. + TRUCK_DIESEL (18): + Truck diesel. + """ + FUEL_TYPE_UNSPECIFIED = 0 + DIESEL = 1 + REGULAR_UNLEADED = 2 + MIDGRADE = 3 + PREMIUM = 4 + SP91 = 5 + SP91_E10 = 6 + SP92 = 7 + SP95 = 8 + SP95_E10 = 9 + SP98 = 10 + SP99 = 11 + SP100 = 12 + LPG = 13 + E80 = 14 + E85 = 15 + METHANE = 16 + BIO_DIESEL = 17 + TRUCK_DIESEL = 18 + + type_: "FuelOptions.FuelPrice.FuelType" = proto.Field( + proto.ENUM, + number=1, + enum="FuelOptions.FuelPrice.FuelType", + ) + price: money_pb2.Money = proto.Field( + proto.MESSAGE, + number=2, + message=money_pb2.Money, + ) + update_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=3, + message=timestamp_pb2.Timestamp, + ) + + fuel_prices: MutableSequence[FuelPrice] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=FuelPrice, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-maps-places/google/maps/places_v1/types/geometry.py b/packages/google-maps-places/google/maps/places_v1/types/geometry.py index cdcc1ad9775b..ee6fd980d1fd 100644 --- a/packages/google-maps-places/google/maps/places_v1/types/geometry.py +++ b/packages/google-maps-places/google/maps/places_v1/types/geometry.py @@ -35,11 +35,11 @@ class Circle(proto.Message): center (google.type.latlng_pb2.LatLng): Required. Center latitude and longitude. - The range of latitude must be within ``[-90.0, 90.0]``. The - range of the longitude must be within ``[-180.0, 180.0]``. + The range of latitude must be within [-90.0, 90.0]. The + range of the longitude must be within [-180.0, 180.0]. radius (float): Required. Radius measured in meters. The radius must be - within ``[0.0, 50000.0]``. + within [0.0, 50000.0]. """ center: latlng_pb2.LatLng = proto.Field( diff --git a/packages/google-maps-places/google/maps/places_v1/types/photo.py b/packages/google-maps-places/google/maps/places_v1/types/photo.py new file mode 100644 index 000000000000..34e23e4a44e9 --- /dev/null +++ b/packages/google-maps-places/google/maps/places_v1/types/photo.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +from google.maps.places_v1.types import attribution + +__protobuf__ = proto.module( + package="google.maps.places.v1", + manifest={ + "Photo", + }, +) + + +class Photo(proto.Message): + r"""Information about a photo of a place. + + Attributes: + name (str): + Output only. A reference representing this place photo which + may be used to look up this place photo again (a.k.a. the + API "resource" name: places/{place_id}/photos/{photo}). + width_px (int): + Output only. The maximum available width, in + pixels. + height_px (int): + Output only. The maximum available height, in + pixels. + author_attributions (MutableSequence[google.maps.places_v1.types.AuthorAttribution]): + Output only. This photo's authors. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + width_px: int = proto.Field( + proto.INT32, + number=2, + ) + height_px: int = proto.Field( + proto.INT32, + number=3, + ) + author_attributions: MutableSequence[ + attribution.AuthorAttribution + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=attribution.AuthorAttribution, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-maps-places/google/maps/places_v1/types/place.py b/packages/google-maps-places/google/maps/places_v1/types/place.py index f9a0d34f9716..b5cec0c4975f 100644 --- a/packages/google-maps-places/google/maps/places_v1/types/place.py +++ b/packages/google-maps-places/google/maps/places_v1/types/place.py @@ -18,12 +18,15 @@ from typing import MutableMapping, MutableSequence from google.geo.type.types import viewport as ggt_viewport -from google.protobuf import timestamp_pb2 # type: ignore from google.type import date_pb2 # type: ignore from google.type import latlng_pb2 # type: ignore from google.type import localized_text_pb2 # type: ignore import proto # type: ignore +from google.maps.places_v1.types import ev_charging +from google.maps.places_v1.types import fuel_options as gmp_fuel_options +from google.maps.places_v1.types import photo, review + __protobuf__ = proto.module( package="google.maps.places.v1", manifest={ @@ -39,23 +42,23 @@ class PriceLevel(proto.Enum): Values: PRICE_LEVEL_UNSPECIFIED (0): Place price level is unspecified or unknown. - FREE (1): - No description available. - INEXPENSIVE (2): + PRICE_LEVEL_FREE (1): + Place provides free services. + PRICE_LEVEL_INEXPENSIVE (2): Place provides inexpensive services. - MODERATE (3): + PRICE_LEVEL_MODERATE (3): Place provides moderately priced services. - EXPENSIVE (4): + PRICE_LEVEL_EXPENSIVE (4): Place provides expensive services. - VERY_EXPENSIVE (5): - Place provides very expensive services. + PRICE_LEVEL_VERY_EXPENSIVE (5): + Place provides very expensive service s. """ PRICE_LEVEL_UNSPECIFIED = 0 - FREE = 1 - INEXPENSIVE = 2 - MODERATE = 3 - EXPENSIVE = 4 - VERY_EXPENSIVE = 5 + PRICE_LEVEL_FREE = 1 + PRICE_LEVEL_INEXPENSIVE = 2 + PRICE_LEVEL_MODERATE = 3 + PRICE_LEVEL_EXPENSIVE = 4 + PRICE_LEVEL_VERY_EXPENSIVE = 5 class Place(proto.Message): @@ -64,162 +67,250 @@ class Place(proto.Message): .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: + name (str): + Output only. An ID representing this place which may be used + to look up this place again (a.k.a. the API "resource" name: + places/). id (str): - Required. The unique identifier of a place. + Output only. The unique identifier of a + place. display_name (google.type.localized_text_pb2.LocalizedText): - The localized name of the place, suitable as - a short human-readable description. For example, - "Google Sydney", "Starbucks", "Pyrmont", etc. + Output only. The localized name of the place, + suitable as a short human-readable description. + For example, "Google Sydney", "Starbucks", + "Pyrmont", etc. types (MutableSequence[str]): - A set of type tags for this result. For - example, "political" and "locality". + Output only. A set of type tags for this + result. For example, "political" and "locality". national_phone_number (str): - A human-readable phone number for the place, - in national format. + Output only. A human-readable phone number + for the place, in national format. international_phone_number (str): - A human-readable phone number for the place, - in international format. + Output only. A human-readable phone number + for the place, in international format. formatted_address (str): - A full, human-readable address for this - place. + Output only. A full, human-readable address + for this place. address_components (MutableSequence[google.maps.places_v1.types.Place.AddressComponent]): - Repeated components for each locality level. + Output only. Repeated components for each + locality level. plus_code (google.maps.places_v1.types.Place.PlusCode): - Plus code of the place location lat/long. + Output only. Plus code of the place location + lat/long. location (google.type.latlng_pb2.LatLng): - The position of this place. + Output only. The position of this place. viewport (google.geo.type.types.Viewport): - A viewport suitable for displaying the place - on an average-sized map. + Output only. A viewport suitable for + displaying the place on an average-sized map. rating (float): - A rating between 1.0 and 5.0, based on user - reviews of this place. + Output only. A rating between 1.0 and 5.0, + based on user reviews of this place. google_maps_uri (str): - A URL providing more information about this - place. + Output only. A URL providing more information + about this place. website_uri (str): - The authoritative website for this place, - e.g. a business' homepage. Note that for places - that are part of a chain (e.g. an IKEA store), - this will usually be the website for the - individual store, not the overall chain. - reviews (MutableSequence[google.maps.places_v1.types.Place.Review]): - List of reviews about this place. - opening_hours (google.maps.places_v1.types.Place.OpeningHours): - The regular hours of operation. + Output only. The authoritative website for + this place, e.g. a business' homepage. Note that + for places that are part of a chain (e.g. an + IKEA store), this will usually be the website + for the individual store, not the overall chain. + reviews (MutableSequence[google.maps.places_v1.types.Review]): + Output only. List of reviews about this + place. + regular_opening_hours (google.maps.places_v1.types.Place.OpeningHours): + Output only. The regular hours of operation. utc_offset_minutes (int): - Number of minutes this place's timezone is - currently offset from UTC. This is expressed in - minutes to support timezones that are offset by - fractions of an hour, e.g. X hours and 15 - minutes. + Output only. Number of minutes this place's + timezone is currently offset from UTC. This is + expressed in minutes to support timezones that + are offset by fractions of an hour, e.g. X hours + and 15 minutes. + + This field is a member of `oneof`_ ``_utc_offset_minutes``. + photos (MutableSequence[google.maps.places_v1.types.Photo]): + Output only. Information (including + references) about photos of this place. adr_format_address (str): - The place's address in adr microformat: - http://microformats.org/wiki/adr. + Output only. The place's address in adr + microformat: http://microformats.org/wiki/adr. business_status (google.maps.places_v1.types.Place.BusinessStatus): - The business status for the place. + Output only. The business status for the + place. price_level (google.maps.places_v1.types.PriceLevel): - Price level of the place. + Output only. Price level of the place. attributions (MutableSequence[google.maps.places_v1.types.Place.Attribution]): - A set of data provider that must be shown - with this result. + Output only. A set of data provider that must + be shown with this result. user_rating_count (int): - The total number of reviews (with or without - text) for this place. + Output only. The total number of reviews + (with or without text) for this place. + + This field is a member of `oneof`_ ``_user_rating_count``. icon_mask_base_uri (str): - A truncated URL to an v2 icon mask. User can - access different icon type by appending type - suffix to the end (eg, ".svg" or ".png"). + Output only. A truncated URL to an v2 icon + mask. User can access different icon type by + appending type suffix to the end (eg, ".svg" or + ".png"). icon_background_color (str): - Background color for icon_mask in hex format, e.g. #909CE1. + Output only. Background color for icon_mask in hex format, + e.g. #909CE1. takeout (bool): - Specifies if the business supports takeout. + Output only. Specifies if the business + supports takeout. This field is a member of `oneof`_ ``_takeout``. delivery (bool): - Specifies if the business supports delivery. + Output only. Specifies if the business + supports delivery. This field is a member of `oneof`_ ``_delivery``. dine_in (bool): - Specifies if the business supports indoor or - outdoor seating options. + Output only. Specifies if the business + supports indoor or outdoor seating options. This field is a member of `oneof`_ ``_dine_in``. curbside_pickup (bool): - Specifies if the business supports curbside - pickup. + Output only. Specifies if the business + supports curbside pickup. This field is a member of `oneof`_ ``_curbside_pickup``. - wheelchair_accessible_entrance (bool): - Specifies if the place has an entrance that - is wheelchair-accessible. - - This field is a member of `oneof`_ ``_wheelchair_accessible_entrance``. reservable (bool): - Specifies if the place supports reservations. + Output only. Specifies if the place supports + reservations. This field is a member of `oneof`_ ``_reservable``. serves_breakfast (bool): - Specifies if the place serves breakfast. + Output only. Specifies if the place serves + breakfast. This field is a member of `oneof`_ ``_serves_breakfast``. serves_lunch (bool): - Specifies if the place serves lunch. + Output only. Specifies if the place serves + lunch. This field is a member of `oneof`_ ``_serves_lunch``. serves_dinner (bool): - Specifies if the place serves dinner. + Output only. Specifies if the place serves + dinner. This field is a member of `oneof`_ ``_serves_dinner``. serves_beer (bool): - Specifies if the place serves beer. + Output only. Specifies if the place serves + beer. This field is a member of `oneof`_ ``_serves_beer``. serves_wine (bool): - Specifies if the place serves wine. + Output only. Specifies if the place serves + wine. This field is a member of `oneof`_ ``_serves_wine``. serves_brunch (bool): - Specifies if the place serves brunch. + Output only. Specifies if the place serves + brunch. This field is a member of `oneof`_ ``_serves_brunch``. serves_vegetarian_food (bool): - Specifies if the place serves vegetarian - food. + Output only. Specifies if the place serves + vegetarian food. This field is a member of `oneof`_ ``_serves_vegetarian_food``. current_opening_hours (google.maps.places_v1.types.Place.OpeningHours): - The hours of operation for the next seven days (including - today). The time period starts at midnight on the date of - the request and ends at 11:59 pm six days later. This field - includes the special_days subfield of all hours, set for - dates that have exceptional hours. + Output only. The hours of operation for the next seven days + (including today). The time period starts at midnight on the + date of the request and ends at 11:59 pm six days later. + This field includes the special_days subfield of all hours, + set for dates that have exceptional hours. current_secondary_opening_hours (MutableSequence[google.maps.places_v1.types.Place.OpeningHours]): - Contains an array of entries for the next seven days - including information about secondary hours of a business. - Secondary hours are different from a business's main hours. - For example, a restaurant can specify drive through hours or - delivery hours as its secondary hours. This field populates - the type subfield, which draws from a predefined list of - opening hours types (such as DRIVE_THROUGH, PICKUP, or - TAKEOUT) based on the types of the place. This field - includes the special_days subfield of all hours, set for - dates that have exceptional hours. - secondary_opening_hours (MutableSequence[google.maps.places_v1.types.Place.OpeningHours]): - Contains an array of entries for information about regular - secondary hours of a business. Secondary hours are different - from a business's main hours. For example, a restaurant can - specify drive through hours or delivery hours as its - secondary hours. This field populates the type subfield, - which draws from a predefined list of opening hours types - (such as DRIVE_THROUGH, PICKUP, or TAKEOUT) based on the - types of the place. - editorial_summary (google.maps.places_v1.types.Place.EditorialSummary): - Contains a summary of the place. A summary is - comprised of a textual overview, and also - includes the language code for these if + Output only. Contains an array of entries for the next seven + days including information about secondary hours of a + business. Secondary hours are different from a business's + main hours. For example, a restaurant can specify drive + through hours or delivery hours as its secondary hours. This + field populates the type subfield, which draws from a + predefined list of opening hours types (such as + DRIVE_THROUGH, PICKUP, or TAKEOUT) based on the types of the + place. This field includes the special_days subfield of all + hours, set for dates that have exceptional hours. + regular_secondary_opening_hours (MutableSequence[google.maps.places_v1.types.Place.OpeningHours]): + Output only. Contains an array of entries for information + about regular secondary hours of a business. Secondary hours + are different from a business's main hours. For example, a + restaurant can specify drive through hours or delivery hours + as its secondary hours. This field populates the type + subfield, which draws from a predefined list of opening + hours types (such as DRIVE_THROUGH, PICKUP, or TAKEOUT) + based on the types of the place. + editorial_summary (google.type.localized_text_pb2.LocalizedText): + Output only. Contains a summary of the place. + A summary is comprised of a textual overview, + and also includes the language code for these if applicable. Summary text must be presented as-is and can not be modified or altered. + outdoor_seating (bool): + Output only. Place provides outdoor seating. + + This field is a member of `oneof`_ ``_outdoor_seating``. + live_music (bool): + Output only. Place provides live music. + + This field is a member of `oneof`_ ``_live_music``. + menu_for_children (bool): + Output only. Place has a children's menu. + + This field is a member of `oneof`_ ``_menu_for_children``. + serves_cocktails (bool): + Output only. Place serves cocktails. + + This field is a member of `oneof`_ ``_serves_cocktails``. + serves_dessert (bool): + Output only. Place serves dessert. + + This field is a member of `oneof`_ ``_serves_dessert``. + serves_coffee (bool): + Output only. Place serves coffee. + + This field is a member of `oneof`_ ``_serves_coffee``. + good_for_children (bool): + Output only. Place is good for children. + + This field is a member of `oneof`_ ``_good_for_children``. + allows_dogs (bool): + Output only. Place allows dogs. + + This field is a member of `oneof`_ ``_allows_dogs``. + restroom (bool): + Output only. Place has restroom. + + This field is a member of `oneof`_ ``_restroom``. + good_for_groups (bool): + Output only. Place accommodates groups. + + This field is a member of `oneof`_ ``_good_for_groups``. + good_for_watching_sports (bool): + Output only. Place is suitable for watching + sports. + + This field is a member of `oneof`_ ``_good_for_watching_sports``. + payment_options (google.maps.places_v1.types.Place.PaymentOptions): + + parking_options (google.maps.places_v1.types.Place.ParkingOptions): + Output only. Options of parking provided by + the place. + sub_destinations (MutableSequence[google.maps.places_v1.types.Place.SubDestination]): + Output only. A list of sub destinations + related to the place. + accessibility_options (google.maps.places_v1.types.Place.AccessibilityOptions): + Output only. Information about the + accessibility options a place offers. + + This field is a member of `oneof`_ ``_accessibility_options``. + fuel_options (google.maps.places_v1.types.FuelOptions): + Output only. The most recent information + about fuel options in a gas station. This + information is updated regularly. + ev_charge_options (google.maps.places_v1.types.EVChargeOptions): + Output only. Information of ev charging + options. """ class BusinessStatus(proto.Enum): @@ -247,19 +338,19 @@ class AddressComponent(proto.Message): Attributes: long_text (str): - The full text description or name of the address component. - For example, an address component for the country Australia - may have a long_name of "Australia". + Output only. The full text description or name of the + address component. For example, an address component for the + country Australia may have a long_name of "Australia". short_text (str): - An abbreviated textual name for the address component, if - available. For example, an address component for the country - of Australia may have a short_name of "AU". + Output only. An abbreviated textual name for the address + component, if available. For example, an address component + for the country of Australia may have a short_name of "AU". types (MutableSequence[str]): - An array indicating the type(s) of the - address component. + Output only. An array indicating the type(s) + of the address component. language_code (str): - The language used to format this components, - in CLDR notation. + Output only. The language used to format this + components, in CLDR notation. """ long_text: str = proto.Field( @@ -287,13 +378,15 @@ class PlusCode(proto.Message): Attributes: global_code (str): - Place's global (full) code, such as ``9FWM33GV+HQ``, - representing an 1/8000 by 1/8000 degree area (~14 by 14 - meters). + Output only. Place's global (full) code, such + as "9FWM33GV+HQ", representing an 1/8000 by + 1/8000 degree area (~14 by 14 meters). compound_code (str): - Place's compound code, such as ``33GV+HQ, Ramberg, Norway``, - containing the suffix of the global code and replacing the - prefix with a formatted name of a reference entity. + Output only. Place's compound code, such as + "33GV+HQ, Ramberg, Norway", containing the + suffix of the global code and replacing the + prefix with a formatted name of a reference + entity. """ global_code: str = proto.Field( @@ -305,125 +398,51 @@ class PlusCode(proto.Message): number=2, ) - class Review(proto.Message): - r"""Information about a review of the place. - - Attributes: - publish_time (google.protobuf.timestamp_pb2.Timestamp): - Timestamp for the review, expressed in - seconds since epoch. - relative_publish_time_description (str): - A string of formatted recent time, expressing - the review time relative to the current time in - a form appropriate for the language and country. - text (google.type.localized_text_pb2.LocalizedText): - The localized text of the review. - author (str): - The name of the review author. - author_uri (str): - A link to the review author's profile. - author_photo_uri (str): - The author's profile photo. - rating (float): - A whole number between 1.0 and 5.0, a.k.a. - the number of stars. - original_language_code (str): - A BCP-47 language code indicating the original language of - the review. If the review has been translated, then - original_language != language. This field contains the main - language tag only, and not the secondary tag indicating - country or region. For example, all the English reviews are - tagged as 'en', and not 'en-AU' or 'en-UK' and so on.This - field is empty if there is only a rating with no review - text. - translated (bool): - A boolean value indicating if the review was - translated from the original language it was - written in. If a review has been translated, - corresponding to a value of true, Google - recommends that you indicate this to your users. - For example, you can add the following string, - “Translated by Google”, to the review. - """ - - publish_time: timestamp_pb2.Timestamp = proto.Field( - proto.MESSAGE, - number=1, - message=timestamp_pb2.Timestamp, - ) - relative_publish_time_description: str = proto.Field( - proto.STRING, - number=2, - ) - text: localized_text_pb2.LocalizedText = proto.Field( - proto.MESSAGE, - number=9, - message=localized_text_pb2.LocalizedText, - ) - author: str = proto.Field( - proto.STRING, - number=4, - ) - author_uri: str = proto.Field( - proto.STRING, - number=5, - ) - author_photo_uri: str = proto.Field( - proto.STRING, - number=6, - ) - rating: float = proto.Field( - proto.DOUBLE, - number=7, - ) - original_language_code: str = proto.Field( - proto.STRING, - number=10, - ) - translated: bool = proto.Field( - proto.BOOL, - number=11, - ) - class OpeningHours(proto.Message): r"""Information about business hour of the place. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: open_now (bool): - Is this place open right now? Always present - unless we lack time-of-day or timezone data for - these opening hours. - periods (MutableSequence[google.maps.places_v1.types.Place.OpeningHours.OpeningHoursPeriod]): - The periods that this place is open during - the week. The periods are in chronological - order, starting with Sunday in the place-local - timezone. An empty (but not absent) value - indicates a place that is never open, e.g. + Output only. Is this place open right now? + Always present unless we lack time-of-day or + timezone data for these opening hours. + + This field is a member of `oneof`_ ``_open_now``. + periods (MutableSequence[google.maps.places_v1.types.Place.OpeningHours.Period]): + Output only. The periods that this place is + open during the week. The periods are in + chronological order, starting with Sunday in the + place-local timezone. An empty (but not absent) + value indicates a place that is never open, e.g. because it is closed temporarily for renovations. weekday_descriptions (MutableSequence[str]): - Localized strings describing the opening - hours of this place, one string for each day of - the week. Will be empty if the hours are + Output only. Localized strings describing the + opening hours of this place, one string for each + day of the week. Will be empty if the hours are unknown or could not be converted to localized - text. Example: "Sun: 18:00–06:00". - secondary_hour_type (google.maps.places_v1.types.Place.OpeningHours.SecondaryHourType): - A type string used to identify the type of - secondary hours. + text. Example: "Sun: + + 18:00–06:00". + secondary_hours_type (google.maps.places_v1.types.Place.OpeningHours.SecondaryHoursType): + Output only. A type string used to identify + the type of secondary hours. special_days (MutableSequence[google.maps.places_v1.types.Place.OpeningHours.SpecialDay]): - Structured information for special days that fall within the - period that the returned opening hours cover. Special days - are days that could impact the business hours of a place, - e.g. Christmas day. Set for current_opening_hours and - current_secondary_opening_hours if there are exceptional - hours. + Output only. Structured information for special days that + fall within the period that the returned opening hours + cover. Special days are days that could impact the business + hours of a place, e.g. Christmas day. Set for + current_opening_hours and current_secondary_opening_hours if + there are exceptional hours. """ - class SecondaryHourType(proto.Enum): + class SecondaryHoursType(proto.Enum): r"""A type used to identify the type of secondary hours. Values: - SECONDARY_HOUR_TYPE_UNSPECIFIED (0): + SECONDARY_HOURS_TYPE_UNSPECIFIED (0): Default value when secondary hour type is not specified. DRIVE_THROUGH (1): @@ -454,7 +473,7 @@ class SecondaryHourType(proto.Enum): ONLINE_SERVICE_HOURS (13): The online service hours. """ - SECONDARY_HOUR_TYPE_UNSPECIFIED = 0 + SECONDARY_HOURS_TYPE_UNSPECIFIED = 0 DRIVE_THROUGH = 1 HAPPY_HOUR = 2 DELIVERY = 3 @@ -469,46 +488,49 @@ class SecondaryHourType(proto.Enum): SENIOR_HOURS = 12 ONLINE_SERVICE_HOURS = 13 - class OpeningHoursPeriod(proto.Message): + class Period(proto.Message): r"""A period the place remains in open_now status. Attributes: - open_ (google.maps.places_v1.types.Place.OpeningHours.OpeningHoursPeriod.OpeningHoursPoint): - The time that the place starts to be open. - close (google.maps.places_v1.types.Place.OpeningHours.OpeningHoursPeriod.OpeningHoursPoint): - The time that the place starts to be closed. + open_ (google.maps.places_v1.types.Place.OpeningHours.Period.Point): + Output only. The time that the place starts + to be open. + close (google.maps.places_v1.types.Place.OpeningHours.Period.Point): + Output only. The time that the place starts + to be closed. """ - class OpeningHoursPoint(proto.Message): + class Point(proto.Message): r"""Status changing points. .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: day (int): - A day of the week, as an integer in the range - 0-6. 0 is Sunday, 1 is Monday, etc. + Output only. A day of the week, as an integer + in the range 0-6. 0 is Sunday, 1 is Monday, + etc. This field is a member of `oneof`_ ``_day``. hour (int): - The hour in 2 digits. Ranges from 00 to 23. + Output only. The hour in 2 digits. Ranges + from 00 to 23. This field is a member of `oneof`_ ``_hour``. minute (int): - The minute in 2 digits. Ranges from 00 to 59. + Output only. The minute in 2 digits. Ranges + from 00 to 59. This field is a member of `oneof`_ ``_minute``. - date_deprecated (str): - Date of the endpoint expressed in ``RFC3339`` format in the - local timezone for the place. For example 2010-12-31. date (google.type.date_pb2.Date): - Date in the local timezone for the place. + Output only. Date in the local timezone for + the place. truncated (bool): - Whether or not this endpoint was truncated. Truncation - occurs when the real hours are outside the times we are - willing to return hours between, so we truncate the hours - back to these boundaries. This ensures that at most - ``24 * 7`` hours from midnight of the day of the request are + Output only. Whether or not this endpoint was truncated. + Truncation occurs when the real hours are outside the times + we are willing to return hours between, so we truncate the + hours back to these boundaries. This ensures that at most 24 + \* 7 hours from midnight of the day of the request are returned. """ @@ -527,10 +549,6 @@ class OpeningHoursPoint(proto.Message): number=3, optional=True, ) - date_deprecated: str = proto.Field( - proto.STRING, - number=4, - ) date: date_pb2.Date = proto.Field( proto.MESSAGE, number=6, @@ -541,19 +559,15 @@ class OpeningHoursPoint(proto.Message): number=5, ) - open_: "Place.OpeningHours.OpeningHoursPeriod.OpeningHoursPoint" = ( - proto.Field( - proto.MESSAGE, - number=1, - message="Place.OpeningHours.OpeningHoursPeriod.OpeningHoursPoint", - ) + open_: "Place.OpeningHours.Period.Point" = proto.Field( + proto.MESSAGE, + number=1, + message="Place.OpeningHours.Period.Point", ) - close: "Place.OpeningHours.OpeningHoursPeriod.OpeningHoursPoint" = ( - proto.Field( - proto.MESSAGE, - number=2, - message="Place.OpeningHours.OpeningHoursPeriod.OpeningHoursPoint", - ) + close: "Place.OpeningHours.Period.Point" = proto.Field( + proto.MESSAGE, + number=2, + message="Place.OpeningHours.Period.Point", ) class SpecialDay(proto.Message): @@ -564,7 +578,7 @@ class SpecialDay(proto.Message): Attributes: date (google.type.date_pb2.Date): - The date of this special day. + Output only. The date of this special day. """ date: date_pb2.Date = proto.Field( @@ -576,22 +590,21 @@ class SpecialDay(proto.Message): open_now: bool = proto.Field( proto.BOOL, number=1, + optional=True, ) - periods: MutableSequence[ - "Place.OpeningHours.OpeningHoursPeriod" - ] = proto.RepeatedField( + periods: MutableSequence["Place.OpeningHours.Period"] = proto.RepeatedField( proto.MESSAGE, number=2, - message="Place.OpeningHours.OpeningHoursPeriod", + message="Place.OpeningHours.Period", ) weekday_descriptions: MutableSequence[str] = proto.RepeatedField( proto.STRING, number=3, ) - secondary_hour_type: "Place.OpeningHours.SecondaryHourType" = proto.Field( + secondary_hours_type: "Place.OpeningHours.SecondaryHoursType" = proto.Field( proto.ENUM, number=4, - enum="Place.OpeningHours.SecondaryHourType", + enum="Place.OpeningHours.SecondaryHoursType", ) special_days: MutableSequence[ "Place.OpeningHours.SpecialDay" @@ -606,9 +619,11 @@ class Attribution(proto.Message): Attributes: provider (str): - Name of the Place's data provider. + Output only. Name of the Place's data + provider. provider_uri (str): - URI to the Place's data provider. + Output only. URI to the Place's data + provider. """ provider: str = proto.Field( @@ -620,23 +635,170 @@ class Attribution(proto.Message): number=2, ) - class EditorialSummary(proto.Message): - r"""Contains a summary of the place. + class PaymentOptions(proto.Message): + r"""Payment options the place accepts. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: - overview (google.type.localized_text_pb2.LocalizedText): - A summary is comprised of a textual overview, - and also includes the language code for these if - applicable. Summary text must be presented as-is - and can not be modified or altered. + accepts_credit_cards (bool): + Place accepts credit cards as payment. + + This field is a member of `oneof`_ ``_accepts_credit_cards``. + accepts_debit_cards (bool): + Place accepts debit cards as payment. + + This field is a member of `oneof`_ ``_accepts_debit_cards``. + accepts_cash_only (bool): + Place accepts cash only as payment. Places + with this attribute may still accept other + payment methods. + + This field is a member of `oneof`_ ``_accepts_cash_only``. + accepts_nfc (bool): + Place accepts NFC payments. + + This field is a member of `oneof`_ ``_accepts_nfc``. """ - overview: localized_text_pb2.LocalizedText = proto.Field( - proto.MESSAGE, + accepts_credit_cards: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + accepts_debit_cards: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + accepts_cash_only: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + accepts_nfc: bool = proto.Field( + proto.BOOL, + number=4, + optional=True, + ) + + class ParkingOptions(proto.Message): + r"""Information about parking options for the place. A parking + lot could support more than one option at the same time. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + free_parking_lot (bool): + Place offers free parking lots. + + This field is a member of `oneof`_ ``_free_parking_lot``. + paid_parking_lot (bool): + Place offers paid parking lots. + + This field is a member of `oneof`_ ``_paid_parking_lot``. + free_street_parking (bool): + Place offers free street parking. + + This field is a member of `oneof`_ ``_free_street_parking``. + paid_street_parking (bool): + Place offers paid street parking. + + This field is a member of `oneof`_ ``_paid_street_parking``. + valet_parking (bool): + Place offers valet parking. + + This field is a member of `oneof`_ ``_valet_parking``. + free_garage_parking (bool): + Place offers free garage parking. + + This field is a member of `oneof`_ ``_free_garage_parking``. + paid_garage_parking (bool): + Place offers paid garage parking. + + This field is a member of `oneof`_ ``_paid_garage_parking``. + """ + + free_parking_lot: bool = proto.Field( + proto.BOOL, number=1, - message=localized_text_pb2.LocalizedText, + optional=True, ) + paid_parking_lot: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + free_street_parking: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + paid_street_parking: bool = proto.Field( + proto.BOOL, + number=4, + optional=True, + ) + valet_parking: bool = proto.Field( + proto.BOOL, + number=5, + optional=True, + ) + free_garage_parking: bool = proto.Field( + proto.BOOL, + number=6, + optional=True, + ) + paid_garage_parking: bool = proto.Field( + proto.BOOL, + number=7, + optional=True, + ) + + class SubDestination(proto.Message): + r"""Place resource name and id of sub destinations that relate to + the place. For example, different terminals are different + destinations of an airport. + Attributes: + name (str): + The resource name of the sub destination. + id (str): + The place id of the sub destination. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + id: str = proto.Field( + proto.STRING, + number=2, + ) + + class AccessibilityOptions(proto.Message): + r"""Information about the accessibility options a place offers. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + wheelchair_accessible_entrance (bool): + Places has wheelchair accessible entrance. + + This field is a member of `oneof`_ ``_wheelchair_accessible_entrance``. + """ + + wheelchair_accessible_entrance: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + + name: str = proto.Field( + proto.STRING, + number=1, + ) id: str = proto.Field( proto.STRING, number=2, @@ -694,12 +856,12 @@ class EditorialSummary(proto.Message): proto.STRING, number=16, ) - reviews: MutableSequence[Review] = proto.RepeatedField( + reviews: MutableSequence[review.Review] = proto.RepeatedField( proto.MESSAGE, - number=20, - message=Review, + number=53, + message=review.Review, ) - opening_hours: OpeningHours = proto.Field( + regular_opening_hours: OpeningHours = proto.Field( proto.MESSAGE, number=21, message=OpeningHours, @@ -707,6 +869,12 @@ class EditorialSummary(proto.Message): utc_offset_minutes: int = proto.Field( proto.INT32, number=22, + optional=True, + ) + photos: MutableSequence[photo.Photo] = proto.RepeatedField( + proto.MESSAGE, + number=54, + message=photo.Photo, ) adr_format_address: str = proto.Field( proto.STRING, @@ -730,6 +898,7 @@ class EditorialSummary(proto.Message): user_rating_count: int = proto.Field( proto.INT32, number=28, + optional=True, ) icon_mask_base_uri: str = proto.Field( proto.STRING, @@ -759,11 +928,6 @@ class EditorialSummary(proto.Message): number=36, optional=True, ) - wheelchair_accessible_entrance: bool = proto.Field( - proto.BOOL, - number=37, - optional=True, - ) reservable: bool = proto.Field( proto.BOOL, number=38, @@ -816,15 +980,103 @@ class EditorialSummary(proto.Message): number=47, message=OpeningHours, ) - secondary_opening_hours: MutableSequence[OpeningHours] = proto.RepeatedField( + regular_secondary_opening_hours: MutableSequence[ + OpeningHours + ] = proto.RepeatedField( proto.MESSAGE, number=49, message=OpeningHours, ) - editorial_summary: EditorialSummary = proto.Field( + editorial_summary: localized_text_pb2.LocalizedText = proto.Field( + proto.MESSAGE, + number=52, + message=localized_text_pb2.LocalizedText, + ) + outdoor_seating: bool = proto.Field( + proto.BOOL, + number=55, + optional=True, + ) + live_music: bool = proto.Field( + proto.BOOL, + number=56, + optional=True, + ) + menu_for_children: bool = proto.Field( + proto.BOOL, + number=57, + optional=True, + ) + serves_cocktails: bool = proto.Field( + proto.BOOL, + number=58, + optional=True, + ) + serves_dessert: bool = proto.Field( + proto.BOOL, + number=59, + optional=True, + ) + serves_coffee: bool = proto.Field( + proto.BOOL, + number=60, + optional=True, + ) + good_for_children: bool = proto.Field( + proto.BOOL, + number=62, + optional=True, + ) + allows_dogs: bool = proto.Field( + proto.BOOL, + number=63, + optional=True, + ) + restroom: bool = proto.Field( + proto.BOOL, + number=64, + optional=True, + ) + good_for_groups: bool = proto.Field( + proto.BOOL, + number=65, + optional=True, + ) + good_for_watching_sports: bool = proto.Field( + proto.BOOL, + number=66, + optional=True, + ) + payment_options: PaymentOptions = proto.Field( + proto.MESSAGE, + number=67, + message=PaymentOptions, + ) + parking_options: ParkingOptions = proto.Field( + proto.MESSAGE, + number=70, + message=ParkingOptions, + ) + sub_destinations: MutableSequence[SubDestination] = proto.RepeatedField( + proto.MESSAGE, + number=71, + message=SubDestination, + ) + accessibility_options: AccessibilityOptions = proto.Field( + proto.MESSAGE, + number=72, + optional=True, + message=AccessibilityOptions, + ) + fuel_options: gmp_fuel_options.FuelOptions = proto.Field( + proto.MESSAGE, + number=78, + message=gmp_fuel_options.FuelOptions, + ) + ev_charge_options: ev_charging.EVChargeOptions = proto.Field( proto.MESSAGE, - number=48, - message=EditorialSummary, + number=79, + message=ev_charging.EVChargeOptions, ) diff --git a/packages/google-maps-places/google/maps/places_v1/types/places_service.py b/packages/google-maps-places/google/maps/places_v1/types/places_service.py index abe636c48796..faec30184cd1 100644 --- a/packages/google-maps-places/google/maps/places_v1/types/places_service.py +++ b/packages/google-maps-places/google/maps/places_v1/types/places_service.py @@ -25,49 +25,218 @@ __protobuf__ = proto.module( package="google.maps.places.v1", manifest={ - "Int32Range", + "SearchNearbyRequest", + "SearchNearbyResponse", "SearchTextRequest", "SearchTextResponse", + "GetPhotoMediaRequest", + "PhotoMedia", + "GetPlaceRequest", }, ) -class Int32Range(proto.Message): - r"""int 32 range. Both min and max are optional. If only min is - set, then the range only has a lower bound. If only max is set, - then range only has an upper bound. At least one of min and max - must be set. Values are inclusive. +class SearchNearbyRequest(proto.Message): + r"""Request proto for Search Nearby. + Attributes: + language_code (str): + Place details will be displayed with the + preferred language if available. If the language + code is unspecified or unrecognized, place + details of any language may be returned, with a + preference for English if such details exist. - .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Current list of supported languages: - Attributes: - min_ (int): - Lower bound. If unset, behavior is documented - on the range field. + https://developers.google.com/maps/faq#languagesupport. + region_code (str): + The Unicode country/region code (CLDR) of the location where + the request is coming from. This parameter is used to + display the place details, like region-specific place name, + if available. The parameter can affect results based on + applicable law. - This field is a member of `oneof`_ ``_min``. - max_ (int): - Upper bound. If unset, behavior is documented - on the range field. + For more information, see + http://www.unicode.org/reports/tr35/#unicode_region_subtag. + + Note that 3-digit region codes are not currently supported. + included_types (MutableSequence[str]): + Included Place type (eg, "restaurant" or "gas_station") from + https://developers.google.com/places/supported_types. + + If there are any conflicting types, i.e. a type appears in + both included_types and excluded_types, an INVALID_ARGUMENT + error is returned. + + If a Place type is specified with multiple type + restrictions, only places that satisfy all of the + restrictions are returned. For example, if we have + {included_types = ["restaurant"], excluded_primary_types = + ["restaurant"]}, the returned places are POIs that provide + "restaurant" related services but do not operate primarily + as "restaurants". + excluded_types (MutableSequence[str]): + Excluded Place type (eg, "restaurant" or "gas_station") from + https://developers.google.com/places/supported_types. + + If the client provides both included_types (e.g. restaurant) + and excluded_types (e.g. cafe), then the response should + include places that are restaurant but not cafe. The + response includes places that match at least one of the + included_types and none of the excluded_types. + + If there are any conflicting types, i.e. a type appears in + both included_types and excluded_types, an INVALID_ARGUMENT + error is returned. + + If a Place type is specified with multiple type + restrictions, only places that satisfy all of the + restrictions are returned. For example, if we have + {included_types = ["restaurant"], excluded_primary_types = + ["restaurant"]}, the returned places are POIs that provide + "restaurant" related services but do not operate primarily + as "restaurants". + included_primary_types (MutableSequence[str]): + Included primary Place type (e.g. "restaurant" or + "gas_station") from + https://developers.google.com/places/supported_types. + + If there are any conflicting primary types, i.e. a type + appears in both included_primary_types and + excluded_primary_types, an INVALID_ARGUMENT error is + returned. + + If a Place type is specified with multiple type + restrictions, only places that satisfy all of the + restrictions are returned. For example, if we have + {included_types = ["restaurant"], excluded_primary_types = + ["restaurant"]}, the returned places are POIs that provide + "restaurant" related services but do not operate primarily + as "restaurants". + excluded_primary_types (MutableSequence[str]): + Excluded primary Place type (e.g. "restaurant" or + "gas_station") from + https://developers.google.com/places/supported_types. + + If there are any conflicting primary types, i.e. a type + appears in both included_primary_types and + excluded_primary_types, an INVALID_ARGUMENT error is + returned. - This field is a member of `oneof`_ ``_max``. + If a Place type is specified with multiple type + restrictions, only places that satisfy all of the + restrictions are returned. For example, if we have + {included_types = ["restaurant"], excluded_primary_types = + ["restaurant"]}, the returned places are POIs that provide + "restaurant" related services but do not operate primarily + as "restaurants". + max_result_count (int): + Maximum number of results to return. It must be between 1 + and 20, inclusively. If the number is unset, it falls back + to the upper limit. If the number is set to negative or + exceeds the upper limit, an INVALID_ARGUMENT error is + returned. + location_restriction (google.maps.places_v1.types.SearchNearbyRequest.LocationRestriction): + Required. The region to search. + rank_preference (google.maps.places_v1.types.SearchNearbyRequest.RankPreference): + How results will be ranked in the response. """ - min_: int = proto.Field( - proto.INT32, + class RankPreference(proto.Enum): + r"""How results will be ranked in the response. + + Values: + RANK_PREFERENCE_UNSPECIFIED (0): + RankPreference value not set. Will use rank + by POPULARITY by default. + DISTANCE (1): + Ranks results by distance. + POPULARITY (2): + Ranks results by popularity. + """ + RANK_PREFERENCE_UNSPECIFIED = 0 + DISTANCE = 1 + POPULARITY = 2 + + class LocationRestriction(proto.Message): + r"""The region to search. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + circle (google.maps.places_v1.types.Circle): + A circle defined by center point and radius. + + This field is a member of `oneof`_ ``type``. + """ + + circle: geometry.Circle = proto.Field( + proto.MESSAGE, + number=2, + oneof="type", + message=geometry.Circle, + ) + + language_code: str = proto.Field( + proto.STRING, number=1, - optional=True, ) - max_: int = proto.Field( - proto.INT32, + region_code: str = proto.Field( + proto.STRING, number=2, - optional=True, + ) + included_types: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + excluded_types: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=4, + ) + included_primary_types: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=5, + ) + excluded_primary_types: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=6, + ) + max_result_count: int = proto.Field( + proto.INT32, + number=7, + ) + location_restriction: LocationRestriction = proto.Field( + proto.MESSAGE, + number=8, + message=LocationRestriction, + ) + rank_preference: RankPreference = proto.Field( + proto.ENUM, + number=9, + enum=RankPreference, + ) + + +class SearchNearbyResponse(proto.Message): + r"""Response proto for Search Nearby. + + Attributes: + places (MutableSequence[google.maps.places_v1.types.Place]): + A list of interesting places that meets + user's requirements like places types, number of + places and specific location restriction. + """ + + places: MutableSequence[place.Place] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=place.Place, ) class SearchTextRequest(proto.Message): - r"""Request data structure for SearchText. + r"""Request proto for SearchText. Attributes: text_query (str): @@ -84,8 +253,10 @@ class SearchTextRequest(proto.Message): https://developers.google.com/maps/faq#languagesupport. region_code (str): The Unicode country/region code (CLDR) of the location where - the request is coming from. It is used to display the place - details, like region-specific place name, if available. + the request is coming from. This parameter is used to + display the place details, like region-specific place name, + if available. The parameter can affect results based on + applicable law. For more information, see http://www.unicode.org/reports/tr35/#unicode_region_subtag. @@ -93,13 +264,6 @@ class SearchTextRequest(proto.Message): Note that 3-digit region codes are not currently supported. rank_preference (google.maps.places_v1.types.SearchTextRequest.RankPreference): How results will be ranked in the response. - location (google.maps.places_v1.types.SearchTextRequest.Location): - The region to search. Setting location would usually yields - better results. Recommended to set. This location serves as - a bias unless strict_restriction is set to true, which turns - the location to a strict restriction. - - Deprecated. Use LocationRestriction or LocationBias instead. included_type (str): The requested place type. Full list of types supported: https://developers.google.com/places/supported_types. Only @@ -108,22 +272,14 @@ class SearchTextRequest(proto.Message): Used to restrict the search to places that are open at a specific time. open_now marks if a business is currently open. - price_range (google.maps.places_v1.types.Int32Range): - [Deprecated!]Used to restrict the search to places that are - within a certain price range. This is on a scale of 0 to 4. - Set a minimum of 0 or set a maximum of 4 has no effect on - the search results. Min price is default to 0 and max price - is default to 4. Default value will be used if either min or - max is unset. min_rating (float): Filter out results whose average user rating is strictly less than this limit. A valid value must be an float between - 0 and 5 (inclusively) at a 0.5 cadence i.e. - ``[0, 0.5, 1.0, ... , 5.0]`` inclusively. This is to keep - parity with LocalRefinement_UserRating. The input rating - will round up to the nearest 0.5(ceiling). For instance, a - rating of 0.6 will eliminate all results with a less than - 1.0 rating. + 0 and 5 (inclusively) at a 0.5 cadence i.e. [0, 0.5, 1.0, + ... , 5.0] inclusively. This is to keep parity with + LocalRefinement_UserRating. The input rating will round up + to the nearest 0.5(ceiling). For instance, a rating of 0.6 + will eliminate all results with a less than 1.0 rating. max_result_count (int): Maximum number of results to return. It must be between 1 and 20, inclusively. If the number is unset, it falls back @@ -167,38 +323,6 @@ class RankPreference(proto.Enum): DISTANCE = 1 RELEVANCE = 2 - class Location(proto.Message): - r"""The region to search. - - Deprecated. Use LocationRestriction or LocationBias instead. - - - .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields - - Attributes: - rectangle (google.geo.type.types.Viewport): - A rectangle box defined by northeast and - southwest corner. - - This field is a member of `oneof`_ ``type``. - strict_restriction (bool): - Make location field a strict restriction and - filter out POIs outside of the given location. - If location type field is unset this field will - have no effect. - """ - - rectangle: viewport.Viewport = proto.Field( - proto.MESSAGE, - number=1, - oneof="type", - message=viewport.Viewport, - ) - strict_restriction: bool = proto.Field( - proto.BOOL, - number=2, - ) - class LocationBias(proto.Message): r"""The region to search. This location serves as a bias which means results around given location might be returned. @@ -274,11 +398,6 @@ class LocationRestriction(proto.Message): number=4, enum=RankPreference, ) - location: Location = proto.Field( - proto.MESSAGE, - number=5, - message=Location, - ) included_type: str = proto.Field( proto.STRING, number=6, @@ -287,11 +406,6 @@ class LocationRestriction(proto.Message): proto.BOOL, number=7, ) - price_range: "Int32Range" = proto.Field( - proto.MESSAGE, - number=8, - message="Int32Range", - ) min_rating: float = proto.Field( proto.DOUBLE, number=9, @@ -337,4 +451,132 @@ class SearchTextResponse(proto.Message): ) +class GetPhotoMediaRequest(proto.Message): + r"""Request for fetching a photo of a place using a photo + resource name. + + Attributes: + name (str): + Required. The resource name of a photo. It is returned in + Place's photos.name field. Format: + places//photos//media. + max_width_px (int): + Optional. Specifies the maximum desired width, in pixels, of + the image. If the image is smaller than the values + specified, the original image will be returned. If the image + is larger in either dimension, it will be scaled to match + the smaller of the two dimensions, restricted to its + original aspect ratio. Both the max_height_px and + max_width_px properties accept an integer between 1 and + 4800, inclusively. If the value is not within the allowed + range, an INVALID_ARGUMENT error will be returned. + + At least one of max_height_px or max_width_px needs to be + specified. If neither max_height_px nor max_width_px is + specified, an INVALID_ARGUMENT error will be returned. + max_height_px (int): + Optional. Specifies the maximum desired height, in pixels, + of the image. If the image is smaller than the values + specified, the original image will be returned. If the image + is larger in either dimension, it will be scaled to match + the smaller of the two dimensions, restricted to its + original aspect ratio. Both the max_height_px and + max_width_px properties accept an integer between 1 and + 4800, inclusively. If the value is not within the allowed + range, an INVALID_ARGUMENT error will be returned. + + At least one of max_height_px or max_width_px needs to be + specified. If neither max_height_px nor max_width_px is + specified, an INVALID_ARGUMENT error will be returned. + skip_http_redirect (bool): + Optional. If set, skip the default HTTP + redirect behavior and render a text format (for + example, in JSON format for HTTP use case) + response. If not set, an HTTP redirect will be + issued to redirect the call to the image midea. + This option is ignored for non-HTTP requests. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + max_width_px: int = proto.Field( + proto.INT32, + number=2, + ) + max_height_px: int = proto.Field( + proto.INT32, + number=3, + ) + skip_http_redirect: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class PhotoMedia(proto.Message): + r"""A photo media from Places API. + + Attributes: + name (str): + The resource name of a photo. It is returned in Place's + photos.name field. Format: + places//photos//media. + photo_uri (str): + A short-lived uri that can be used to render + the photo. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + photo_uri: str = proto.Field( + proto.STRING, + number=2, + ) + + +class GetPlaceRequest(proto.Message): + r"""Request for fetching a Place with a place id (in a name) + string. + + Attributes: + name (str): + Required. A place_id returned in a Place (with "places/" + prefix), or equivalently the name in the same Place. Format: + places/. + language_code (str): + Optional. Place details will be displayed + with the preferred language if available. + + Current list of supported languages: + + https://developers.google.com/maps/faq#languagesupport. + region_code (str): + Optional. The Unicode country/region code (CLDR) of the + location where the request is coming from. This parameter is + used to display the place details, like region-specific + place name, if available. The parameter can affect results + based on applicable law. For more information, see + http://www.unicode.org/reports/tr35/#unicode_region_subtag. + + Note that 3-digit region codes are not currently supported. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + language_code: str = proto.Field( + proto.STRING, + number=2, + ) + region_code: str = proto.Field( + proto.STRING, + number=3, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-maps-places/google/maps/places_v1/types/review.py b/packages/google-maps-places/google/maps/places_v1/types/review.py new file mode 100644 index 000000000000..b5df7ae538f2 --- /dev/null +++ b/packages/google-maps-places/google/maps/places_v1/types/review.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +from google.protobuf import timestamp_pb2 # type: ignore +from google.type import localized_text_pb2 # type: ignore +import proto # type: ignore + +from google.maps.places_v1.types import attribution + +__protobuf__ = proto.module( + package="google.maps.places.v1", + manifest={ + "Review", + }, +) + + +class Review(proto.Message): + r"""Information about a review of a place. + + Attributes: + name (str): + Output only. A reference representing this place review + which may be used to look up this place review again (a.k.a. + the API "resource" name: + places/{place_id}/reviews/{review}). + relative_publish_time_description (str): + Output only. A string of formatted recent + time, expressing the review time relative to the + current time in a form appropriate for the + language and country. + text (google.type.localized_text_pb2.LocalizedText): + Output only. The localized text of the + review. + original_text (google.type.localized_text_pb2.LocalizedText): + Output only. The review text in its original + language. + rating (float): + Output only. A number between 1.0 and 5.0, + a.k.a. the number of stars. + author_attribution (google.maps.places_v1.types.AuthorAttribution): + Output only. This review's author. + publish_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. Timestamp for the review. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + relative_publish_time_description: str = proto.Field( + proto.STRING, + number=2, + ) + text: localized_text_pb2.LocalizedText = proto.Field( + proto.MESSAGE, + number=9, + message=localized_text_pb2.LocalizedText, + ) + original_text: localized_text_pb2.LocalizedText = proto.Field( + proto.MESSAGE, + number=12, + message=localized_text_pb2.LocalizedText, + ) + rating: float = proto.Field( + proto.DOUBLE, + number=7, + ) + author_attribution: attribution.AuthorAttribution = proto.Field( + proto.MESSAGE, + number=13, + message=attribution.AuthorAttribution, + ) + publish_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=14, + message=timestamp_pb2.Timestamp, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-maps-places/noxfile.py b/packages/google-maps-places/noxfile.py index 9a2acd8b6787..be54712bfa8f 100644 --- a/packages/google-maps-places/noxfile.py +++ b/packages/google-maps-places/noxfile.py @@ -46,7 +46,7 @@ UNIT_TEST_EXTRAS = [] UNIT_TEST_EXTRAS_BY_PYTHON = {} -SYSTEM_TEST_PYTHON_VERSIONS = [] +SYSTEM_TEST_PYTHON_VERSIONS = ["3.8", "3.9", "3.10", "3.11"] SYSTEM_TEST_STANDARD_DEPENDENCIES = [ "mock", "pytest", @@ -405,24 +405,3 @@ def prerelease_deps(session): session.run("python", "-c", "import google.auth; print(google.auth.__version__)") session.run("py.test", "tests/unit") - - system_test_path = os.path.join("tests", "system.py") - system_test_folder_path = os.path.join("tests", "system") - - # Only run system tests if found. - if os.path.exists(system_test_path): - session.run( - "py.test", - "--verbose", - f"--junitxml=system_{session.python}_sponge_log.xml", - system_test_path, - *session.posargs, - ) - if os.path.exists(system_test_folder_path): - session.run( - "py.test", - "--verbose", - f"--junitxml=system_{session.python}_sponge_log.xml", - system_test_folder_path, - *session.posargs, - ) diff --git a/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_photo_media_async.py b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_photo_media_async.py new file mode 100644 index 000000000000..9299db172a17 --- /dev/null +++ b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_photo_media_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetPhotoMedia +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-maps-places + + +# [START places_v1_generated_Places_GetPhotoMedia_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.maps import places_v1 + + +async def sample_get_photo_media(): + # Create a client + client = places_v1.PlacesAsyncClient() + + # Initialize request argument(s) + request = places_v1.GetPhotoMediaRequest( + name="name_value", + ) + + # Make the request + response = await client.get_photo_media(request=request) + + # Handle the response + print(response) + +# [END places_v1_generated_Places_GetPhotoMedia_async] diff --git a/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_photo_media_sync.py b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_photo_media_sync.py new file mode 100644 index 000000000000..731d71fcf8f7 --- /dev/null +++ b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_photo_media_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetPhotoMedia +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-maps-places + + +# [START places_v1_generated_Places_GetPhotoMedia_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.maps import places_v1 + + +def sample_get_photo_media(): + # Create a client + client = places_v1.PlacesClient() + + # Initialize request argument(s) + request = places_v1.GetPhotoMediaRequest( + name="name_value", + ) + + # Make the request + response = client.get_photo_media(request=request) + + # Handle the response + print(response) + +# [END places_v1_generated_Places_GetPhotoMedia_sync] diff --git a/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_place_async.py b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_place_async.py new file mode 100644 index 000000000000..831d4dbdfc4b --- /dev/null +++ b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_place_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetPlace +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-maps-places + + +# [START places_v1_generated_Places_GetPlace_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.maps import places_v1 + + +async def sample_get_place(): + # Create a client + client = places_v1.PlacesAsyncClient() + + # Initialize request argument(s) + request = places_v1.GetPlaceRequest( + name="name_value", + ) + + # Make the request + response = await client.get_place(request=request) + + # Handle the response + print(response) + +# [END places_v1_generated_Places_GetPlace_async] diff --git a/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_place_sync.py b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_place_sync.py new file mode 100644 index 000000000000..cbcd3fc1eb84 --- /dev/null +++ b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_get_place_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetPlace +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-maps-places + + +# [START places_v1_generated_Places_GetPlace_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.maps import places_v1 + + +def sample_get_place(): + # Create a client + client = places_v1.PlacesClient() + + # Initialize request argument(s) + request = places_v1.GetPlaceRequest( + name="name_value", + ) + + # Make the request + response = client.get_place(request=request) + + # Handle the response + print(response) + +# [END places_v1_generated_Places_GetPlace_sync] diff --git a/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_search_nearby_async.py b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_search_nearby_async.py new file mode 100644 index 000000000000..56ff46e98f2b --- /dev/null +++ b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_search_nearby_async.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for SearchNearby +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-maps-places + + +# [START places_v1_generated_Places_SearchNearby_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.maps import places_v1 + + +async def sample_search_nearby(): + # Create a client + client = places_v1.PlacesAsyncClient() + + # Initialize request argument(s) + location_restriction = places_v1.LocationRestriction() + location_restriction.circle.radius = 0.648 + + request = places_v1.SearchNearbyRequest( + location_restriction=location_restriction, + ) + + # Make the request + response = await client.search_nearby(request=request) + + # Handle the response + print(response) + +# [END places_v1_generated_Places_SearchNearby_async] diff --git a/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_search_nearby_sync.py b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_search_nearby_sync.py new file mode 100644 index 000000000000..948cb9a3a7a6 --- /dev/null +++ b/packages/google-maps-places/samples/generated_samples/places_v1_generated_places_search_nearby_sync.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for SearchNearby +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-maps-places + + +# [START places_v1_generated_Places_SearchNearby_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.maps import places_v1 + + +def sample_search_nearby(): + # Create a client + client = places_v1.PlacesClient() + + # Initialize request argument(s) + location_restriction = places_v1.LocationRestriction() + location_restriction.circle.radius = 0.648 + + request = places_v1.SearchNearbyRequest( + location_restriction=location_restriction, + ) + + # Make the request + response = client.search_nearby(request=request) + + # Handle the response + print(response) + +# [END places_v1_generated_Places_SearchNearby_sync] diff --git a/packages/google-maps-places/samples/generated_samples/snippet_metadata_google.maps.places.v1.json b/packages/google-maps-places/samples/generated_samples/snippet_metadata_google.maps.places.v1.json index 8bc643843de4..6444e295ff29 100644 --- a/packages/google-maps-places/samples/generated_samples/snippet_metadata_google.maps.places.v1.json +++ b/packages/google-maps-places/samples/generated_samples/snippet_metadata_google.maps.places.v1.json @@ -8,9 +8,484 @@ ], "language": "PYTHON", "name": "google-maps-places", - "version": "0.1.3" + "version": "0.1.0" }, "snippets": [ + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.maps.places_v1.PlacesAsyncClient", + "shortName": "PlacesAsyncClient" + }, + "fullName": "google.maps.places_v1.PlacesAsyncClient.get_photo_media", + "method": { + "fullName": "google.maps.places.v1.Places.GetPhotoMedia", + "service": { + "fullName": "google.maps.places.v1.Places", + "shortName": "Places" + }, + "shortName": "GetPhotoMedia" + }, + "parameters": [ + { + "name": "request", + "type": "google.maps.places_v1.types.GetPhotoMediaRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.maps.places_v1.types.PhotoMedia", + "shortName": "get_photo_media" + }, + "description": "Sample for GetPhotoMedia", + "file": "places_v1_generated_places_get_photo_media_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "places_v1_generated_Places_GetPhotoMedia_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "places_v1_generated_places_get_photo_media_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.maps.places_v1.PlacesClient", + "shortName": "PlacesClient" + }, + "fullName": "google.maps.places_v1.PlacesClient.get_photo_media", + "method": { + "fullName": "google.maps.places.v1.Places.GetPhotoMedia", + "service": { + "fullName": "google.maps.places.v1.Places", + "shortName": "Places" + }, + "shortName": "GetPhotoMedia" + }, + "parameters": [ + { + "name": "request", + "type": "google.maps.places_v1.types.GetPhotoMediaRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.maps.places_v1.types.PhotoMedia", + "shortName": "get_photo_media" + }, + "description": "Sample for GetPhotoMedia", + "file": "places_v1_generated_places_get_photo_media_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "places_v1_generated_Places_GetPhotoMedia_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "places_v1_generated_places_get_photo_media_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.maps.places_v1.PlacesAsyncClient", + "shortName": "PlacesAsyncClient" + }, + "fullName": "google.maps.places_v1.PlacesAsyncClient.get_place", + "method": { + "fullName": "google.maps.places.v1.Places.GetPlace", + "service": { + "fullName": "google.maps.places.v1.Places", + "shortName": "Places" + }, + "shortName": "GetPlace" + }, + "parameters": [ + { + "name": "request", + "type": "google.maps.places_v1.types.GetPlaceRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.maps.places_v1.types.Place", + "shortName": "get_place" + }, + "description": "Sample for GetPlace", + "file": "places_v1_generated_places_get_place_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "places_v1_generated_Places_GetPlace_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "places_v1_generated_places_get_place_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.maps.places_v1.PlacesClient", + "shortName": "PlacesClient" + }, + "fullName": "google.maps.places_v1.PlacesClient.get_place", + "method": { + "fullName": "google.maps.places.v1.Places.GetPlace", + "service": { + "fullName": "google.maps.places.v1.Places", + "shortName": "Places" + }, + "shortName": "GetPlace" + }, + "parameters": [ + { + "name": "request", + "type": "google.maps.places_v1.types.GetPlaceRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.maps.places_v1.types.Place", + "shortName": "get_place" + }, + "description": "Sample for GetPlace", + "file": "places_v1_generated_places_get_place_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "places_v1_generated_Places_GetPlace_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "places_v1_generated_places_get_place_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.maps.places_v1.PlacesAsyncClient", + "shortName": "PlacesAsyncClient" + }, + "fullName": "google.maps.places_v1.PlacesAsyncClient.search_nearby", + "method": { + "fullName": "google.maps.places.v1.Places.SearchNearby", + "service": { + "fullName": "google.maps.places.v1.Places", + "shortName": "Places" + }, + "shortName": "SearchNearby" + }, + "parameters": [ + { + "name": "request", + "type": "google.maps.places_v1.types.SearchNearbyRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.maps.places_v1.types.SearchNearbyResponse", + "shortName": "search_nearby" + }, + "description": "Sample for SearchNearby", + "file": "places_v1_generated_places_search_nearby_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "places_v1_generated_Places_SearchNearby_async", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 48, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 51, + "start": 49, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 52, + "type": "RESPONSE_HANDLING" + } + ], + "title": "places_v1_generated_places_search_nearby_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.maps.places_v1.PlacesClient", + "shortName": "PlacesClient" + }, + "fullName": "google.maps.places_v1.PlacesClient.search_nearby", + "method": { + "fullName": "google.maps.places.v1.Places.SearchNearby", + "service": { + "fullName": "google.maps.places.v1.Places", + "shortName": "Places" + }, + "shortName": "SearchNearby" + }, + "parameters": [ + { + "name": "request", + "type": "google.maps.places_v1.types.SearchNearbyRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.maps.places_v1.types.SearchNearbyResponse", + "shortName": "search_nearby" + }, + "description": "Sample for SearchNearby", + "file": "places_v1_generated_places_search_nearby_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "places_v1_generated_Places_SearchNearby_sync", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 48, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 51, + "start": 49, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 52, + "type": "RESPONSE_HANDLING" + } + ], + "title": "places_v1_generated_places_search_nearby_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/packages/google-maps-places/scripts/fixup_places_v1_keywords.py b/packages/google-maps-places/scripts/fixup_places_v1_keywords.py index 46658513268f..4d24e9b61751 100644 --- a/packages/google-maps-places/scripts/fixup_places_v1_keywords.py +++ b/packages/google-maps-places/scripts/fixup_places_v1_keywords.py @@ -39,7 +39,10 @@ def partition( class placesCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'search_text': ('text_query', 'language_code', 'region_code', 'rank_preference', 'location', 'included_type', 'open_now', 'price_range', 'min_rating', 'max_result_count', 'price_levels', 'strict_type_filtering', 'location_bias', 'location_restriction', ), + 'get_photo_media': ('name', 'max_width_px', 'max_height_px', 'skip_http_redirect', ), + 'get_place': ('name', 'language_code', 'region_code', ), + 'search_nearby': ('location_restriction', 'language_code', 'region_code', 'included_types', 'excluded_types', 'included_primary_types', 'excluded_primary_types', 'max_result_count', 'rank_preference', ), + 'search_text': ('text_query', 'language_code', 'region_code', 'rank_preference', 'included_type', 'open_now', 'min_rating', 'max_result_count', 'price_levels', 'strict_type_filtering', 'location_bias', 'location_restriction', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: diff --git a/packages/google-maps-places/tests/unit/gapic/places_v1/test_places.py b/packages/google-maps-places/tests/unit/gapic/places_v1/test_places.py index 6f57d5aad8f5..f8946f734500 100644 --- a/packages/google-maps-places/tests/unit/gapic/places_v1/test_places.py +++ b/packages/google-maps-places/tests/unit/gapic/places_v1/test_places.py @@ -36,6 +36,7 @@ from google.oauth2 import service_account from google.protobuf import json_format from google.type import latlng_pb2 # type: ignore +from google.type import localized_text_pb2 # type: ignore import grpc from grpc.experimental import aio from proto.marshal.rules import wrappers @@ -49,7 +50,15 @@ PlacesClient, transports, ) -from google.maps.places_v1.types import geometry, place, places_service +from google.maps.places_v1.types import ( + ev_charging, + fuel_options, + geometry, + photo, + place, + places_service, + review, +) def client_cert_source_callback(): @@ -630,161 +639,1639 @@ def test_places_client_create_channel_credentials_file( api_audience=None, ) - # test that the credentials from file are saved and used as the credentials. - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch.object( - google.auth, "default", autospec=True - ) as adc, mock.patch.object( - grpc_helpers, "create_channel" - ) as create_channel: - creds = ga_credentials.AnonymousCredentials() - file_creds = ga_credentials.AnonymousCredentials() - load_creds.return_value = (file_creds, None) - adc.return_value = (creds, None) - client = client_class(client_options=options, transport=transport_name) - create_channel.assert_called_with( - "places.googleapis.com:443", - credentials=file_creds, - credentials_file=None, - quota_project_id=None, - default_scopes=(), - scopes=None, - default_host="places.googleapis.com", - ssl_credentials=None, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), + # test that the credentials from file are saved and used as the credentials. + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel" + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + file_creds = ga_credentials.AnonymousCredentials() + load_creds.return_value = (file_creds, None) + adc.return_value = (creds, None) + client = client_class(client_options=options, transport=transport_name) + create_channel.assert_called_with( + "places.googleapis.com:443", + credentials=file_creds, + credentials_file=None, + quota_project_id=None, + default_scopes=(), + scopes=None, + default_host="places.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + places_service.SearchNearbyRequest, + dict, + ], +) +def test_search_nearby(request_type, transport: str = "grpc"): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.search_nearby), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = places_service.SearchNearbyResponse() + response = client.search_nearby(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.SearchNearbyRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.SearchNearbyResponse) + + +def test_search_nearby_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.search_nearby), "__call__") as call: + client.search_nearby() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.SearchNearbyRequest() + + +@pytest.mark.asyncio +async def test_search_nearby_async( + transport: str = "grpc_asyncio", request_type=places_service.SearchNearbyRequest +): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.search_nearby), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + places_service.SearchNearbyResponse() + ) + response = await client.search_nearby(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.SearchNearbyRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.SearchNearbyResponse) + + +@pytest.mark.asyncio +async def test_search_nearby_async_from_dict(): + await test_search_nearby_async(request_type=dict) + + +@pytest.mark.parametrize( + "request_type", + [ + places_service.SearchTextRequest, + dict, + ], +) +def test_search_text(request_type, transport: str = "grpc"): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.search_text), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = places_service.SearchTextResponse() + response = client.search_text(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.SearchTextRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.SearchTextResponse) + + +def test_search_text_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.search_text), "__call__") as call: + client.search_text() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.SearchTextRequest() + + +@pytest.mark.asyncio +async def test_search_text_async( + transport: str = "grpc_asyncio", request_type=places_service.SearchTextRequest +): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.search_text), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + places_service.SearchTextResponse() + ) + response = await client.search_text(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.SearchTextRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.SearchTextResponse) + + +@pytest.mark.asyncio +async def test_search_text_async_from_dict(): + await test_search_text_async(request_type=dict) + + +@pytest.mark.parametrize( + "request_type", + [ + places_service.GetPhotoMediaRequest, + dict, + ], +) +def test_get_photo_media(request_type, transport: str = "grpc"): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_photo_media), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = places_service.PhotoMedia( + name="name_value", + photo_uri="photo_uri_value", + ) + response = client.get_photo_media(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.GetPhotoMediaRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.PhotoMedia) + assert response.name == "name_value" + assert response.photo_uri == "photo_uri_value" + + +def test_get_photo_media_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_photo_media), "__call__") as call: + client.get_photo_media() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.GetPhotoMediaRequest() + + +@pytest.mark.asyncio +async def test_get_photo_media_async( + transport: str = "grpc_asyncio", request_type=places_service.GetPhotoMediaRequest +): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_photo_media), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + places_service.PhotoMedia( + name="name_value", + photo_uri="photo_uri_value", + ) + ) + response = await client.get_photo_media(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.GetPhotoMediaRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.PhotoMedia) + assert response.name == "name_value" + assert response.photo_uri == "photo_uri_value" + + +@pytest.mark.asyncio +async def test_get_photo_media_async_from_dict(): + await test_get_photo_media_async(request_type=dict) + + +def test_get_photo_media_field_headers(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = places_service.GetPhotoMediaRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_photo_media), "__call__") as call: + call.return_value = places_service.PhotoMedia() + client.get_photo_media(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_photo_media_field_headers_async(): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = places_service.GetPhotoMediaRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_photo_media), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + places_service.PhotoMedia() + ) + await client.get_photo_media(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +def test_get_photo_media_flattened(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_photo_media), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = places_service.PhotoMedia() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_photo_media( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +def test_get_photo_media_flattened_error(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_photo_media( + places_service.GetPhotoMediaRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_photo_media_flattened_async(): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_photo_media), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = places_service.PhotoMedia() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + places_service.PhotoMedia() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_photo_media( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_get_photo_media_flattened_error_async(): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_photo_media( + places_service.GetPhotoMediaRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + places_service.GetPlaceRequest, + dict, + ], +) +def test_get_place(request_type, transport: str = "grpc"): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_place), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = place.Place( + name="name_value", + id="id_value", + types=["types_value"], + national_phone_number="national_phone_number_value", + international_phone_number="international_phone_number_value", + formatted_address="formatted_address_value", + rating=0.645, + google_maps_uri="google_maps_uri_value", + website_uri="website_uri_value", + utc_offset_minutes=1942, + adr_format_address="adr_format_address_value", + business_status=place.Place.BusinessStatus.OPERATIONAL, + price_level=place.PriceLevel.PRICE_LEVEL_FREE, + user_rating_count=1835, + icon_mask_base_uri="icon_mask_base_uri_value", + icon_background_color="icon_background_color_value", + takeout=True, + delivery=True, + dine_in=True, + curbside_pickup=True, + reservable=True, + serves_breakfast=True, + serves_lunch=True, + serves_dinner=True, + serves_beer=True, + serves_wine=True, + serves_brunch=True, + serves_vegetarian_food=True, + outdoor_seating=True, + live_music=True, + menu_for_children=True, + serves_cocktails=True, + serves_dessert=True, + serves_coffee=True, + good_for_children=True, + allows_dogs=True, + restroom=True, + good_for_groups=True, + good_for_watching_sports=True, + ) + response = client.get_place(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.GetPlaceRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, place.Place) + assert response.name == "name_value" + assert response.id == "id_value" + assert response.types == ["types_value"] + assert response.national_phone_number == "national_phone_number_value" + assert response.international_phone_number == "international_phone_number_value" + assert response.formatted_address == "formatted_address_value" + assert math.isclose(response.rating, 0.645, rel_tol=1e-6) + assert response.google_maps_uri == "google_maps_uri_value" + assert response.website_uri == "website_uri_value" + assert response.utc_offset_minutes == 1942 + assert response.adr_format_address == "adr_format_address_value" + assert response.business_status == place.Place.BusinessStatus.OPERATIONAL + assert response.price_level == place.PriceLevel.PRICE_LEVEL_FREE + assert response.user_rating_count == 1835 + assert response.icon_mask_base_uri == "icon_mask_base_uri_value" + assert response.icon_background_color == "icon_background_color_value" + assert response.takeout is True + assert response.delivery is True + assert response.dine_in is True + assert response.curbside_pickup is True + assert response.reservable is True + assert response.serves_breakfast is True + assert response.serves_lunch is True + assert response.serves_dinner is True + assert response.serves_beer is True + assert response.serves_wine is True + assert response.serves_brunch is True + assert response.serves_vegetarian_food is True + assert response.outdoor_seating is True + assert response.live_music is True + assert response.menu_for_children is True + assert response.serves_cocktails is True + assert response.serves_dessert is True + assert response.serves_coffee is True + assert response.good_for_children is True + assert response.allows_dogs is True + assert response.restroom is True + assert response.good_for_groups is True + assert response.good_for_watching_sports is True + + +def test_get_place_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_place), "__call__") as call: + client.get_place() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.GetPlaceRequest() + + +@pytest.mark.asyncio +async def test_get_place_async( + transport: str = "grpc_asyncio", request_type=places_service.GetPlaceRequest +): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_place), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + place.Place( + name="name_value", + id="id_value", + types=["types_value"], + national_phone_number="national_phone_number_value", + international_phone_number="international_phone_number_value", + formatted_address="formatted_address_value", + rating=0.645, + google_maps_uri="google_maps_uri_value", + website_uri="website_uri_value", + utc_offset_minutes=1942, + adr_format_address="adr_format_address_value", + business_status=place.Place.BusinessStatus.OPERATIONAL, + price_level=place.PriceLevel.PRICE_LEVEL_FREE, + user_rating_count=1835, + icon_mask_base_uri="icon_mask_base_uri_value", + icon_background_color="icon_background_color_value", + takeout=True, + delivery=True, + dine_in=True, + curbside_pickup=True, + reservable=True, + serves_breakfast=True, + serves_lunch=True, + serves_dinner=True, + serves_beer=True, + serves_wine=True, + serves_brunch=True, + serves_vegetarian_food=True, + outdoor_seating=True, + live_music=True, + menu_for_children=True, + serves_cocktails=True, + serves_dessert=True, + serves_coffee=True, + good_for_children=True, + allows_dogs=True, + restroom=True, + good_for_groups=True, + good_for_watching_sports=True, + ) + ) + response = await client.get_place(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == places_service.GetPlaceRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, place.Place) + assert response.name == "name_value" + assert response.id == "id_value" + assert response.types == ["types_value"] + assert response.national_phone_number == "national_phone_number_value" + assert response.international_phone_number == "international_phone_number_value" + assert response.formatted_address == "formatted_address_value" + assert math.isclose(response.rating, 0.645, rel_tol=1e-6) + assert response.google_maps_uri == "google_maps_uri_value" + assert response.website_uri == "website_uri_value" + assert response.utc_offset_minutes == 1942 + assert response.adr_format_address == "adr_format_address_value" + assert response.business_status == place.Place.BusinessStatus.OPERATIONAL + assert response.price_level == place.PriceLevel.PRICE_LEVEL_FREE + assert response.user_rating_count == 1835 + assert response.icon_mask_base_uri == "icon_mask_base_uri_value" + assert response.icon_background_color == "icon_background_color_value" + assert response.takeout is True + assert response.delivery is True + assert response.dine_in is True + assert response.curbside_pickup is True + assert response.reservable is True + assert response.serves_breakfast is True + assert response.serves_lunch is True + assert response.serves_dinner is True + assert response.serves_beer is True + assert response.serves_wine is True + assert response.serves_brunch is True + assert response.serves_vegetarian_food is True + assert response.outdoor_seating is True + assert response.live_music is True + assert response.menu_for_children is True + assert response.serves_cocktails is True + assert response.serves_dessert is True + assert response.serves_coffee is True + assert response.good_for_children is True + assert response.allows_dogs is True + assert response.restroom is True + assert response.good_for_groups is True + assert response.good_for_watching_sports is True + + +@pytest.mark.asyncio +async def test_get_place_async_from_dict(): + await test_get_place_async(request_type=dict) + + +def test_get_place_field_headers(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = places_service.GetPlaceRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_place), "__call__") as call: + call.return_value = place.Place() + client.get_place(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_place_field_headers_async(): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = places_service.GetPlaceRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_place), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(place.Place()) + await client.get_place(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +def test_get_place_flattened(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_place), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = place.Place() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_place( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +def test_get_place_flattened_error(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_place( + places_service.GetPlaceRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_place_flattened_async(): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_place), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = place.Place() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(place.Place()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_place( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_get_place_flattened_error_async(): + client = PlacesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_place( + places_service.GetPlaceRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + places_service.SearchNearbyRequest, + dict, + ], +) +def test_search_nearby_rest(request_type): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = places_service.SearchNearbyResponse() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = places_service.SearchNearbyResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.search_nearby(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.SearchNearbyResponse) + + +def test_search_nearby_rest_required_fields( + request_type=places_service.SearchNearbyRequest, +): + transport_class = transports.PlacesRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).search_nearby._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).search_nearby._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = places_service.SearchNearbyResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = places_service.SearchNearbyResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.search_nearby(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_search_nearby_rest_unset_required_fields(): + transport = transports.PlacesRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.search_nearby._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("locationRestriction",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_search_nearby_rest_interceptors(null_interceptor): + transport = transports.PlacesRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None if null_interceptor else transports.PlacesRestInterceptor(), + ) + client = PlacesClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.PlacesRestInterceptor, "post_search_nearby" + ) as post, mock.patch.object( + transports.PlacesRestInterceptor, "pre_search_nearby" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = places_service.SearchNearbyRequest.pb( + places_service.SearchNearbyRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = places_service.SearchNearbyResponse.to_json( + places_service.SearchNearbyResponse() + ) + + request = places_service.SearchNearbyRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = places_service.SearchNearbyResponse() + + client.search_nearby( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_search_nearby_rest_bad_request( + transport: str = "rest", request_type=places_service.SearchNearbyRequest +): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.search_nearby(request) + + +def test_search_nearby_rest_error(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + places_service.SearchTextRequest, + dict, + ], +) +def test_search_text_rest(request_type): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = places_service.SearchTextResponse() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = places_service.SearchTextResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.search_text(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.SearchTextResponse) + + +def test_search_text_rest_required_fields( + request_type=places_service.SearchTextRequest, +): + transport_class = transports.PlacesRestTransport + + request_init = {} + request_init["text_query"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).search_text._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["textQuery"] = "text_query_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).search_text._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "textQuery" in jsonified_request + assert jsonified_request["textQuery"] == "text_query_value" + + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = places_service.SearchTextResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = places_service.SearchTextResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.search_text(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_search_text_rest_unset_required_fields(): + transport = transports.PlacesRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.search_text._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("textQuery",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_search_text_rest_interceptors(null_interceptor): + transport = transports.PlacesRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None if null_interceptor else transports.PlacesRestInterceptor(), + ) + client = PlacesClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.PlacesRestInterceptor, "post_search_text" + ) as post, mock.patch.object( + transports.PlacesRestInterceptor, "pre_search_text" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = places_service.SearchTextRequest.pb( + places_service.SearchTextRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = places_service.SearchTextResponse.to_json( + places_service.SearchTextResponse() + ) + + request = places_service.SearchTextRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = places_service.SearchTextResponse() + + client.search_text( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_search_text_rest_bad_request( + transport: str = "rest", request_type=places_service.SearchTextRequest +): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.search_text(request) + + +def test_search_text_rest_error(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + places_service.GetPhotoMediaRequest, + dict, + ], +) +def test_get_photo_media_rest(request_type): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "places/sample1/photos/sample2/media"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = places_service.PhotoMedia( + name="name_value", + photo_uri="photo_uri_value", + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = places_service.PhotoMedia.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.get_photo_media(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, places_service.PhotoMedia) + assert response.name == "name_value" + assert response.photo_uri == "photo_uri_value" + + +def test_get_photo_media_rest_required_fields( + request_type=places_service.GetPhotoMediaRequest, +): + transport_class = transports.PlacesRestTransport + + request_init = {} + request_init["name"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson( + pb_request, + including_default_value_fields=False, + use_integers_for_enums=False, + ) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_photo_media._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["name"] = "name_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_photo_media._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "max_height_px", + "max_width_px", + "skip_http_redirect", + ) + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = places_service.PhotoMedia() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = places_service.PhotoMedia.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_photo_media(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_photo_media_rest_unset_required_fields(): + transport = transports.PlacesRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_photo_media._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "maxHeightPx", + "maxWidthPx", + "skipHttpRedirect", + ) + ) + & set(("name",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_photo_media_rest_interceptors(null_interceptor): + transport = transports.PlacesRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None if null_interceptor else transports.PlacesRestInterceptor(), + ) + client = PlacesClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.PlacesRestInterceptor, "post_get_photo_media" + ) as post, mock.patch.object( + transports.PlacesRestInterceptor, "pre_get_photo_media" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = places_service.GetPhotoMediaRequest.pb( + places_service.GetPhotoMediaRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = places_service.PhotoMedia.to_json( + places_service.PhotoMedia() + ) + + request = places_service.GetPhotoMediaRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = places_service.PhotoMedia() + + client.get_photo_media( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), ], ) + pre.assert_called_once() + post.assert_called_once() + -@pytest.mark.parametrize( - "request_type", - [ - places_service.SearchTextRequest, - dict, - ], -) -def test_search_text(request_type, transport: str = "grpc"): +def test_get_photo_media_rest_bad_request( + transport: str = "rest", request_type=places_service.GetPhotoMediaRequest +): client = PlacesClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() - - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.search_text), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = places_service.SearchTextResponse() - response = client.search_text(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == places_service.SearchTextRequest() + # send a request that will satisfy transcoding + request_init = {"name": "places/sample1/photos/sample2/media"} + request = request_type(**request_init) - # Establish that the response is the type that we expect. - assert isinstance(response, places_service.SearchTextResponse) + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_photo_media(request) -def test_search_text_empty_call(): - # This test is a coverage failsafe to make sure that totally empty calls, - # i.e. request == None and no flattened fields passed, work. +def test_get_photo_media_rest_flattened(): client = PlacesClient( credentials=ga_credentials.AnonymousCredentials(), - transport="grpc", + transport="rest", ) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.search_text), "__call__") as call: - client.search_text() - call.assert_called() - _, args, _ = call.mock_calls[0] - assert args[0] == places_service.SearchTextRequest() + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = places_service.PhotoMedia() + # get arguments that satisfy an http rule for this method + sample_request = {"name": "places/sample1/photos/sample2/media"} -@pytest.mark.asyncio -async def test_search_text_async( - transport: str = "grpc_asyncio", request_type=places_service.SearchTextRequest -): - client = PlacesAsyncClient( - credentials=ga_credentials.AnonymousCredentials(), - transport=transport, - ) + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = places_service.PhotoMedia.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.search_text), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - places_service.SearchTextResponse() + client.get_photo_media(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{name=places/*/photos/*/media}" % client.transport._host, args[1] ) - response = await client.search_text(request) - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) - _, args, _ = call.mock_calls[0] - assert args[0] == places_service.SearchTextRequest() - # Establish that the response is the type that we expect. - assert isinstance(response, places_service.SearchTextResponse) +def test_get_photo_media_rest_flattened_error(transport: str = "rest"): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_photo_media( + places_service.GetPhotoMediaRequest(), + name="name_value", + ) -@pytest.mark.asyncio -async def test_search_text_async_from_dict(): - await test_search_text_async(request_type=dict) +def test_get_photo_media_rest_error(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) @pytest.mark.parametrize( "request_type", [ - places_service.SearchTextRequest, + places_service.GetPlaceRequest, dict, ], ) -def test_search_text_rest(request_type): +def test_get_place_rest(request_type): client = PlacesClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {} + request_init = {"name": "places/sample1"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = places_service.SearchTextResponse() + return_value = place.Place( + name="name_value", + id="id_value", + types=["types_value"], + national_phone_number="national_phone_number_value", + international_phone_number="international_phone_number_value", + formatted_address="formatted_address_value", + rating=0.645, + google_maps_uri="google_maps_uri_value", + website_uri="website_uri_value", + utc_offset_minutes=1942, + adr_format_address="adr_format_address_value", + business_status=place.Place.BusinessStatus.OPERATIONAL, + price_level=place.PriceLevel.PRICE_LEVEL_FREE, + user_rating_count=1835, + icon_mask_base_uri="icon_mask_base_uri_value", + icon_background_color="icon_background_color_value", + takeout=True, + delivery=True, + dine_in=True, + curbside_pickup=True, + reservable=True, + serves_breakfast=True, + serves_lunch=True, + serves_dinner=True, + serves_beer=True, + serves_wine=True, + serves_brunch=True, + serves_vegetarian_food=True, + outdoor_seating=True, + live_music=True, + menu_for_children=True, + serves_cocktails=True, + serves_dessert=True, + serves_coffee=True, + good_for_children=True, + allows_dogs=True, + restroom=True, + good_for_groups=True, + good_for_watching_sports=True, + ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - pb_return_value = places_service.SearchTextResponse.pb(return_value) - json_return_value = json_format.MessageToJson(pb_return_value) + # Convert return value to protobuf type + return_value = place.Place.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.search_text(request) + response = client.get_place(request) # Establish that the response is the type that we expect. - assert isinstance(response, places_service.SearchTextResponse) - - -def test_search_text_rest_required_fields( - request_type=places_service.SearchTextRequest, -): + assert isinstance(response, place.Place) + assert response.name == "name_value" + assert response.id == "id_value" + assert response.types == ["types_value"] + assert response.national_phone_number == "national_phone_number_value" + assert response.international_phone_number == "international_phone_number_value" + assert response.formatted_address == "formatted_address_value" + assert math.isclose(response.rating, 0.645, rel_tol=1e-6) + assert response.google_maps_uri == "google_maps_uri_value" + assert response.website_uri == "website_uri_value" + assert response.utc_offset_minutes == 1942 + assert response.adr_format_address == "adr_format_address_value" + assert response.business_status == place.Place.BusinessStatus.OPERATIONAL + assert response.price_level == place.PriceLevel.PRICE_LEVEL_FREE + assert response.user_rating_count == 1835 + assert response.icon_mask_base_uri == "icon_mask_base_uri_value" + assert response.icon_background_color == "icon_background_color_value" + assert response.takeout is True + assert response.delivery is True + assert response.dine_in is True + assert response.curbside_pickup is True + assert response.reservable is True + assert response.serves_breakfast is True + assert response.serves_lunch is True + assert response.serves_dinner is True + assert response.serves_beer is True + assert response.serves_wine is True + assert response.serves_brunch is True + assert response.serves_vegetarian_food is True + assert response.outdoor_seating is True + assert response.live_music is True + assert response.menu_for_children is True + assert response.serves_cocktails is True + assert response.serves_dessert is True + assert response.serves_coffee is True + assert response.good_for_children is True + assert response.allows_dogs is True + assert response.restroom is True + assert response.good_for_groups is True + assert response.good_for_watching_sports is True + + +def test_get_place_rest_required_fields(request_type=places_service.GetPlaceRequest): transport_class = transports.PlacesRestTransport request_init = {} - request_init["text_query"] = "" + request_init["name"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( @@ -799,21 +2286,28 @@ def test_search_text_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).search_text._get_unset_required_fields(jsonified_request) + ).get_place._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["textQuery"] = "text_query_value" + jsonified_request["name"] = "name_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).search_text._get_unset_required_fields(jsonified_request) + ).get_place._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "language_code", + "region_code", + ) + ) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "textQuery" in jsonified_request - assert jsonified_request["textQuery"] == "text_query_value" + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" client = PlacesClient( credentials=ga_credentials.AnonymousCredentials(), @@ -822,7 +2316,7 @@ def test_search_text_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = places_service.SearchTextResponse() + return_value = place.Place() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -834,39 +2328,47 @@ def test_search_text_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "post", + "method": "get", "query_params": pb_request, } - transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 - pb_return_value = places_service.SearchTextResponse.pb(return_value) - json_return_value = json_format.MessageToJson(pb_return_value) + # Convert return value to protobuf type + return_value = place.Place.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.search_text(request) + response = client.get_place(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_search_text_rest_unset_required_fields(): +def test_get_place_rest_unset_required_fields(): transport = transports.PlacesRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.search_text._get_unset_required_fields({}) - assert set(unset_fields) == (set(()) & set(("textQuery",))) + unset_fields = transport.get_place._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "languageCode", + "regionCode", + ) + ) + & set(("name",)) + ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_search_text_rest_interceptors(null_interceptor): +def test_get_place_rest_interceptors(null_interceptor): transport = transports.PlacesRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None if null_interceptor else transports.PlacesRestInterceptor(), @@ -877,15 +2379,13 @@ def test_search_text_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.PlacesRestInterceptor, "post_search_text" + transports.PlacesRestInterceptor, "post_get_place" ) as post, mock.patch.object( - transports.PlacesRestInterceptor, "pre_search_text" + transports.PlacesRestInterceptor, "pre_get_place" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = places_service.SearchTextRequest.pb( - places_service.SearchTextRequest() - ) + pb_message = places_service.GetPlaceRequest.pb(places_service.GetPlaceRequest()) transcode.return_value = { "method": "post", "uri": "my_uri", @@ -896,19 +2396,17 @@ def test_search_text_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = places_service.SearchTextResponse.to_json( - places_service.SearchTextResponse() - ) + req.return_value._content = place.Place.to_json(place.Place()) - request = places_service.SearchTextRequest() + request = places_service.GetPlaceRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = places_service.SearchTextResponse() + post.return_value = place.Place() - client.search_text( + client.get_place( request, metadata=[ ("key", "val"), @@ -920,8 +2418,8 @@ def test_search_text_rest_interceptors(null_interceptor): post.assert_called_once() -def test_search_text_rest_bad_request( - transport: str = "rest", request_type=places_service.SearchTextRequest +def test_get_place_rest_bad_request( + transport: str = "rest", request_type=places_service.GetPlaceRequest ): client = PlacesClient( credentials=ga_credentials.AnonymousCredentials(), @@ -929,7 +2427,7 @@ def test_search_text_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {} + request_init = {"name": "places/sample1"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -941,10 +2439,65 @@ def test_search_text_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.search_text(request) + client.get_place(request) -def test_search_text_rest_error(): +def test_get_place_rest_flattened(): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = place.Place() + + # get arguments that satisfy an http rule for this method + sample_request = {"name": "places/sample1"} + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = place.Place.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.get_place(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{name=places/*}" % client.transport._host, args[1] + ) + + +def test_get_place_rest_flattened_error(transport: str = "rest"): + client = PlacesClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_place( + places_service.GetPlaceRequest(), + name="name_value", + ) + + +def test_get_place_rest_error(): client = PlacesClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -1088,7 +2641,12 @@ def test_places_base_transport(): # Every method on the transport should just blindly # raise NotImplementedError. - methods = ("search_text",) + methods = ( + "search_nearby", + "search_text", + "get_photo_media", + "get_place", + ) for method in methods: with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) @@ -1343,9 +2901,18 @@ def test_places_client_transport_session_collision(transport_name): credentials=creds2, transport=transport_name, ) + session1 = client1.transport.search_nearby._session + session2 = client2.transport.search_nearby._session + assert session1 != session2 session1 = client1.transport.search_text._session session2 = client2.transport.search_text._session assert session1 != session2 + session1 = client1.transport.get_photo_media._session + session2 = client2.transport.get_photo_media._session + assert session1 != session2 + session1 = client1.transport.get_place._session + session2 = client2.transport.get_place._session + assert session1 != session2 def test_places_grpc_transport_channel(): @@ -1466,8 +3033,97 @@ def test_places_transport_channel_mtls_with_adc(transport_class): assert transport.grpc_channel == mock_grpc_channel +def test_photo_path(): + place = "squid" + photo = "clam" + expected = "places/{place}/photos/{photo}".format( + place=place, + photo=photo, + ) + actual = PlacesClient.photo_path(place, photo) + assert expected == actual + + +def test_parse_photo_path(): + expected = { + "place": "whelk", + "photo": "octopus", + } + path = PlacesClient.photo_path(**expected) + + # Check that the path construction is reversible. + actual = PlacesClient.parse_photo_path(path) + assert expected == actual + + +def test_photo_media_path(): + place_id = "oyster" + photo_reference = "nudibranch" + expected = "places/{place_id}/photos/{photo_reference}/media".format( + place_id=place_id, + photo_reference=photo_reference, + ) + actual = PlacesClient.photo_media_path(place_id, photo_reference) + assert expected == actual + + +def test_parse_photo_media_path(): + expected = { + "place_id": "cuttlefish", + "photo_reference": "mussel", + } + path = PlacesClient.photo_media_path(**expected) + + # Check that the path construction is reversible. + actual = PlacesClient.parse_photo_media_path(path) + assert expected == actual + + +def test_place_path(): + place_id = "winkle" + expected = "places/{place_id}".format( + place_id=place_id, + ) + actual = PlacesClient.place_path(place_id) + assert expected == actual + + +def test_parse_place_path(): + expected = { + "place_id": "nautilus", + } + path = PlacesClient.place_path(**expected) + + # Check that the path construction is reversible. + actual = PlacesClient.parse_place_path(path) + assert expected == actual + + +def test_review_path(): + place = "scallop" + review = "abalone" + expected = "places/{place}/reviews/{review}".format( + place=place, + review=review, + ) + actual = PlacesClient.review_path(place, review) + assert expected == actual + + +def test_parse_review_path(): + expected = { + "place": "squid", + "review": "clam", + } + path = PlacesClient.review_path(**expected) + + # Check that the path construction is reversible. + actual = PlacesClient.parse_review_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "squid" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -1477,7 +3133,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "clam", + "billing_account": "octopus", } path = PlacesClient.common_billing_account_path(**expected) @@ -1487,7 +3143,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "whelk" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -1497,7 +3153,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "octopus", + "folder": "nudibranch", } path = PlacesClient.common_folder_path(**expected) @@ -1507,7 +3163,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "oyster" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -1517,7 +3173,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "nudibranch", + "organization": "mussel", } path = PlacesClient.common_organization_path(**expected) @@ -1527,7 +3183,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "cuttlefish" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -1537,7 +3193,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "mussel", + "project": "nautilus", } path = PlacesClient.common_project_path(**expected) @@ -1547,8 +3203,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "winkle" - location = "nautilus" + project = "scallop" + location = "abalone" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -1559,8 +3215,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "scallop", - "location": "abalone", + "project": "squid", + "location": "clam", } path = PlacesClient.common_location_path(**expected)