Metadata-Version: 2.4
Name: copomex-py-client
Version: 0.1.0
Summary: Cliente Python para la API de Copomex — códigos postales de México
License: MIT
Project-URL: Homepage, https://copomex.com
Project-URL: Documentation, https://docs.copomex.com/libraries/python
Project-URL: Repository, https://github.com/multiservicios-web/copomex-py-client
Project-URL: Bug Tracker, https://github.com/multiservicios-web/copomex-py-client/issues
Keywords: copomex,codigo postal,mexico,postal code,api client
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: responses>=0.25; extra == "dev"

<p align="center">
  <img src="assets/logo.png" alt="Copomex" width="96" />
</p>

# copomex-py-client

Cliente Python para la [API de Copomex](https://copomex.com) — consulta de códigos postales, colonias, municipios, estados, localidades, vialidades y geocoding de México.

- Python 3.10+
- Sin dependencias externas más allá de `requests`
- Cubre los 24 endpoints disponibles

---

## Instalación

```bash
pip install copomex-py-client
```

---

## Inicio rápido

```python
from copomex import Copomex

client = Copomex("TU_TOKEN")

info = client.info_cp("06600")
print(info)
```

Puedes usar `token=pruebas` para hacer pruebas sin costo ni registro. Los datos devueltos son aleatorios pero la estructura es real.

---

## Manejo de errores

```python
from copomex import Copomex, CopomexAPIError, CopomexHTTPError

client = Copomex("TU_TOKEN")

try:
    result = client.info_cp("99999")
except CopomexAPIError as e:
    print(f"Error de API [{e.code}]: {e.message}")
except CopomexHTTPError as e:
    print(f"Error HTTP: {e.status_code}")
```

| Excepción | Cuándo se lanza |
|---|---|
| `CopomexAPIError` | La API devuelve `error: true`. Tiene `.code` y `.message`. |
| `CopomexHTTPError` | Respuesta HTTP no exitosa (4xx, 5xx). Tiene `.status_code`. |
| `CopomexError` | Clase base de las dos anteriores. |

---

## Referencia de métodos

### Constructor

```python
Copomex(token: str, timeout: int = 10)
```

| Parámetro | Descripción |
|---|---|
| `token` | Tu token de acceso. Usa `"pruebas"` para desarrollo. |
| `timeout` | Timeout de la petición HTTP en segundos (default: 10). |

---

### Códigos postales

#### `info_cp(cp, *, simplified=False)`
Información completa de un código postal.

Sin `simplified`, devuelve una **lista** (un elemento por colonia del CP). Con `simplified=True`, devuelve un **dict** con datos agregados.

```python
colonias = client.info_cp("06600")       # list[dict]
info     = client.info_cp("06600", simplified=True)  # dict
```

#### `search_cp(texto, *, limit=None)`
Búsqueda por coincidencia parcial de código postal.

```python
client.search_cp("066")
client.search_cp("066", limit=10)
```

#### `get_colonia_por_cp(cp)`
Colonias asociadas a un código postal.

```python
client.get_colonia_por_cp("06600")
```

#### `get_cp_por_estado(estado)`
Todos los códigos postales de un estado.

```python
client.get_cp_por_estado("Jalisco")
```

#### `get_cp_por_municipio(municipio)`
Códigos postales de un municipio.

```python
client.get_cp_por_municipio("Guadalajara")
```

#### `search_cp_advanced(estado, *, limit=None, municipio=None, colonia=None)`
Búsqueda avanzada de CPs con filtros opcionales (coincidencia parcial).

```python
client.search_cp_advanced("Jalisco", municipio="Guadalajara", limit=20)
client.search_cp_advanced("CDMX", colonia="Condesa")
```

#### `get_cp_advanced(estado, *, limit=None, municipio=None, colonia=None)`
Búsqueda exacta de CPs con filtros (coincidencias exactas, no parciales).

```python
client.get_cp_advanced("Jalisco", municipio="Guadalajara")
```

---

### Estados

#### `get_estados()`
Lista de todos los estados de México.

```python
client.get_estados()
```

#### `get_estado_clave()`
Estados con su clave oficial INEGI.

```python
client.get_estado_clave()
```

---

### Municipios

#### `get_municipio_por_estado(estado)`
Municipios de un estado.

```python
client.get_municipio_por_estado("Jalisco")
```

#### `get_municipio_clave_por_estado(estado)`
Municipios con clave INEGI, filtrados por nombre de estado.

```python
client.get_municipio_clave_por_estado("Jalisco")
```

#### `get_municipio_clave_por_clave_estado(clave)`
Municipios con clave INEGI, filtrados por clave de estado.

```python
client.get_municipio_clave_por_clave_estado("14")
```

---

### Colonias

#### `get_colonia_por_municipio(municipio)`
Colonias de un municipio.

```python
client.get_colonia_por_municipio("Guadalajara")
```

#### `get_colonia_por_estado_municipio(estado, municipio)`
Colonias con CP filtradas por estado y municipio.

```python
client.get_colonia_por_estado_municipio("Jalisco", "Guadalajara")
```

---

### Ciudades

#### `get_cities_by_state_code(clave_estado)`
Ciudades de un estado por su clave INEGI.

```python
client.get_cities_by_state_code("14")
```

---

### Localidades

#### `get_localidad_por_estado_municipio(estado, municipio)`
Catálogo de localidades filtrado por nombre de estado y municipio.

```python
client.get_localidad_por_estado_municipio("Jalisco", "Guadalajara")
```

#### `get_localidad_por_clave_estado_municipio(clave_estado, clave_municipio)`
Localidades filtradas por claves INEGI de estado y municipio.

```python
client.get_localidad_por_clave_estado_municipio("14", "039")
```

#### `info_localidad(clave_estado, clave_municipio, clave_localidad)`
Información detallada de una localidad (incluye coordenadas y altitud).

```python
client.info_localidad("14", "039", "0001")
```

---

### Vialidades

#### `get_vialidad(clave_estado, clave_municipio, busqueda, limit, *, clave_localidad=None)`
Búsqueda en el catálogo de más de 3 millones de calles y vialidades.

```python
client.get_vialidad("14", "039", "juarez", 10)
client.get_vialidad("14", "039", "reforma", 5, clave_localidad="0001")
```

#### `get_tipo_vialidad()`
Catálogo de los 22 tipos de vialidad (calle, avenida, boulevard, etc.).

```python
client.get_tipo_vialidad()
```

---

### Geocoding

> Estos métodos consumen **2 créditos** por consulta.

#### `info_cp_geocoding(cp, *, type=None, calle=None, numero=None)`
Convierte un código postal (con calle y número opcionales) a coordenadas lat/lng.

```python
client.info_cp_geocoding("06600")
client.info_cp_geocoding("06600", calle="Insurgentes", numero="123")
```

#### `info_cp_geocoding_reverse(lat, lng)`
Convierte coordenadas lat/lng a dirección postal completa.

```python
client.info_cp_geocoding_reverse(19.4326, -99.1332)
```

---

### Cuenta

#### `consultas_disponibles()`
Saldo de créditos disponibles del token.

```python
client.consultas_disponibles()
```

#### `ultima_actualizacion_db()`
Fecha y hora de la última actualización de la base de datos.

```python
client.ultima_actualizacion_db()
```

---

## Créditos

| Consulta | Créditos |
|---|---|
| Todos los endpoints excepto geocoding | 1 |
| `info_cp_geocoding` | 2 |
| `info_cp_geocoding_reverse` | 2 |

---

## Licencia

[Multiservicios Web](https://multiservicios-web.com.mx) - 
[Copomex](https://copomex.com)
