offlineRevGeocoder 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.
@@ -0,0 +1,26 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AminJavadi
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 all
13
+ 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 THE
21
+ SOFTWARE.
22
+
23
+ Natural Earth data notice:
24
+ The bundled geographic cache is derived from Natural Earth data. Natural Earth
25
+ map data is public domain and may be used, modified, and redistributed. See:
26
+ https://www.naturalearthdata.com/about/terms-of-use/
@@ -0,0 +1,3 @@
1
+ include README.md
2
+ include LICENSE
3
+ recursive-include offlineRevGeocoder/data *.pkl
@@ -0,0 +1,131 @@
1
+ Metadata-Version: 2.4
2
+ Name: offlineRevGeocoder
3
+ Version: 0.1.0
4
+ Summary: Fast offline reverse geocoding using a prepared Natural Earth cache
5
+ Home-page: https://github.com/aminjavadi02/reverseGeocoder-py
6
+ Author: AminJavadi
7
+ License: MIT
8
+ Project-URL: Source, https://github.com/aminjavadi02/reverseGeocoder-py
9
+ Project-URL: Natural Earth, https://www.naturalearthdata.com/
10
+ Keywords: geocoder,geocoding,gis,natural-earth,reverse-geocoding
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: GIS
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Dynamic: author
24
+ Dynamic: classifier
25
+ Dynamic: description
26
+ Dynamic: description-content-type
27
+ Dynamic: home-page
28
+ Dynamic: keywords
29
+ Dynamic: license
30
+ Dynamic: license-file
31
+ Dynamic: project-url
32
+ Dynamic: requires-python
33
+ Dynamic: summary
34
+
35
+ # Reverse Geocoder
36
+
37
+ Tiny offline reverse geocoding for Python.
38
+
39
+ `offlineRevGeocoder` takes a latitude and longitude and returns a small `GeoResult`
40
+ object with the matching country, continent, ocean, and nearest city when one is
41
+ close enough. It is intentionally simple: the geographic source data is prepared
42
+ ahead of time, cached as a pickle file, and loaded locally at runtime. No API
43
+ keys, no network requests, no external service latency.
44
+
45
+ The bundled lookup data is derived from [Natural Earth](https://www.naturalearthdata.com/),
46
+ a public domain map dataset. The prepared cache is included so callers can use
47
+ the package immediately.
48
+
49
+ ## Project Info
50
+
51
+ - PyPI package: `offlineRevGeocoder`
52
+ - Import package: `offlineRevGeocoder`
53
+ - Source code: [github.com/aminjavadi02/reverseGeocoder-py](https://github.com/aminjavadi02/reverseGeocoder-py)
54
+ - License: MIT
55
+ - Author: AminJavadi
56
+
57
+ This is an open-source package. Bug reports, fixes, data improvements, and
58
+ documentation updates are welcome; please open an issue or send a pull request
59
+ on GitHub.
60
+
61
+ ## Install
62
+
63
+ ```bash
64
+ pip install offlineRevGeocoder
65
+ ```
66
+
67
+ ## Usage
68
+
69
+ ```python
70
+ from offlineRevGeocoder import get
71
+
72
+ result = get(35.6892, 51.3890)
73
+
74
+ print(result.country) # Iran
75
+ print(result.country_iso2) # IR
76
+ print(result.city) # Tehran
77
+ print(result.precision) # city
78
+ ```
79
+
80
+ ## Common Use Case
81
+
82
+ This package is most useful when you only need a small reverse geocoding answer,
83
+ for example checking whether a user's latitude and longitude are in or near a
84
+ specific city. In that kind of flow, you often do not need to pay for a full
85
+ reverse geocoding API subscription.
86
+
87
+ ```python
88
+ from offlineRevGeocoder import get
89
+
90
+ place = get(35.7000, 51.4000, city_radius_km=25)
91
+
92
+ print(place.city) # Tehran
93
+ print(place.precision) # city
94
+ print(place.city == "Tehran") # True
95
+ ```
96
+
97
+ For a nearby-city check, use `city_radius_km` to control how strict the match
98
+ should be for your product.
99
+
100
+ ## Return Type
101
+
102
+ `get(lat, lon, city_radius_km=50)` returns:
103
+
104
+ ```python
105
+ GeoResult(
106
+ continent: str | None,
107
+ country: str | None,
108
+ country_iso2: str | None,
109
+ country_iso3: str | None,
110
+ ocean: str | None,
111
+ city: str | None,
112
+ city_distance_km: float | None,
113
+ precision: str,
114
+ )
115
+ ```
116
+
117
+ `precision` is one of:
118
+
119
+ - `city`: a nearby city was found.
120
+ - `country`: the point matched a country, but no nearby city was found.
121
+ - `ocean`: the point matched an ocean or marine area.
122
+ - `none`: no matching land or ocean feature was found.
123
+
124
+ ## Data
125
+
126
+ The package uses Natural Earth datasets that were transformed into a compact
127
+ pickle cache at `offlineRevGeocoder/data/reverse_geocoder_cache.pkl`. Natural Earth data is
128
+ public domain, so it can be redistributed with this MIT-licensed package.
129
+
130
+ The code is MIT licensed. Natural Earth requests attribution where possible; this
131
+ README keeps that attribution with the package.
@@ -0,0 +1,97 @@
1
+ # Reverse Geocoder
2
+
3
+ Tiny offline reverse geocoding for Python.
4
+
5
+ `offlineRevGeocoder` takes a latitude and longitude and returns a small `GeoResult`
6
+ object with the matching country, continent, ocean, and nearest city when one is
7
+ close enough. It is intentionally simple: the geographic source data is prepared
8
+ ahead of time, cached as a pickle file, and loaded locally at runtime. No API
9
+ keys, no network requests, no external service latency.
10
+
11
+ The bundled lookup data is derived from [Natural Earth](https://www.naturalearthdata.com/),
12
+ a public domain map dataset. The prepared cache is included so callers can use
13
+ the package immediately.
14
+
15
+ ## Project Info
16
+
17
+ - PyPI package: `offlineRevGeocoder`
18
+ - Import package: `offlineRevGeocoder`
19
+ - Source code: [github.com/aminjavadi02/reverseGeocoder-py](https://github.com/aminjavadi02/reverseGeocoder-py)
20
+ - License: MIT
21
+ - Author: AminJavadi
22
+
23
+ This is an open-source package. Bug reports, fixes, data improvements, and
24
+ documentation updates are welcome; please open an issue or send a pull request
25
+ on GitHub.
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ pip install offlineRevGeocoder
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```python
36
+ from offlineRevGeocoder import get
37
+
38
+ result = get(35.6892, 51.3890)
39
+
40
+ print(result.country) # Iran
41
+ print(result.country_iso2) # IR
42
+ print(result.city) # Tehran
43
+ print(result.precision) # city
44
+ ```
45
+
46
+ ## Common Use Case
47
+
48
+ This package is most useful when you only need a small reverse geocoding answer,
49
+ for example checking whether a user's latitude and longitude are in or near a
50
+ specific city. In that kind of flow, you often do not need to pay for a full
51
+ reverse geocoding API subscription.
52
+
53
+ ```python
54
+ from offlineRevGeocoder import get
55
+
56
+ place = get(35.7000, 51.4000, city_radius_km=25)
57
+
58
+ print(place.city) # Tehran
59
+ print(place.precision) # city
60
+ print(place.city == "Tehran") # True
61
+ ```
62
+
63
+ For a nearby-city check, use `city_radius_km` to control how strict the match
64
+ should be for your product.
65
+
66
+ ## Return Type
67
+
68
+ `get(lat, lon, city_radius_km=50)` returns:
69
+
70
+ ```python
71
+ GeoResult(
72
+ continent: str | None,
73
+ country: str | None,
74
+ country_iso2: str | None,
75
+ country_iso3: str | None,
76
+ ocean: str | None,
77
+ city: str | None,
78
+ city_distance_km: float | None,
79
+ precision: str,
80
+ )
81
+ ```
82
+
83
+ `precision` is one of:
84
+
85
+ - `city`: a nearby city was found.
86
+ - `country`: the point matched a country, but no nearby city was found.
87
+ - `ocean`: the point matched an ocean or marine area.
88
+ - `none`: no matching land or ocean feature was found.
89
+
90
+ ## Data
91
+
92
+ The package uses Natural Earth datasets that were transformed into a compact
93
+ pickle cache at `offlineRevGeocoder/data/reverse_geocoder_cache.pkl`. Natural Earth data is
94
+ public domain, so it can be redistributed with this MIT-licensed package.
95
+
96
+ The code is MIT licensed. Natural Earth requests attribution where possible; this
97
+ README keeps that attribution with the package.
@@ -0,0 +1,3 @@
1
+ from .reverseGeocoder import GeoResult, get
2
+
3
+ __all__ = ["GeoResult", "get"]
@@ -0,0 +1,150 @@
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import pickle
5
+ from dataclasses import dataclass
6
+ from functools import lru_cache
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ CACHE = Path(__file__).resolve().parent / "data" / "reverse_geocoder_cache.pkl"
11
+ CACHE_VERSION = 3
12
+ EARTH_RADIUS_KM = 6371.0088
13
+
14
+
15
+ @dataclass(frozen=True, slots=True)
16
+ class GeoResult:
17
+ continent: str | None
18
+ country: str | None
19
+ country_iso2: str | None
20
+ country_iso3: str | None
21
+ ocean: str | None
22
+ city: str | None
23
+ city_distance_km: float | None
24
+ precision: str
25
+
26
+
27
+ C_CONTINENT, C_COUNTRY, C_ISO2, C_ISO3, C_BBOX, C_RINGS = range(6)
28
+ CITY_NAME, CITY_ISO2, CITY_LAT, CITY_LON = range(4)
29
+ M_NAME, M_BBOX, M_RINGS = range(3)
30
+
31
+
32
+ def get(lat: float, lon: float, *, city_radius_km: float = 50) -> GeoResult:
33
+ _validate(lat, lon)
34
+ data = _load()
35
+ country = _find_country(data, lat, lon)
36
+ ocean = None if country else _find_ocean(data, lat, lon)
37
+ city = _find_city(data, lat, lon, city_radius_km, country)
38
+ return GeoResult(
39
+ continent=country[C_CONTINENT] if country else None,
40
+ country=country[C_COUNTRY] if country else None,
41
+ country_iso2=country[C_ISO2] if country else None,
42
+ country_iso3=country[C_ISO3] if country else None,
43
+ ocean=ocean[M_NAME] if ocean else None,
44
+ city=city[0][CITY_NAME] if city else None,
45
+ city_distance_km=round(city[1], 3) if city else None,
46
+ precision="city" if city else "country" if country else "ocean" if ocean else "none",
47
+ )
48
+
49
+
50
+ @lru_cache(maxsize=1)
51
+ def _load() -> dict[str, Any]:
52
+ if not CACHE.exists():
53
+ raise RuntimeError("missing reverse geocoder cache; run python3 prepare.py")
54
+ with CACHE.open("rb") as f:
55
+ data = pickle.load(f)
56
+ if data.get("version") != CACHE_VERSION:
57
+ raise RuntimeError("stale reverse geocoder cache; run python3 prepare.py")
58
+ return data
59
+
60
+
61
+ def _find_country(data: dict[str, Any], lat: float, lon: float) -> tuple[Any, ...] | None:
62
+ cell = _cell_id(*_cell(lat, lon, data["country_cell"]), data["country_grid_width"])
63
+ for i in data["country_grid"].get(cell, []):
64
+ country = data["countries"][i]
65
+ if _in_bbox(lat, lon, country[C_BBOX]) and _in_polygon(lat, lon, country[C_RINGS]):
66
+ return country
67
+ return None
68
+
69
+
70
+ def _find_ocean(data: dict[str, Any], lat: float, lon: float) -> tuple[Any, ...] | None:
71
+ cell = _cell_id(*_cell(lat, lon, data["marine_cell"]), data["marine_grid_width"])
72
+ for i in data["marine_grid"].get(cell, []):
73
+ ocean = data["marine"][i]
74
+ if _in_bbox(lat, lon, ocean[M_BBOX]) and _in_polygon(lat, lon, ocean[M_RINGS]):
75
+ return ocean
76
+ return None
77
+
78
+
79
+ def _find_city(data: dict[str, Any], lat: float, lon: float, radius_km: float, country: tuple[Any, ...] | None) -> tuple[tuple[Any, ...], float] | None:
80
+ size = data["city_cell"]
81
+ radius_cells = max(1, math.ceil((radius_km / 111.0) / size))
82
+ width = data["city_grid_width"]
83
+ cx, cy = _cell(lat, lon, size)
84
+ best_city = None
85
+ best_distance = radius_km
86
+ country_iso2 = country[C_ISO2] if country else None
87
+ for x in range(cx - radius_cells, cx + radius_cells + 1):
88
+ for y in range(cy - radius_cells, cy + radius_cells + 1):
89
+ for i in data["city_grid"].get(_cell_id(x, y, width), []):
90
+ city = data["cities"][i]
91
+ if country_iso2 and city[CITY_ISO2] and city[CITY_ISO2] != country_iso2:
92
+ continue
93
+ distance = _haversine(lat, lon, city[CITY_LAT], city[CITY_LON])
94
+ if distance <= best_distance:
95
+ best_city = city
96
+ best_distance = distance
97
+ return (best_city, best_distance) if best_city else None
98
+
99
+
100
+ def _in_polygon(lat: float, lon: float, rings: list[tuple]) -> bool:
101
+ inside = False
102
+ for bbox, points in rings:
103
+ if _in_bbox(lat, lon, bbox) and _point_in_ring(lat, lon, points):
104
+ inside = not inside
105
+ return inside
106
+
107
+
108
+ def _point_in_ring(lat: float, lon: float, ring: list[tuple[float, float]]) -> bool:
109
+ inside = False
110
+ j = len(ring) - 1
111
+ for i, (xi, yi) in enumerate(ring):
112
+ xj, yj = ring[j]
113
+ if ((xi <= lon <= xj) or (xj <= lon <= xi)) and ((yi <= lat <= yj) or (yj <= lat <= yi)):
114
+ cross = (lat - yi) * (xj - xi) - (lon - xi) * (yj - yi)
115
+ if abs(cross) <= 1e-10:
116
+ return True
117
+ if (yi > lat) != (yj > lat):
118
+ x_at_lat = (xj - xi) * (lat - yi) / (yj - yi) + xi
119
+ if lon < x_at_lat:
120
+ inside = not inside
121
+ j = i
122
+ return inside
123
+
124
+
125
+ def _in_bbox(lat: float, lon: float, bbox: tuple[float, float, float, float]) -> bool:
126
+ minx, miny, maxx, maxy = bbox
127
+ return minx <= lon <= maxx and miny <= lat <= maxy
128
+
129
+
130
+ def _haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
131
+ p1, p2 = math.radians(lat1), math.radians(lat2)
132
+ dp = math.radians(lat2 - lat1)
133
+ dl = math.radians(lon2 - lon1)
134
+ a = math.sin(dp / 2) ** 2 + math.cos(p1) * math.cos(p2) * math.sin(dl / 2) ** 2
135
+ return 2 * EARTH_RADIUS_KM * math.atan2(math.sqrt(a), math.sqrt(1 - a))
136
+
137
+
138
+ def _cell(lat: float, lon: float, size: float) -> tuple[int, int]:
139
+ return math.floor((lon + 180.0) / size), math.floor((lat + 90.0) / size)
140
+
141
+
142
+ def _cell_id(x: int, y: int, width: int) -> int:
143
+ return y * width + x
144
+
145
+
146
+ def _validate(lat: float, lon: float) -> None:
147
+ if not -90 <= lat <= 90:
148
+ raise ValueError("lat must be between -90 and 90")
149
+ if not -180 <= lon <= 180:
150
+ raise ValueError("lon must be between -180 and 180")
@@ -0,0 +1,131 @@
1
+ Metadata-Version: 2.4
2
+ Name: offlineRevGeocoder
3
+ Version: 0.1.0
4
+ Summary: Fast offline reverse geocoding using a prepared Natural Earth cache
5
+ Home-page: https://github.com/aminjavadi02/reverseGeocoder-py
6
+ Author: AminJavadi
7
+ License: MIT
8
+ Project-URL: Source, https://github.com/aminjavadi02/reverseGeocoder-py
9
+ Project-URL: Natural Earth, https://www.naturalearthdata.com/
10
+ Keywords: geocoder,geocoding,gis,natural-earth,reverse-geocoding
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: GIS
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Dynamic: author
24
+ Dynamic: classifier
25
+ Dynamic: description
26
+ Dynamic: description-content-type
27
+ Dynamic: home-page
28
+ Dynamic: keywords
29
+ Dynamic: license
30
+ Dynamic: license-file
31
+ Dynamic: project-url
32
+ Dynamic: requires-python
33
+ Dynamic: summary
34
+
35
+ # Reverse Geocoder
36
+
37
+ Tiny offline reverse geocoding for Python.
38
+
39
+ `offlineRevGeocoder` takes a latitude and longitude and returns a small `GeoResult`
40
+ object with the matching country, continent, ocean, and nearest city when one is
41
+ close enough. It is intentionally simple: the geographic source data is prepared
42
+ ahead of time, cached as a pickle file, and loaded locally at runtime. No API
43
+ keys, no network requests, no external service latency.
44
+
45
+ The bundled lookup data is derived from [Natural Earth](https://www.naturalearthdata.com/),
46
+ a public domain map dataset. The prepared cache is included so callers can use
47
+ the package immediately.
48
+
49
+ ## Project Info
50
+
51
+ - PyPI package: `offlineRevGeocoder`
52
+ - Import package: `offlineRevGeocoder`
53
+ - Source code: [github.com/aminjavadi02/reverseGeocoder-py](https://github.com/aminjavadi02/reverseGeocoder-py)
54
+ - License: MIT
55
+ - Author: AminJavadi
56
+
57
+ This is an open-source package. Bug reports, fixes, data improvements, and
58
+ documentation updates are welcome; please open an issue or send a pull request
59
+ on GitHub.
60
+
61
+ ## Install
62
+
63
+ ```bash
64
+ pip install offlineRevGeocoder
65
+ ```
66
+
67
+ ## Usage
68
+
69
+ ```python
70
+ from offlineRevGeocoder import get
71
+
72
+ result = get(35.6892, 51.3890)
73
+
74
+ print(result.country) # Iran
75
+ print(result.country_iso2) # IR
76
+ print(result.city) # Tehran
77
+ print(result.precision) # city
78
+ ```
79
+
80
+ ## Common Use Case
81
+
82
+ This package is most useful when you only need a small reverse geocoding answer,
83
+ for example checking whether a user's latitude and longitude are in or near a
84
+ specific city. In that kind of flow, you often do not need to pay for a full
85
+ reverse geocoding API subscription.
86
+
87
+ ```python
88
+ from offlineRevGeocoder import get
89
+
90
+ place = get(35.7000, 51.4000, city_radius_km=25)
91
+
92
+ print(place.city) # Tehran
93
+ print(place.precision) # city
94
+ print(place.city == "Tehran") # True
95
+ ```
96
+
97
+ For a nearby-city check, use `city_radius_km` to control how strict the match
98
+ should be for your product.
99
+
100
+ ## Return Type
101
+
102
+ `get(lat, lon, city_radius_km=50)` returns:
103
+
104
+ ```python
105
+ GeoResult(
106
+ continent: str | None,
107
+ country: str | None,
108
+ country_iso2: str | None,
109
+ country_iso3: str | None,
110
+ ocean: str | None,
111
+ city: str | None,
112
+ city_distance_km: float | None,
113
+ precision: str,
114
+ )
115
+ ```
116
+
117
+ `precision` is one of:
118
+
119
+ - `city`: a nearby city was found.
120
+ - `country`: the point matched a country, but no nearby city was found.
121
+ - `ocean`: the point matched an ocean or marine area.
122
+ - `none`: no matching land or ocean feature was found.
123
+
124
+ ## Data
125
+
126
+ The package uses Natural Earth datasets that were transformed into a compact
127
+ pickle cache at `offlineRevGeocoder/data/reverse_geocoder_cache.pkl`. Natural Earth data is
128
+ public domain, so it can be redistributed with this MIT-licensed package.
129
+
130
+ The code is MIT licensed. Natural Earth requests attribution where possible; this
131
+ README keeps that attribution with the package.
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ setup.py
5
+ offlineRevGeocoder/__init__.py
6
+ offlineRevGeocoder/reverseGeocoder.py
7
+ offlineRevGeocoder.egg-info/PKG-INFO
8
+ offlineRevGeocoder.egg-info/SOURCES.txt
9
+ offlineRevGeocoder.egg-info/dependency_links.txt
10
+ offlineRevGeocoder.egg-info/top_level.txt
11
+ offlineRevGeocoder/data/__init__.py
12
+ offlineRevGeocoder/data/reverse_geocoder_cache.pkl
@@ -0,0 +1 @@
1
+ offlineRevGeocoder
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,39 @@
1
+ from pathlib import Path
2
+
3
+ from setuptools import setup
4
+
5
+ ROOT = Path(__file__).parent
6
+ README = (ROOT / "README.md").read_text(encoding="utf-8")
7
+
8
+ setup(
9
+ name="offlineRevGeocoder",
10
+ version="0.1.0",
11
+ description="Fast offline reverse geocoding using a prepared Natural Earth cache",
12
+ long_description=README,
13
+ long_description_content_type="text/markdown",
14
+ author="AminJavadi",
15
+ url="https://github.com/aminjavadi02/reverseGeocoder-py",
16
+ project_urls={
17
+ "Source": "https://github.com/aminjavadi02/reverseGeocoder-py",
18
+ "Natural Earth": "https://www.naturalearthdata.com/",
19
+ },
20
+ packages=["offlineRevGeocoder", "offlineRevGeocoder.data"],
21
+ include_package_data=True,
22
+ package_data={"offlineRevGeocoder": ["data/*.pkl"]},
23
+ python_requires=">=3.10",
24
+ install_requires=[],
25
+ license="MIT",
26
+ license_files=["LICENSE"],
27
+ classifiers=[
28
+ "Development Status :: 3 - Alpha",
29
+ "Intended Audience :: Developers",
30
+ "License :: OSI Approved :: MIT License",
31
+ "Operating System :: OS Independent",
32
+ "Programming Language :: Python :: 3",
33
+ "Programming Language :: Python :: 3.10",
34
+ "Programming Language :: Python :: 3.11",
35
+ "Programming Language :: Python :: 3.12",
36
+ "Topic :: Scientific/Engineering :: GIS",
37
+ ],
38
+ keywords=["geocoder", "geocoding", "gis", "natural-earth", "reverse-geocoding"],
39
+ )