gmaps-async-client


Namegmaps-async-client JSON
Version 1.0.1 PyPI version JSON
download
home_pageNone
SummaryPython wrapper for Google Maps APIs (Places & Geocoding)
upload_time2025-09-06 19:19:49
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseMIT
keywords gmaps api transportation geocoding places autocomplete
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # gmaps-async-client

Async Python client for Google Maps APIs (Places & Geocoding) with httpx and Pydantic.

[![codecov](https://codecov.io/gh/asparagusbeef/gmaps-async-client/branch/main/graph/badge.svg)](https://codecov.io/gh/asparagusbeef/gmaps-async-client)
[![PyPI version](https://badge.fury.io/py/gmaps-async-client.svg)](https://badge.fury.io/py/gmaps-async-client)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://python.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)

**Problem**: Need async Google Places (New) and Geocoding API access with proper typing, rate limiting, and flexible configuration.
**Solution**: Unified client with Places (nearby/text search, details, autocomplete) and Geocoding APIs, HTTP/2 support, and centralized settings.

## Note

This is a work-in-progress. Response models are not yet implemented, and not all routes are implemented. Feel free to contribute!

## Installation

```bash
# Basic
pip install gmaps-async-client

# With Google ADC auth support
pip install gmaps-async-client[google]
```

## Quick Start

```python
from gmaps import GmapsClient

async def main():
    async with GmapsClient() as client:
        # Places API - search nearby
        response = await client.places.nearby_search_simple(
            latitude=37.7749, longitude=-122.4194, radius=1000
        )

        # Places API - text search
        response = await client.places.text_search_simple(
            query="coffee shops in San Francisco"
        )

        # Geocoding API - address to coords
        response = await client.geocoding.geocode_simple(
            address="1600 Amphitheatre Parkway, Mountain View, CA"
        )

        # Geocoding API - place ID to address
        response = await client.geocoding.place_geocode_simple(
            place_id="ChIJd8BlQ2BZwokRAFUEcm_qrcA"
        )

        # Parse responses
        data = response.json()
        print(data)

import asyncio
asyncio.run(main())
```

## Authentication

Auth priority: API key (param/env) → Google ADC → error

```bash
# Option 1: Environment variable
export GOOGLE_PLACES_API_KEY="your-key"

# Option 2: Google ADC (requires gmaps[google])
gcloud auth application-default login
```

```python
# Explicit API key
client = GmapsClient(api_key="your-key")

# Force ADC mode
client = GmapsClient(auth_mode=AuthMode.ADC)
```


## Configuration

### Basic Configuration

```python
from gmaps import GmapsClient, ClientOptions, RetryConfig
import httpx

options = ClientOptions(
    timeout=httpx.Timeout(30.0),
    retry=RetryConfig(max_attempts=3),
    enable_logging=True
)

client = GmapsClient(
    options=options,
    places_qpm=100,      # Places API rate limit
    geocoding_qpm=50     # Geocoding API rate limit
)
```

### Environment Variables

Centralized configuration via environment variables (prefix: `GMAPS_`):

`GMAPS_GOOGLE_PLACES_API_KEY` - The Google Places API key. Also accepts `GOOGLE_PLACES_API_KEY` as an alias.
`GMAPS_STRICT_PLACE_TYPE_VALIDATION` - Whether to strictly validate place types against the types in [Table A](https://developers.google.com/maps/documentation/places/web-service/place-types#table-a). Possible values: `true` or `false`. Default is `true`.

### Custom Type Registration

Register custom place types, components, or extra computations. Useful if the API changes and the SDK is not updated yet.

```python
from gmaps import register_custom, get_custom, clear_custom_registries

# Register custom place types
register_custom("place_types", "custom_restaurant", "special_shop")

# Register custom geocoding components
register_custom("components", "custom_area", "special_zone")

# Register custom extra computations
register_custom("extra_computations", "CUSTOM_COMPUTATION", "SPECIAL_FEATURE")

# View registered values
print(get_custom("place_types"))  # {'custom_restaurant', 'special_shop'}
print(get_custom("components"))   # {'custom_area', 'special_zone'}

# Clear
clear_custom_registries()
```

## API Methods

### Places API

```python
# Nearby search
response = await client.places.nearby_search_simple(
    latitude=37.7749, longitude=-122.4194, radius=1000,
    included_types=["restaurant"], max_results=10
)

# Text search
response = await client.places.text_search_simple(
    query="pizza restaurants", max_results=10
)

# Place details
response = await client.places.place_details_simple(
    place_id="ChIJN1t_tDeuEmsRUsoyG83frY4",
    session_token="your-session-token"  # Optional for billing optimization
)

# Autocomplete
response = await client.places.autocomplete_simple(
    input_text="coffee shop",
    included_primary_types=["cafe"],
    session_token="your-session-token",  # Optional for billing optimization
    field_mask=["suggestions.placePrediction.text.text"]  # Control returned fields
)
```

### Geocoding API

```python
# Address to coordinates
response = await client.geocoding.geocode_simple(
    address="1600 Amphitheatre Parkway, Mountain View, CA"
)

# Place ID to address (place geocoding)
response = await client.geocoding.place_geocode_simple(
    place_id="ChIJd8BlQ2BZwokRAFUEcm_qrcA",
    language="en",
    region="us"
)
```

### Advanced Usage

```python
from gmaps import (
    GmapsClient, NearbySearchRequest, Circle, LatLng,
    LocationRestriction, GeocodingRequest
)

# Full request objects for complex queries
request = NearbySearchRequest(
    location_restriction=LocationRestriction(
        circle=Circle(
            center=LatLng(latitude=37.7749, longitude=-122.4194),
            radius=1500.0
        )
    ),
    included_types=["restaurant"],
    max_result_count=20
)

response = await client.places.nearby_search(
    request=request,
    field_mask=["places.displayName", "places.rating"]
)
```

## Response Handling

```python
response = await client.places.text_search_simple(query="pizza")
data = response.json()

# Places API responses
for place in data.get("places", []):
    name = place.get("displayName", {}).get("text")
    address = place.get("formattedAddress")
    rating = place.get("rating")

# Geocoding API responses
for result in data.get("results", []):
    coords = result["geometry"]["location"]
    lat, lng = coords["lat"], coords["lng"]
```

**Field Masks**: Control returned data for performance
```python
field_mask = ["places.displayName", "places.location"]
```

## Error Handling

```python
import httpx
from gmaps import GmapsClient

async with GmapsClient() as client:
    try:
        response = await client.places.text_search_simple(query="restaurants")
        data = response.json()
    except httpx.HTTPStatusError as e:
        print(f"HTTP {e.response.status_code}: {e.response.text}")
    except httpx.RequestError as e:
        print(f"Network error: {e}")
```

## Available Models

All models can be imported directly from `gmaps`:

```python
from gmaps import (
    # Clients
    GmapsClient, PlacesClient, GeocodingClient,
    # Configuration
    ClientOptions, RateLimitConfig, AuthMode, RetryConfig,
    # Request models
    NearbySearchRequest, TextSearchRequest, DetailsRequest,
    AutocompleteRequest, GeocodingRequest,
    # Location models
    LatLng, Circle, LocationRestriction, LocationBias, Viewport,
    # Component models
    ComponentFilter, Component,
    # Enums
    RankPreference, PriceLevel, EVConnectorType, ExtraComputations,
    # Custom registration hooks
    register_custom, get_custom, clear_custom_registries, CustomField
)
```



## Requirements

- Python 3.9+
- httpx >= 0.25.0
- pydantic >= 2.0.0
- pydantic-settings >= 2.0.0
- h2 >= 4.3.0 (for HTTP/2)
- google-auth (for ADC)

## Links

[GitHub](https://github.com/asparagusbeef/gmaps-async-client) • [PyPI](https://pypi.org/project/gmaps-async-client/) • [Google Maps API](https://developers.google.com/maps)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "gmaps-async-client",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": "Jonathan Oren <jonathanoren98@gmail.com>",
    "keywords": "gmaps, api, transportation, geocoding, places, autocomplete",
    "author": null,
    "author_email": "Jonathan Oren <jonathanoren98@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/72/07/1ed63a82d30a129606b5dae9593100f01d2fb044ca871b9ac3ac150e3eb6/gmaps_async_client-1.0.1.tar.gz",
    "platform": null,
    "description": "# gmaps-async-client\n\nAsync Python client for Google Maps APIs (Places & Geocoding) with httpx and Pydantic.\n\n[![codecov](https://codecov.io/gh/asparagusbeef/gmaps-async-client/branch/main/graph/badge.svg)](https://codecov.io/gh/asparagusbeef/gmaps-async-client)\n[![PyPI version](https://badge.fury.io/py/gmaps-async-client.svg)](https://badge.fury.io/py/gmaps-async-client)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://python.org)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)\n[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)\n\n**Problem**: Need async Google Places (New) and Geocoding API access with proper typing, rate limiting, and flexible configuration.\n**Solution**: Unified client with Places (nearby/text search, details, autocomplete) and Geocoding APIs, HTTP/2 support, and centralized settings.\n\n## Note\n\nThis is a work-in-progress. Response models are not yet implemented, and not all routes are implemented. Feel free to contribute!\n\n## Installation\n\n```bash\n# Basic\npip install gmaps-async-client\n\n# With Google ADC auth support\npip install gmaps-async-client[google]\n```\n\n## Quick Start\n\n```python\nfrom gmaps import GmapsClient\n\nasync def main():\n    async with GmapsClient() as client:\n        # Places API - search nearby\n        response = await client.places.nearby_search_simple(\n            latitude=37.7749, longitude=-122.4194, radius=1000\n        )\n\n        # Places API - text search\n        response = await client.places.text_search_simple(\n            query=\"coffee shops in San Francisco\"\n        )\n\n        # Geocoding API - address to coords\n        response = await client.geocoding.geocode_simple(\n            address=\"1600 Amphitheatre Parkway, Mountain View, CA\"\n        )\n\n        # Geocoding API - place ID to address\n        response = await client.geocoding.place_geocode_simple(\n            place_id=\"ChIJd8BlQ2BZwokRAFUEcm_qrcA\"\n        )\n\n        # Parse responses\n        data = response.json()\n        print(data)\n\nimport asyncio\nasyncio.run(main())\n```\n\n## Authentication\n\nAuth priority: API key (param/env) \u2192 Google ADC \u2192 error\n\n```bash\n# Option 1: Environment variable\nexport GOOGLE_PLACES_API_KEY=\"your-key\"\n\n# Option 2: Google ADC (requires gmaps[google])\ngcloud auth application-default login\n```\n\n```python\n# Explicit API key\nclient = GmapsClient(api_key=\"your-key\")\n\n# Force ADC mode\nclient = GmapsClient(auth_mode=AuthMode.ADC)\n```\n\n\n## Configuration\n\n### Basic Configuration\n\n```python\nfrom gmaps import GmapsClient, ClientOptions, RetryConfig\nimport httpx\n\noptions = ClientOptions(\n    timeout=httpx.Timeout(30.0),\n    retry=RetryConfig(max_attempts=3),\n    enable_logging=True\n)\n\nclient = GmapsClient(\n    options=options,\n    places_qpm=100,      # Places API rate limit\n    geocoding_qpm=50     # Geocoding API rate limit\n)\n```\n\n### Environment Variables\n\nCentralized configuration via environment variables (prefix: `GMAPS_`):\n\n`GMAPS_GOOGLE_PLACES_API_KEY` - The Google Places API key. Also accepts `GOOGLE_PLACES_API_KEY` as an alias.\n`GMAPS_STRICT_PLACE_TYPE_VALIDATION` - Whether to strictly validate place types against the types in [Table A](https://developers.google.com/maps/documentation/places/web-service/place-types#table-a). Possible values: `true` or `false`. Default is `true`.\n\n### Custom Type Registration\n\nRegister custom place types, components, or extra computations. Useful if the API changes and the SDK is not updated yet.\n\n```python\nfrom gmaps import register_custom, get_custom, clear_custom_registries\n\n# Register custom place types\nregister_custom(\"place_types\", \"custom_restaurant\", \"special_shop\")\n\n# Register custom geocoding components\nregister_custom(\"components\", \"custom_area\", \"special_zone\")\n\n# Register custom extra computations\nregister_custom(\"extra_computations\", \"CUSTOM_COMPUTATION\", \"SPECIAL_FEATURE\")\n\n# View registered values\nprint(get_custom(\"place_types\"))  # {'custom_restaurant', 'special_shop'}\nprint(get_custom(\"components\"))   # {'custom_area', 'special_zone'}\n\n# Clear\nclear_custom_registries()\n```\n\n## API Methods\n\n### Places API\n\n```python\n# Nearby search\nresponse = await client.places.nearby_search_simple(\n    latitude=37.7749, longitude=-122.4194, radius=1000,\n    included_types=[\"restaurant\"], max_results=10\n)\n\n# Text search\nresponse = await client.places.text_search_simple(\n    query=\"pizza restaurants\", max_results=10\n)\n\n# Place details\nresponse = await client.places.place_details_simple(\n    place_id=\"ChIJN1t_tDeuEmsRUsoyG83frY4\",\n    session_token=\"your-session-token\"  # Optional for billing optimization\n)\n\n# Autocomplete\nresponse = await client.places.autocomplete_simple(\n    input_text=\"coffee shop\",\n    included_primary_types=[\"cafe\"],\n    session_token=\"your-session-token\",  # Optional for billing optimization\n    field_mask=[\"suggestions.placePrediction.text.text\"]  # Control returned fields\n)\n```\n\n### Geocoding API\n\n```python\n# Address to coordinates\nresponse = await client.geocoding.geocode_simple(\n    address=\"1600 Amphitheatre Parkway, Mountain View, CA\"\n)\n\n# Place ID to address (place geocoding)\nresponse = await client.geocoding.place_geocode_simple(\n    place_id=\"ChIJd8BlQ2BZwokRAFUEcm_qrcA\",\n    language=\"en\",\n    region=\"us\"\n)\n```\n\n### Advanced Usage\n\n```python\nfrom gmaps import (\n    GmapsClient, NearbySearchRequest, Circle, LatLng,\n    LocationRestriction, GeocodingRequest\n)\n\n# Full request objects for complex queries\nrequest = NearbySearchRequest(\n    location_restriction=LocationRestriction(\n        circle=Circle(\n            center=LatLng(latitude=37.7749, longitude=-122.4194),\n            radius=1500.0\n        )\n    ),\n    included_types=[\"restaurant\"],\n    max_result_count=20\n)\n\nresponse = await client.places.nearby_search(\n    request=request,\n    field_mask=[\"places.displayName\", \"places.rating\"]\n)\n```\n\n## Response Handling\n\n```python\nresponse = await client.places.text_search_simple(query=\"pizza\")\ndata = response.json()\n\n# Places API responses\nfor place in data.get(\"places\", []):\n    name = place.get(\"displayName\", {}).get(\"text\")\n    address = place.get(\"formattedAddress\")\n    rating = place.get(\"rating\")\n\n# Geocoding API responses\nfor result in data.get(\"results\", []):\n    coords = result[\"geometry\"][\"location\"]\n    lat, lng = coords[\"lat\"], coords[\"lng\"]\n```\n\n**Field Masks**: Control returned data for performance\n```python\nfield_mask = [\"places.displayName\", \"places.location\"]\n```\n\n## Error Handling\n\n```python\nimport httpx\nfrom gmaps import GmapsClient\n\nasync with GmapsClient() as client:\n    try:\n        response = await client.places.text_search_simple(query=\"restaurants\")\n        data = response.json()\n    except httpx.HTTPStatusError as e:\n        print(f\"HTTP {e.response.status_code}: {e.response.text}\")\n    except httpx.RequestError as e:\n        print(f\"Network error: {e}\")\n```\n\n## Available Models\n\nAll models can be imported directly from `gmaps`:\n\n```python\nfrom gmaps import (\n    # Clients\n    GmapsClient, PlacesClient, GeocodingClient,\n    # Configuration\n    ClientOptions, RateLimitConfig, AuthMode, RetryConfig,\n    # Request models\n    NearbySearchRequest, TextSearchRequest, DetailsRequest,\n    AutocompleteRequest, GeocodingRequest,\n    # Location models\n    LatLng, Circle, LocationRestriction, LocationBias, Viewport,\n    # Component models\n    ComponentFilter, Component,\n    # Enums\n    RankPreference, PriceLevel, EVConnectorType, ExtraComputations,\n    # Custom registration hooks\n    register_custom, get_custom, clear_custom_registries, CustomField\n)\n```\n\n\n\n## Requirements\n\n- Python 3.9+\n- httpx >= 0.25.0\n- pydantic >= 2.0.0\n- pydantic-settings >= 2.0.0\n- h2 >= 4.3.0 (for HTTP/2)\n- google-auth (for ADC)\n\n## Links\n\n[GitHub](https://github.com/asparagusbeef/gmaps-async-client) \u2022 [PyPI](https://pypi.org/project/gmaps-async-client/) \u2022 [Google Maps API](https://developers.google.com/maps)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python wrapper for Google Maps APIs (Places & Geocoding)",
    "version": "1.0.1",
    "project_urls": {
        "Changelog": "https://github.com/asparagusbeef/gmaps-async-client/blob/main/CHANGELOG.md",
        "Documentation": "https://asparagusbeef.github.io/gmaps-async-client",
        "Homepage": "https://github.com/asparagusbeef/gmaps-async-client",
        "Issues": "https://github.com/asparagusbeef/gmaps-async-client/issues",
        "Repository": "https://github.com/asparagusbeef/gmaps-async-client"
    },
    "split_keywords": [
        "gmaps",
        " api",
        " transportation",
        " geocoding",
        " places",
        " autocomplete"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "04e8394198bc97f175b39638734689b2cf8b8c5367b8e797183258959ecd7a07",
                "md5": "91dc11d776fb476b06a9973fe8a5c9c3",
                "sha256": "f9dc897376cdfb42e340071660f152d6a3befaa38383f5497b196a1f25f13d98"
            },
            "downloads": -1,
            "filename": "gmaps_async_client-1.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "91dc11d776fb476b06a9973fe8a5c9c3",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 33793,
            "upload_time": "2025-09-06T19:19:48",
            "upload_time_iso_8601": "2025-09-06T19:19:48.206897Z",
            "url": "https://files.pythonhosted.org/packages/04/e8/394198bc97f175b39638734689b2cf8b8c5367b8e797183258959ecd7a07/gmaps_async_client-1.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "72071ed63a82d30a129606b5dae9593100f01d2fb044ca871b9ac3ac150e3eb6",
                "md5": "ca41e4de3676b53d191f3027a57aab71",
                "sha256": "28f49c12f53884eb5d6766603ff01f1b9e6e1b6ac88cefaf64df001dafe3fec4"
            },
            "downloads": -1,
            "filename": "gmaps_async_client-1.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "ca41e4de3676b53d191f3027a57aab71",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 61063,
            "upload_time": "2025-09-06T19:19:49",
            "upload_time_iso_8601": "2025-09-06T19:19:49.154417Z",
            "url": "https://files.pythonhosted.org/packages/72/07/1ed63a82d30a129606b5dae9593100f01d2fb044ca871b9ac3ac150e3eb6/gmaps_async_client-1.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-06 19:19:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "asparagusbeef",
    "github_project": "gmaps-async-client",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "gmaps-async-client"
}
        
Elapsed time: 2.16956s