Metadata-Version: 2.4
Name: gmaps-async-client
Version: 0.0.2
Summary: Python wrapper for Google Maps APIs (Places & Geocoding)
Author-email: Jonathan Oren <jonathanoren98@gmail.com>
Maintainer-email: Jonathan Oren <jonathanoren98@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/asparagusbeef/gmaps-async-client
Project-URL: Documentation, https://asparagusbeef.github.io/gmaps-async-client
Project-URL: Repository, https://github.com/asparagusbeef/gmaps-async-client
Project-URL: Issues, https://github.com/asparagusbeef/gmaps-async-client/issues
Project-URL: Changelog, https://github.com/asparagusbeef/gmaps-async-client/blob/main/CHANGELOG.md
Keywords: gmaps,api,transportation,geocoding,places,autocomplete
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.25.0
Requires-Dist: pydantic<3.0.0,>=2.5.0
Provides-Extra: google
Requires-Dist: google-auth>=2.0.0; extra == "google"
Requires-Dist: google-auth-stubs>=0.3.0; extra == "google"
Provides-Extra: dev
Requires-Dist: pytest>=8.4.0; extra == "dev"
Requires-Dist: pytest-asyncio>=1.1.0; extra == "dev"
Requires-Dist: pytest-cov>=6.1.0; extra == "dev"
Requires-Dist: pytest-mock>=3.14.0; extra == "dev"
Requires-Dist: httpx[mock]>=0.25.0; extra == "dev"
Requires-Dist: respx>=0.21.0; extra == "dev"
Requires-Dist: ruff>=0.12.12; extra == "dev"
Requires-Dist: mypy>=1.17.1; extra == "dev"
Requires-Dist: black>=24.0.0; extra == "dev"
Requires-Dist: isort>=6.0.0; extra == "dev"
Requires-Dist: bandit>=1.8.6; extra == "dev"
Requires-Dist: pre-commit>=4.3.0; extra == "dev"
Requires-Dist: build>=1.3.0; extra == "dev"
Requires-Dist: twine>=6.2.0; extra == "dev"
Provides-Extra: test
Requires-Dist: pytest>=8.4.2; extra == "test"
Requires-Dist: pytest-asyncio>=1.1.0; extra == "test"
Requires-Dist: pytest-cov>=6.2.1; extra == "test"
Requires-Dist: pytest-mock>=3.14.0; extra == "test"
Requires-Dist: httpx[mock]>=0.25.0; extra == "test"
Requires-Dist: respx>=0.21.0; extra == "test"
Requires-Dist: pytest-env>=1.1.0; extra == "test"
Requires-Dist: trio>=0.27.0; extra == "test"
Requires-Dist: python-dotenv>=1.0.0; extra == "test"
Dynamic: license-file

# 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.svg)](https://badge.fury.io/py/gmaps)
[![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 Maps API access with proper typing and rate limiting.
**Solution**: Unified client with Places (nearby/text search, details, autocomplete) and Geocoding APIs.

## 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"
        )

        # 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

```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
)

## 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"
)

# Autocomplete
response = await client.places.autocomplete_simple(
    input_text="coffee shop",
    included_primary_types=["cafe"]
)
```

### Geocoding API

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

### 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
# Minimal
field_mask = ["places.displayName", "places.location"]

# Detailed
field_mask = ["places.displayName", "places.rating", "places.reviews"]
```

## 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, ExtraComputation
)
```



## Requirements

- Python 3.9+
- httpx >= 0.25.0
- pydantic >= 2.0.0
- 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)
