Metadata-Version: 2.5
Name: indiaddr
Version: 0.1.0
Summary: Parse and validate messy Indian addresses into structured fields.
Author-email: Priyam Desai <priyamdesai1312@gmail.com>
License: MIT
License-File: LICENSE
Keywords: address,geocoding,india,nlp,parser,pincode,validation
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.8
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 :: Text Processing :: Linguistic
Requires-Python: >=3.8
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# indiaddr

**Parse and validate messy Indian addresses into structured fields.**

Western address parsers (`usaddress`, `libpostal`, Parserator) are built for
US/European formats and stumble on Indian addresses — which love landmarks
("opposite the temple"), locality suffixes (Nagar, Society, Colony), and
irregular ordering. `indiaddr` is built specifically for the Indian case, and
unlike plain parsers it can also **validate** an address by cross-checking the
pincode against the stated city and state.

Zero runtime dependencies. Pure Python.

```bash
pip install indiaddr
```

## Quick start

```python
from indiaddr import parse, validate

a = parse("B-402 Shitalnath Apt, opp Jain temple, Paldi, Ahmedabad, Guj 380007")

a.building   # 'B-402 Shitalnath Apartment'   (abbreviation expanded)
a.landmark   # 'opposite Jain temple'          (trigger normalized)
a.area       # 'Paldi'
a.city       # 'Ahmedabad'
a.state      # 'Gujarat'                        (expanded from 'Guj')
a.pincode    # '380007'

a.to_dict()
a.confidence # {'pincode': 0.99, 'state': 0.95, 'city': 0.9, ...}
```

## Validation — the part plain parsers skip

`indiaddr` doesn't just split an address; it checks whether the parts are
mutually consistent, catching data-entry errors:

```python
from indiaddr import validate

v = validate("Bandra, Mumbai, Delhi 110001")
v.valid       # False
v.warnings    # ["City 'Mumbai' is in 'Maharashtra', not the stated state 'Delhi'."]

v = validate("Ring Road, Surat, Gujarat 600001")
v.valid       # False
v.warnings    # ["Pincode '600001' (zone 6) does not match state 'Gujarat'."]
```

Checks performed:

- `pincode_present` / `pincode_format_valid` — is there a structurally valid PIN?
- `pincode_matches_state` — does the PIN's postal zone match the state?
- `city_matches_state` — does a known city sit in the stated state?
- `state_recognized` — is the state a real Indian state/UT?

## What it extracts

| Field      | How it's found                                            |
|------------|-----------------------------------------------------------|
| `pincode`  | 6-digit number; validated against Indian PIN zones        |
| `state`    | Fixed list of 28 states + 8 UTs, plus aliases/misspellings |
| `city`     | Seed list of major cities, cross-checked with the pincode |
| `landmark` | Trigger words: near / opposite / behind / beside / ...    |
| `sublocality` | Named cluster: Society / Apartment / Complex / Tower / ... |
| `area`     | Broader locality: Nagar / Colony / Sector / West / East / ...  |
| `building` | Flat / plot / floor number (peeled off the complex name)  |

Indian addresses often carry **two** locality parts — a named society/complex
*and* a broader area (e.g. "Sunrise Society, Andheri West"). `indiaddr` models
both, splitting a leading flat code off the complex name:

```python
a = parse("Flat 3, Sunrise Society, Andheri West, Mumbai 400058")
a.building      # 'Flat 3'
a.sublocality   # 'Sunrise Society'
a.area          # 'Andheri West'
```

It also **normalizes**: `Apt → Apartment`, `Rd → Road`, `opp → opposite`,
`Bangalore → Bengaluru`, `Guj → Gujarat`.

## Honest limitations

This is a hard problem and `indiaddr` is deliberately scoped:

- The **city list is a high-frequency seed**, not exhaustive. Cities outside it
  won't be recognized or cross-checked (they'll fall through to `area`).
  For full pincode coverage, pair it with the
  [`indiapins`](https://pypi.org/project/indiapins/) dataset.
- **Building vs area** disambiguation is heuristic. On very irregular inputs a
  chunk can land in the wrong field. Confidence scores flag the shaky ones.
- It does **not** geocode (no coordinates) — it parses and validates text.

Contributions that expand the city/area data or improve the heuristics are
welcome.

## Roadmap (v0.2+)

- Larger bundled city/locality dataset
- Optional `indiapins` integration for pincode → city auto-fill
- Address **normalization to a canonical single-line format** (for deduping)
- Confidence-weighted "best guess" for ambiguous chunks

## License

MIT
