pinsearch-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pinsearch_sdk-0.1.0/LICENSE +21 -0
- pinsearch_sdk-0.1.0/PKG-INFO +219 -0
- pinsearch_sdk-0.1.0/README.md +209 -0
- pinsearch_sdk-0.1.0/pyproject.toml +8 -0
- pinsearch_sdk-0.1.0/setup.cfg +4 -0
- pinsearch_sdk-0.1.0/src/__init__.py +0 -0
- pinsearch_sdk-0.1.0/src/client.py +167 -0
- pinsearch_sdk-0.1.0/src/pinsearch_sdk.egg-info/PKG-INFO +219 -0
- pinsearch_sdk-0.1.0/src/pinsearch_sdk.egg-info/SOURCES.txt +9 -0
- pinsearch_sdk-0.1.0/src/pinsearch_sdk.egg-info/dependency_links.txt +1 -0
- pinsearch_sdk-0.1.0/src/pinsearch_sdk.egg-info/top_level.txt +2 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amit Bhagat
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pinsearch-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: search Indian postal information by PIN code, state, or district
|
|
5
|
+
Author-email: Amit Bhagat <amitbhagat621@gmail.com>
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
# pinsearch-sdk
|
|
12
|
+
|
|
13
|
+
A lightweight Python SDK for searching Indian Postal Index Number (PIN) code data.
|
|
14
|
+
|
|
15
|
+
`pinsearch-sdk` provides fast offline access to Indian postal information, including:
|
|
16
|
+
|
|
17
|
+
* PIN code lookups
|
|
18
|
+
* State-based searches
|
|
19
|
+
* District-based searches
|
|
20
|
+
* Office information
|
|
21
|
+
* Geographic coordinates (when available)
|
|
22
|
+
|
|
23
|
+
The SDK ships with a pre-indexed dataset and requires no external API or internet connection.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install pinsearch-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
or with uv:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv add pinsearch-sdk
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from pinsearch_sdk import PinSearch
|
|
45
|
+
|
|
46
|
+
client = PinSearch()
|
|
47
|
+
|
|
48
|
+
record = client.get("504273")
|
|
49
|
+
|
|
50
|
+
print(record.officename)
|
|
51
|
+
print(record.district)
|
|
52
|
+
print(record.statename)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Output:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
Karjibheempur B.O
|
|
59
|
+
MANCHERIAL
|
|
60
|
+
TELANGANA
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Lookup by PIN Code
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from pinsearch_sdk import PinSearch
|
|
69
|
+
|
|
70
|
+
client = PinSearch()
|
|
71
|
+
|
|
72
|
+
record = client.get("504273")
|
|
73
|
+
|
|
74
|
+
print(record)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
PincodeData(
|
|
81
|
+
circlename='Telangana Circle',
|
|
82
|
+
regionname='Hyderabad Region',
|
|
83
|
+
divisionname='Adilabad Division',
|
|
84
|
+
officename='Karjibheempur B.O',
|
|
85
|
+
pincode='504273',
|
|
86
|
+
officetype='BO',
|
|
87
|
+
delivery='Delivery',
|
|
88
|
+
district='MANCHERIAL',
|
|
89
|
+
statename='TELANGANA',
|
|
90
|
+
latitude=19.335427,
|
|
91
|
+
longitude=79.4928856
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If the PIN code does not exist:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
record = client.get("000000")
|
|
99
|
+
|
|
100
|
+
print(record)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
None
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Search by State
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from pinsearch_sdk import PinSearch
|
|
113
|
+
|
|
114
|
+
client = PinSearch()
|
|
115
|
+
|
|
116
|
+
for office in client.by_state("TELANGANA"):
|
|
117
|
+
print(office.officename)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The method returns an iterator and yields `PincodeData` objects lazily.
|
|
121
|
+
|
|
122
|
+
Convert to a list if needed:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
results = list(client.by_state("TELANGANA"))
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Search by District
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from pinsearch_sdk import PinSearch
|
|
134
|
+
|
|
135
|
+
client = PinSearch()
|
|
136
|
+
|
|
137
|
+
for office in client.by_district("MANCHERIAL"):
|
|
138
|
+
print(office.pincode)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Iterate Over the Entire Dataset
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from pinsearch_sdk import PinSearch
|
|
147
|
+
|
|
148
|
+
client = PinSearch()
|
|
149
|
+
|
|
150
|
+
for office in client:
|
|
151
|
+
print(office.pincode)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Data Model
|
|
157
|
+
|
|
158
|
+
Every search method returns a `PincodeData` object.
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
@dataclass
|
|
162
|
+
class PincodeData:
|
|
163
|
+
circlename: str
|
|
164
|
+
regionname: str
|
|
165
|
+
divisionname: str
|
|
166
|
+
officename: str
|
|
167
|
+
pincode: str
|
|
168
|
+
officetype: str
|
|
169
|
+
delivery: str
|
|
170
|
+
district: str
|
|
171
|
+
statename: str
|
|
172
|
+
latitude: float | None
|
|
173
|
+
longitude: float | None
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Example
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from pinsearch_sdk import PinSearch
|
|
182
|
+
|
|
183
|
+
client = PinSearch()
|
|
184
|
+
|
|
185
|
+
record = client.get("504273")
|
|
186
|
+
|
|
187
|
+
print(record.officename)
|
|
188
|
+
print(record.latitude)
|
|
189
|
+
print(record.longitude)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Output:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
Karjibheempur B.O
|
|
196
|
+
19.335427
|
|
197
|
+
79.4928856
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Performance
|
|
203
|
+
|
|
204
|
+
* PIN code lookups are O(1)
|
|
205
|
+
* State searches use pre-built indexes
|
|
206
|
+
* District searches use pre-built indexes
|
|
207
|
+
* Search results are yielded lazily to reduce memory usage
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Data Source
|
|
212
|
+
|
|
213
|
+
The information is derived from publicly available dataset from [Open Government Data (OGD) Platform India](https://www.data.gov.in)
|
|
214
|
+
The data is intended for informational purposes and may not always reflect the latest changes made by India Post.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# pinsearch-sdk
|
|
2
|
+
|
|
3
|
+
A lightweight Python SDK for searching Indian Postal Index Number (PIN) code data.
|
|
4
|
+
|
|
5
|
+
`pinsearch-sdk` provides fast offline access to Indian postal information, including:
|
|
6
|
+
|
|
7
|
+
* PIN code lookups
|
|
8
|
+
* State-based searches
|
|
9
|
+
* District-based searches
|
|
10
|
+
* Office information
|
|
11
|
+
* Geographic coordinates (when available)
|
|
12
|
+
|
|
13
|
+
The SDK ships with a pre-indexed dataset and requires no external API or internet connection.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install pinsearch-sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
or with uv:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uv add pinsearch-sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from pinsearch_sdk import PinSearch
|
|
35
|
+
|
|
36
|
+
client = PinSearch()
|
|
37
|
+
|
|
38
|
+
record = client.get("504273")
|
|
39
|
+
|
|
40
|
+
print(record.officename)
|
|
41
|
+
print(record.district)
|
|
42
|
+
print(record.statename)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Output:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
Karjibheempur B.O
|
|
49
|
+
MANCHERIAL
|
|
50
|
+
TELANGANA
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Lookup by PIN Code
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from pinsearch_sdk import PinSearch
|
|
59
|
+
|
|
60
|
+
client = PinSearch()
|
|
61
|
+
|
|
62
|
+
record = client.get("504273")
|
|
63
|
+
|
|
64
|
+
print(record)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
PincodeData(
|
|
71
|
+
circlename='Telangana Circle',
|
|
72
|
+
regionname='Hyderabad Region',
|
|
73
|
+
divisionname='Adilabad Division',
|
|
74
|
+
officename='Karjibheempur B.O',
|
|
75
|
+
pincode='504273',
|
|
76
|
+
officetype='BO',
|
|
77
|
+
delivery='Delivery',
|
|
78
|
+
district='MANCHERIAL',
|
|
79
|
+
statename='TELANGANA',
|
|
80
|
+
latitude=19.335427,
|
|
81
|
+
longitude=79.4928856
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
If the PIN code does not exist:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
record = client.get("000000")
|
|
89
|
+
|
|
90
|
+
print(record)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
None
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Search by State
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from pinsearch_sdk import PinSearch
|
|
103
|
+
|
|
104
|
+
client = PinSearch()
|
|
105
|
+
|
|
106
|
+
for office in client.by_state("TELANGANA"):
|
|
107
|
+
print(office.officename)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The method returns an iterator and yields `PincodeData` objects lazily.
|
|
111
|
+
|
|
112
|
+
Convert to a list if needed:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
results = list(client.by_state("TELANGANA"))
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Search by District
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from pinsearch_sdk import PinSearch
|
|
124
|
+
|
|
125
|
+
client = PinSearch()
|
|
126
|
+
|
|
127
|
+
for office in client.by_district("MANCHERIAL"):
|
|
128
|
+
print(office.pincode)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Iterate Over the Entire Dataset
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from pinsearch_sdk import PinSearch
|
|
137
|
+
|
|
138
|
+
client = PinSearch()
|
|
139
|
+
|
|
140
|
+
for office in client:
|
|
141
|
+
print(office.pincode)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Data Model
|
|
147
|
+
|
|
148
|
+
Every search method returns a `PincodeData` object.
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
@dataclass
|
|
152
|
+
class PincodeData:
|
|
153
|
+
circlename: str
|
|
154
|
+
regionname: str
|
|
155
|
+
divisionname: str
|
|
156
|
+
officename: str
|
|
157
|
+
pincode: str
|
|
158
|
+
officetype: str
|
|
159
|
+
delivery: str
|
|
160
|
+
district: str
|
|
161
|
+
statename: str
|
|
162
|
+
latitude: float | None
|
|
163
|
+
longitude: float | None
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Example
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from pinsearch_sdk import PinSearch
|
|
172
|
+
|
|
173
|
+
client = PinSearch()
|
|
174
|
+
|
|
175
|
+
record = client.get("504273")
|
|
176
|
+
|
|
177
|
+
print(record.officename)
|
|
178
|
+
print(record.latitude)
|
|
179
|
+
print(record.longitude)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Output:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
Karjibheempur B.O
|
|
186
|
+
19.335427
|
|
187
|
+
79.4928856
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Performance
|
|
193
|
+
|
|
194
|
+
* PIN code lookups are O(1)
|
|
195
|
+
* State searches use pre-built indexes
|
|
196
|
+
* District searches use pre-built indexes
|
|
197
|
+
* Search results are yielded lazily to reduce memory usage
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Data Source
|
|
202
|
+
|
|
203
|
+
The information is derived from publicly available dataset from [Open Government Data (OGD) Platform India](https://www.data.gov.in)
|
|
204
|
+
The data is intended for informational purposes and may not always reflect the latest changes made by India Post.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pinsearch-sdk"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
authors = [{name = "Amit Bhagat", "email" = "amitbhagat621@gmail.com"}]
|
|
5
|
+
description = "search Indian postal information by PIN code, state, or district"
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
requires-python = ">=3.12"
|
|
8
|
+
dependencies = []
|
|
File without changes
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from collections.abc import Iterator
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from functools import lru_cache
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Dict
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(slots=True)
|
|
11
|
+
class PincodeData:
|
|
12
|
+
circlename: str
|
|
13
|
+
regionname: str
|
|
14
|
+
divisionname: str
|
|
15
|
+
officename: str
|
|
16
|
+
pincode: str
|
|
17
|
+
officetype: str
|
|
18
|
+
delivery: str
|
|
19
|
+
district: str
|
|
20
|
+
statename: str
|
|
21
|
+
latitude: float | None
|
|
22
|
+
longitude: float | None
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def from_dict(cls, data: dict) -> "PincodeData":
|
|
26
|
+
lat = data.get("latitude")
|
|
27
|
+
lon = data.get("longitude")
|
|
28
|
+
|
|
29
|
+
return cls(
|
|
30
|
+
**{
|
|
31
|
+
**data,
|
|
32
|
+
"latitude": None if lat in ("NA", "", None) else float(lat),
|
|
33
|
+
"longitude": None if lon in ("NA", "", None) else float(lon),
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class PinSearch:
|
|
39
|
+
"""
|
|
40
|
+
Search and retrieve Indian postal information using PIN codes,
|
|
41
|
+
state names, and district names.
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
The dataset is loaded once and cached in memory for fast lookups.
|
|
45
|
+
Additional indexes are built during initialization to provide
|
|
46
|
+
efficient state and district searches.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
data_file : str | pathlib.Path, optional
|
|
51
|
+
Path to the JSON dataset file. Defaults to
|
|
52
|
+
``"pincode_data.json"``.
|
|
53
|
+
|
|
54
|
+
Examples
|
|
55
|
+
--------
|
|
56
|
+
Create a client:
|
|
57
|
+
|
|
58
|
+
>>> pins = PinSearch()
|
|
59
|
+
|
|
60
|
+
Lookup a specific PIN code:
|
|
61
|
+
|
|
62
|
+
>>> record = pins.get("504273")
|
|
63
|
+
>>> record.officename
|
|
64
|
+
'Karjibheempur B.O'
|
|
65
|
+
|
|
66
|
+
Search by state:
|
|
67
|
+
|
|
68
|
+
>>> for office in pins.by_state("TELANGANA"):
|
|
69
|
+
... print(office.pincode)
|
|
70
|
+
|
|
71
|
+
Search by district:
|
|
72
|
+
|
|
73
|
+
>>> for office in pins.by_district("MANCHERIAL"):
|
|
74
|
+
... print(office.officename)
|
|
75
|
+
|
|
76
|
+
Iterate over the entire dataset:
|
|
77
|
+
|
|
78
|
+
>>> for office in pins:
|
|
79
|
+
... print(office.pincode)
|
|
80
|
+
|
|
81
|
+
Get the total number of records:
|
|
82
|
+
|
|
83
|
+
>>> len(pins)
|
|
84
|
+
|
|
85
|
+
Notes
|
|
86
|
+
-----
|
|
87
|
+
- PIN code lookups are performed in constant time (O(1)).
|
|
88
|
+
- State and district searches use pre-built indexes for fast
|
|
89
|
+
retrieval.
|
|
90
|
+
- Search methods return iterators and yield ``PincodeData``
|
|
91
|
+
objects lazily.
|
|
92
|
+
- Latitude and longitude values are converted to ``float`` when
|
|
93
|
+
available. Missing coordinates are represented as ``None``.
|
|
94
|
+
|
|
95
|
+
Attributes
|
|
96
|
+
----------
|
|
97
|
+
_DATA_FILE : pathlib.Path
|
|
98
|
+
Path to the dataset file.
|
|
99
|
+
|
|
100
|
+
_state_index : collections.defaultdict[list]
|
|
101
|
+
Internal state-based lookup index.
|
|
102
|
+
|
|
103
|
+
_district_index : collections.defaultdict[list]
|
|
104
|
+
Internal district-based lookup index.
|
|
105
|
+
|
|
106
|
+
See Also
|
|
107
|
+
--------
|
|
108
|
+
PincodeData
|
|
109
|
+
Dataclass representing a postal record.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
def __init__(self):
|
|
113
|
+
self._DATA_FILE = Path("pincode_data.json")
|
|
114
|
+
|
|
115
|
+
# Build indexes
|
|
116
|
+
self._state_index = defaultdict(list)
|
|
117
|
+
self._district_index = defaultdict(list)
|
|
118
|
+
self._build_indexes()
|
|
119
|
+
|
|
120
|
+
def __iter__(self) -> Iterator[PincodeData]:
|
|
121
|
+
for record in self._read_pincode_data().values():
|
|
122
|
+
yield PincodeData.from_dict(record)
|
|
123
|
+
|
|
124
|
+
def __len__(self) -> int:
|
|
125
|
+
return len(self._read_pincode_data())
|
|
126
|
+
|
|
127
|
+
@lru_cache(maxsize=1)
|
|
128
|
+
def _read_pincode_data(self) -> Dict:
|
|
129
|
+
with open(self._DATA_FILE, encoding="utf-8") as f:
|
|
130
|
+
return json.load(f)
|
|
131
|
+
|
|
132
|
+
def _build_indexes(self) -> None:
|
|
133
|
+
data = self._read_pincode_data()
|
|
134
|
+
|
|
135
|
+
for record in data.values():
|
|
136
|
+
self._state_index[record["statename"].upper()].append(record)
|
|
137
|
+
|
|
138
|
+
self._district_index[record["district"].upper()].append(record)
|
|
139
|
+
|
|
140
|
+
def get(self, pincode: int) -> PincodeData | None:
|
|
141
|
+
"""search using a pincode\n
|
|
142
|
+
Example:
|
|
143
|
+
>>> PinSearch().get("000000")
|
|
144
|
+
"""
|
|
145
|
+
data = self._read_pincode_data()
|
|
146
|
+
record = data.get(str(pincode))
|
|
147
|
+
|
|
148
|
+
if record is None:
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
return PincodeData.from_dict(record)
|
|
152
|
+
|
|
153
|
+
def by_state(self, state_name: str) -> Iterator[PincodeData]:
|
|
154
|
+
"""search using a state name\n
|
|
155
|
+
Example:
|
|
156
|
+
>>> PinSearch().by_state("delhi")
|
|
157
|
+
"""
|
|
158
|
+
for record in self._state_index[state_name.upper()]:
|
|
159
|
+
yield PincodeData.from_dict(record)
|
|
160
|
+
|
|
161
|
+
def by_district(self, district: str) -> Iterator[PincodeData]:
|
|
162
|
+
"""search using a district\n
|
|
163
|
+
Example:
|
|
164
|
+
>>> PinSearch().by_district("delhi")
|
|
165
|
+
"""
|
|
166
|
+
for record in self._district_index[district.upper()]:
|
|
167
|
+
yield PincodeData.from_dict(record)
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pinsearch-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: search Indian postal information by PIN code, state, or district
|
|
5
|
+
Author-email: Amit Bhagat <amitbhagat621@gmail.com>
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
# pinsearch-sdk
|
|
12
|
+
|
|
13
|
+
A lightweight Python SDK for searching Indian Postal Index Number (PIN) code data.
|
|
14
|
+
|
|
15
|
+
`pinsearch-sdk` provides fast offline access to Indian postal information, including:
|
|
16
|
+
|
|
17
|
+
* PIN code lookups
|
|
18
|
+
* State-based searches
|
|
19
|
+
* District-based searches
|
|
20
|
+
* Office information
|
|
21
|
+
* Geographic coordinates (when available)
|
|
22
|
+
|
|
23
|
+
The SDK ships with a pre-indexed dataset and requires no external API or internet connection.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install pinsearch-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
or with uv:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv add pinsearch-sdk
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from pinsearch_sdk import PinSearch
|
|
45
|
+
|
|
46
|
+
client = PinSearch()
|
|
47
|
+
|
|
48
|
+
record = client.get("504273")
|
|
49
|
+
|
|
50
|
+
print(record.officename)
|
|
51
|
+
print(record.district)
|
|
52
|
+
print(record.statename)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Output:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
Karjibheempur B.O
|
|
59
|
+
MANCHERIAL
|
|
60
|
+
TELANGANA
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Lookup by PIN Code
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from pinsearch_sdk import PinSearch
|
|
69
|
+
|
|
70
|
+
client = PinSearch()
|
|
71
|
+
|
|
72
|
+
record = client.get("504273")
|
|
73
|
+
|
|
74
|
+
print(record)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
PincodeData(
|
|
81
|
+
circlename='Telangana Circle',
|
|
82
|
+
regionname='Hyderabad Region',
|
|
83
|
+
divisionname='Adilabad Division',
|
|
84
|
+
officename='Karjibheempur B.O',
|
|
85
|
+
pincode='504273',
|
|
86
|
+
officetype='BO',
|
|
87
|
+
delivery='Delivery',
|
|
88
|
+
district='MANCHERIAL',
|
|
89
|
+
statename='TELANGANA',
|
|
90
|
+
latitude=19.335427,
|
|
91
|
+
longitude=79.4928856
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If the PIN code does not exist:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
record = client.get("000000")
|
|
99
|
+
|
|
100
|
+
print(record)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
None
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Search by State
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from pinsearch_sdk import PinSearch
|
|
113
|
+
|
|
114
|
+
client = PinSearch()
|
|
115
|
+
|
|
116
|
+
for office in client.by_state("TELANGANA"):
|
|
117
|
+
print(office.officename)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The method returns an iterator and yields `PincodeData` objects lazily.
|
|
121
|
+
|
|
122
|
+
Convert to a list if needed:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
results = list(client.by_state("TELANGANA"))
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Search by District
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from pinsearch_sdk import PinSearch
|
|
134
|
+
|
|
135
|
+
client = PinSearch()
|
|
136
|
+
|
|
137
|
+
for office in client.by_district("MANCHERIAL"):
|
|
138
|
+
print(office.pincode)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Iterate Over the Entire Dataset
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from pinsearch_sdk import PinSearch
|
|
147
|
+
|
|
148
|
+
client = PinSearch()
|
|
149
|
+
|
|
150
|
+
for office in client:
|
|
151
|
+
print(office.pincode)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Data Model
|
|
157
|
+
|
|
158
|
+
Every search method returns a `PincodeData` object.
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
@dataclass
|
|
162
|
+
class PincodeData:
|
|
163
|
+
circlename: str
|
|
164
|
+
regionname: str
|
|
165
|
+
divisionname: str
|
|
166
|
+
officename: str
|
|
167
|
+
pincode: str
|
|
168
|
+
officetype: str
|
|
169
|
+
delivery: str
|
|
170
|
+
district: str
|
|
171
|
+
statename: str
|
|
172
|
+
latitude: float | None
|
|
173
|
+
longitude: float | None
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Example
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from pinsearch_sdk import PinSearch
|
|
182
|
+
|
|
183
|
+
client = PinSearch()
|
|
184
|
+
|
|
185
|
+
record = client.get("504273")
|
|
186
|
+
|
|
187
|
+
print(record.officename)
|
|
188
|
+
print(record.latitude)
|
|
189
|
+
print(record.longitude)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Output:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
Karjibheempur B.O
|
|
196
|
+
19.335427
|
|
197
|
+
79.4928856
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Performance
|
|
203
|
+
|
|
204
|
+
* PIN code lookups are O(1)
|
|
205
|
+
* State searches use pre-built indexes
|
|
206
|
+
* District searches use pre-built indexes
|
|
207
|
+
* Search results are yielded lazily to reduce memory usage
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Data Source
|
|
212
|
+
|
|
213
|
+
The information is derived from publicly available dataset from [Open Government Data (OGD) Platform India](https://www.data.gov.in)
|
|
214
|
+
The data is intended for informational purposes and may not always reflect the latest changes made by India Post.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|