parseapi 0.1.0__tar.gz → 0.2.1__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.
- parseapi-0.2.1/.github/workflows/publish.yml +23 -0
- {parseapi-0.1.0 → parseapi-0.2.1}/PKG-INFO +13 -2
- {parseapi-0.1.0 → parseapi-0.2.1}/README.md +11 -0
- {parseapi-0.1.0 → parseapi-0.2.1}/pyproject.toml +1 -1
- {parseapi-0.1.0 → parseapi-0.2.1}/smoke/smoke.py +44 -2
- {parseapi-0.1.0 → parseapi-0.2.1}/src/parseapi/__init__.py +1 -1
- {parseapi-0.1.0 → parseapi-0.2.1}/src/parseapi/_client.py +167 -19
- {parseapi-0.1.0 → parseapi-0.2.1}/tests/test_client.py +35 -0
- {parseapi-0.1.0 → parseapi-0.2.1}/.gitignore +0 -0
- {parseapi-0.1.0 → parseapi-0.2.1}/LICENSE +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- '[0-9]+.[0-9]+.[0-9]+'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
id-token: write
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
publish:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v5
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.12'
|
|
21
|
+
- run: pip install build
|
|
22
|
+
- run: python -m build
|
|
23
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: parseapi
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Official parseAPI client for Python. One key, minimal JSON, fast.
|
|
5
5
|
Project-URL: Homepage, https://parseapi.com
|
|
6
6
|
Project-URL: Documentation, https://parseapi.com/docs
|
|
@@ -42,7 +42,14 @@ One method per endpoint, named after the route.
|
|
|
42
42
|
parse.ip("8.8.8.8")
|
|
43
43
|
parse.ip.self()
|
|
44
44
|
parse.email("hello@gmail.com")
|
|
45
|
+
parse.vat("DE136695976")
|
|
46
|
+
parse.iban("DE89370400440532013000")
|
|
47
|
+
parse.npi("1881018208")
|
|
45
48
|
parse.phone("+14155552671")
|
|
49
|
+
parse.carrier("+14155552671")
|
|
50
|
+
parse.caller("+14155552671")
|
|
51
|
+
parse.hlr("+14155552671")
|
|
52
|
+
parse.postal("SW1A 1AA")
|
|
46
53
|
parse.postal("28202", country="US")
|
|
47
54
|
parse.postal.nearby("28202", country="US", radius=40)
|
|
48
55
|
parse.postal.distance("28202", "10001", country="US")
|
|
@@ -50,8 +57,10 @@ parse.city("charlotte", country="US")
|
|
|
50
57
|
parse.city.id("city_mb8mbqrkz8zb")
|
|
51
58
|
parse.city.search("char", country="US", limit=10)
|
|
52
59
|
parse.city.nearest(35.2271, -80.8431)
|
|
60
|
+
parse.city.nearby("denver", radius=8, unit="mi")
|
|
53
61
|
parse.country("US")
|
|
54
62
|
parse.country.states("US")
|
|
63
|
+
parse.state("colorado")
|
|
55
64
|
parse.state("NC", country="US")
|
|
56
65
|
parse.state.districts("NC", country="US")
|
|
57
66
|
parse.district("37081")
|
|
@@ -60,6 +69,7 @@ parse.continent.countries("NA")
|
|
|
60
69
|
parse.currency("USD")
|
|
61
70
|
parse.currency.rate("USD", "EUR")
|
|
62
71
|
parse.language("en")
|
|
72
|
+
parse.name("BILLY OSHALL")
|
|
63
73
|
parse.timezone("America/New_York")
|
|
64
74
|
parse.holiday("US", year=2026)
|
|
65
75
|
parse.holiday.date("US", "2026-12-25")
|
|
@@ -69,6 +79,7 @@ parse.weather(40.7128, -74.006)
|
|
|
69
79
|
parse.domain("example.com")
|
|
70
80
|
parse.mx("example.com")
|
|
71
81
|
parse.useragent(ua_string)
|
|
82
|
+
parse.vin("1HGCM82633A004352")
|
|
72
83
|
parse.emoji("rocket")
|
|
73
84
|
parse.emoji.search("fire")
|
|
74
85
|
```
|
|
@@ -23,7 +23,14 @@ One method per endpoint, named after the route.
|
|
|
23
23
|
parse.ip("8.8.8.8")
|
|
24
24
|
parse.ip.self()
|
|
25
25
|
parse.email("hello@gmail.com")
|
|
26
|
+
parse.vat("DE136695976")
|
|
27
|
+
parse.iban("DE89370400440532013000")
|
|
28
|
+
parse.npi("1881018208")
|
|
26
29
|
parse.phone("+14155552671")
|
|
30
|
+
parse.carrier("+14155552671")
|
|
31
|
+
parse.caller("+14155552671")
|
|
32
|
+
parse.hlr("+14155552671")
|
|
33
|
+
parse.postal("SW1A 1AA")
|
|
27
34
|
parse.postal("28202", country="US")
|
|
28
35
|
parse.postal.nearby("28202", country="US", radius=40)
|
|
29
36
|
parse.postal.distance("28202", "10001", country="US")
|
|
@@ -31,8 +38,10 @@ parse.city("charlotte", country="US")
|
|
|
31
38
|
parse.city.id("city_mb8mbqrkz8zb")
|
|
32
39
|
parse.city.search("char", country="US", limit=10)
|
|
33
40
|
parse.city.nearest(35.2271, -80.8431)
|
|
41
|
+
parse.city.nearby("denver", radius=8, unit="mi")
|
|
34
42
|
parse.country("US")
|
|
35
43
|
parse.country.states("US")
|
|
44
|
+
parse.state("colorado")
|
|
36
45
|
parse.state("NC", country="US")
|
|
37
46
|
parse.state.districts("NC", country="US")
|
|
38
47
|
parse.district("37081")
|
|
@@ -41,6 +50,7 @@ parse.continent.countries("NA")
|
|
|
41
50
|
parse.currency("USD")
|
|
42
51
|
parse.currency.rate("USD", "EUR")
|
|
43
52
|
parse.language("en")
|
|
53
|
+
parse.name("BILLY OSHALL")
|
|
44
54
|
parse.timezone("America/New_York")
|
|
45
55
|
parse.holiday("US", year=2026)
|
|
46
56
|
parse.holiday.date("US", "2026-12-25")
|
|
@@ -50,6 +60,7 @@ parse.weather(40.7128, -74.006)
|
|
|
50
60
|
parse.domain("example.com")
|
|
51
61
|
parse.mx("example.com")
|
|
52
62
|
parse.useragent(ua_string)
|
|
63
|
+
parse.vin("1HGCM82633A004352")
|
|
53
64
|
parse.emoji("rocket")
|
|
54
65
|
parse.emoji.search("fire")
|
|
55
66
|
```
|
|
@@ -51,6 +51,16 @@ expect_ok("ip", lambda: parse.ip("8.8.8.8"), lambda r: None if r["ip"] == "8.8.8
|
|
|
51
51
|
expect_ok("ip.self", lambda: parse.ip.self(), lambda r: None if r.get("ip") else "no ip")
|
|
52
52
|
expect_ok("continent", lambda: parse.continent("NA"), lambda r: None if r["name"] == "North America" else "wrong name")
|
|
53
53
|
expect_ok("continent.countries", lambda: parse.continent.countries("NA"), lambda r: None if r["countries"] else "empty")
|
|
54
|
+
expect_ok(
|
|
55
|
+
"bloc",
|
|
56
|
+
lambda: parse.bloc("EU"),
|
|
57
|
+
lambda r: None if r["name"] == "European Union" and r["members"] == 27 else "wrong bloc",
|
|
58
|
+
)
|
|
59
|
+
expect_ok(
|
|
60
|
+
"bloc.countries",
|
|
61
|
+
lambda: parse.bloc.countries("SCHENGEN"),
|
|
62
|
+
lambda r: None if r["countries"] and len(r["countries"]) == 29 else "wrong members",
|
|
63
|
+
)
|
|
54
64
|
expect_ok("country", lambda: parse.country("US"), lambda r: None if r["iso3"] == "USA" else "wrong iso3")
|
|
55
65
|
expect_ok("country.states", lambda: parse.country.states("US"), lambda r: None if len(r["states"]) >= 50 else "too few")
|
|
56
66
|
expect_ok("state", lambda: parse.state("NC", country="US"), lambda r: None if r["name"] == "North Carolina" else "wrong")
|
|
@@ -72,10 +82,37 @@ expect_ok(
|
|
|
72
82
|
lambda r: None if 800 < r["distance"] < 1000 else f"distance {r['distance']}",
|
|
73
83
|
)
|
|
74
84
|
expect_ok("email", lambda: parse.email("hello@gmail.com"), lambda r: None if r["valid"] is True else "not valid")
|
|
75
|
-
expect_ok(
|
|
85
|
+
expect_ok(
|
|
86
|
+
"vat",
|
|
87
|
+
lambda: parse.vat("DE136695976"),
|
|
88
|
+
lambda r: None if r.get("valid") is True and r.get("country") == "DE" else "not valid DE",
|
|
89
|
+
)
|
|
90
|
+
expect_ok(
|
|
91
|
+
"iban",
|
|
92
|
+
lambda: parse.iban("DE89370400440532013000"),
|
|
93
|
+
lambda r: None if r.get("valid") is True and r.get("country") == "DE" and r.get("bank") == "37040044" else "not valid DE",
|
|
94
|
+
)
|
|
95
|
+
expect_ok("iban junk", lambda: parse.iban("hello"), lambda r: None if r.get("valid") is False else "expected invalid")
|
|
96
|
+
expect_ok(
|
|
97
|
+
"npi",
|
|
98
|
+
lambda: parse.npi("1881018208"),
|
|
99
|
+
lambda r: None if r.get("valid") is True and r.get("registered") is True else "not registered",
|
|
100
|
+
)
|
|
101
|
+
expect_ok("npi junk", lambda: parse.npi("hello"), lambda r: None if r.get("valid") is False else "expected invalid")
|
|
102
|
+
expect_ok("phone", lambda: parse.phone("+14155552671"), lambda r: None if r["phone"] == "+14155552671" else "wrong phone")
|
|
103
|
+
# Metered core siblings: junk numbers answer 200 valid false, free, no vendor dip.
|
|
104
|
+
expect_ok("carrier junk free", lambda: parse.carrier("555-0100"), lambda r: None if r["valid"] is False else "expected invalid")
|
|
105
|
+
expect_ok("caller junk free", lambda: parse.caller("555-0100"), lambda r: None if r["valid"] is False else "expected invalid")
|
|
106
|
+
expect_ok("hlr junk free", lambda: parse.hlr("555-0100"), lambda r: None if r["valid"] is False else "expected invalid")
|
|
76
107
|
expect_ok("domain", lambda: parse.domain("gmail.com"), lambda r: None if r["available"] is False else "gmail available?")
|
|
77
108
|
expect_ok("mx", lambda: parse.mx("gmail.com"), lambda r: None if r["mx"] else "no mx")
|
|
78
109
|
expect_ok("useragent", lambda: parse.useragent(UA), lambda r: None if r["browser"] == "Chrome" else f"browser {r['browser']}")
|
|
110
|
+
expect_ok(
|
|
111
|
+
"vin",
|
|
112
|
+
lambda: parse.vin("1HGCM82633A004352"),
|
|
113
|
+
lambda r: None if r.get("valid") is True and r.get("make") == "Honda" and r.get("year") == 2003 else "wrong decode",
|
|
114
|
+
)
|
|
115
|
+
expect_ok("vin junk", lambda: parse.vin("1HGCM82613A004352"), lambda r: None if r.get("valid") is False else "expected invalid")
|
|
79
116
|
expect_ok("currency", lambda: parse.currency("USD"), lambda r: None if r["symbol"] == "$" else "wrong symbol")
|
|
80
117
|
expect_ok("currency.rate", lambda: parse.currency.rate("USD", "EUR"), lambda r: None if 0 < r["rate"] < 10 else "bad rate")
|
|
81
118
|
expect_ok(
|
|
@@ -83,6 +120,11 @@ expect_ok(
|
|
|
83
120
|
lambda: parse.language("en"),
|
|
84
121
|
lambda r: None if r.get("language") == "en" and r.get("name") == "English" else "wrong language",
|
|
85
122
|
)
|
|
123
|
+
expect_ok(
|
|
124
|
+
"name",
|
|
125
|
+
lambda: parse.name("BILLY O'SHALL"),
|
|
126
|
+
lambda r: None if r["name"] == "Billy O'Shall" and r["valid"] is True and r["gender"] == "male" else "wrong name",
|
|
127
|
+
)
|
|
86
128
|
expect_ok(
|
|
87
129
|
"timezone",
|
|
88
130
|
lambda: parse.timezone("America/New_York"),
|
|
@@ -97,7 +139,7 @@ expect_ok(
|
|
|
97
139
|
expect_ok("holiday null", lambda: parse.holiday.date("US", "2026-08-12"), lambda r: None if r["holiday"] is None else "expected null")
|
|
98
140
|
expect_ok("elevation", lambda: parse.elevation(35.2271, -80.8431), lambda r: None if isinstance(r["elevation"], (int, float)) else "no elevation")
|
|
99
141
|
expect_ok("point", lambda: parse.point(36.0726, -79.792), lambda r: None if r["country"] == "US" else f"country {r['country']}")
|
|
100
|
-
expect_ok("weather", lambda: parse.weather(40.7128, -74.006), lambda r: None if r.get("station") else "no station")
|
|
142
|
+
expect_ok("weather", lambda: parse.weather(40.7128, -74.006), lambda r: None if (r.get("station") or {}).get("id") else "no station")
|
|
101
143
|
expect_ok("emoji", lambda: parse.emoji("rocket"), lambda r: None if r["emoji"] == "\U0001F680" else "wrong emoji")
|
|
102
144
|
expect_ok("emoji.search", lambda: parse.emoji.search("fire", limit=5), lambda r: None if r["emojis"] else "empty")
|
|
103
145
|
expect_ok("point deep triad", lambda: parse.point(36.0726, -79.792, deep=True), lambda r: None if isinstance(r.get("deep"), dict) else "deep missing")
|
|
@@ -8,7 +8,7 @@ from urllib.parse import quote
|
|
|
8
8
|
|
|
9
9
|
import httpx
|
|
10
10
|
|
|
11
|
-
VERSION = "0.1
|
|
11
|
+
VERSION = "0.2.1"
|
|
12
12
|
DEFAULT_BASE_URL = "https://api.parseapi.com"
|
|
13
13
|
DEFAULT_TIMEOUT = 10.0
|
|
14
14
|
DEFAULT_RETRIES = 2
|
|
@@ -107,6 +107,7 @@ class ParseAPI:
|
|
|
107
107
|
)
|
|
108
108
|
self.ip = _IpSync(self)
|
|
109
109
|
self.continent = _ContinentSync(self)
|
|
110
|
+
self.bloc = _BlocSync(self)
|
|
110
111
|
self.country = _CountrySync(self)
|
|
111
112
|
self.state = _StateSync(self)
|
|
112
113
|
self.city = _CitySync(self)
|
|
@@ -114,6 +115,7 @@ class ParseAPI:
|
|
|
114
115
|
self.currency = _CurrencySync(self)
|
|
115
116
|
self.holiday = _HolidaySync(self)
|
|
116
117
|
self.emoji = _EmojiSync(self)
|
|
118
|
+
self.tariff = _TariffSync(self)
|
|
117
119
|
|
|
118
120
|
def close(self) -> None:
|
|
119
121
|
self._http.close()
|
|
@@ -145,15 +147,40 @@ class ParseAPI:
|
|
|
145
147
|
|
|
146
148
|
# Plain methods (no subresources)
|
|
147
149
|
|
|
148
|
-
def district(self, code: str, *, country: Optional[str] = None) -> Json:
|
|
149
|
-
return self._get(f"/district/{_seg(code)}", {"country": country})
|
|
150
|
+
def district(self, code: str, *, country: Optional[str] = None, state: Optional[str] = None) -> Json:
|
|
151
|
+
return self._get(f"/district/{_seg(code)}", {"country": country, "state": state})
|
|
150
152
|
|
|
151
153
|
def email(self, email: str, *, deep: bool = False) -> Json:
|
|
152
154
|
return self._get(f"/email/{_seg(email)}", {"deep": deep})
|
|
153
155
|
|
|
156
|
+
def vat(
|
|
157
|
+
self,
|
|
158
|
+
number: str,
|
|
159
|
+
*,
|
|
160
|
+
country: Optional[str] = None,
|
|
161
|
+
deep: bool = False,
|
|
162
|
+
from_vat: Optional[str] = None,
|
|
163
|
+
) -> Json:
|
|
164
|
+
return self._get(f"/vat/{_seg(number)}", {"country": country, "deep": deep, "from": from_vat})
|
|
165
|
+
|
|
166
|
+
def iban(self, iban: str, *, country: Optional[str] = None) -> Json:
|
|
167
|
+
return self._get(f"/iban/{_seg(iban)}", {"country": country})
|
|
168
|
+
|
|
169
|
+
def npi(self, npi: str, *, deep: bool = False) -> Json:
|
|
170
|
+
return self._get(f"/npi/{_seg(npi)}", {"deep": deep})
|
|
171
|
+
|
|
154
172
|
def phone(self, number: str, *, country: Optional[str] = None, deep: bool = False) -> Json:
|
|
155
173
|
return self._get(f"/phone/{_seg(number)}", {"country": country, "deep": deep})
|
|
156
174
|
|
|
175
|
+
def carrier(self, number: str, *, country: Optional[str] = None) -> Json:
|
|
176
|
+
return self._get(f"/carrier/{_seg(number)}", {"country": country})
|
|
177
|
+
|
|
178
|
+
def caller(self, number: str, *, country: Optional[str] = None) -> Json:
|
|
179
|
+
return self._get(f"/caller/{_seg(number)}", {"country": country})
|
|
180
|
+
|
|
181
|
+
def hlr(self, number: str, *, country: Optional[str] = None) -> Json:
|
|
182
|
+
return self._get(f"/hlr/{_seg(number)}", {"country": country})
|
|
183
|
+
|
|
157
184
|
def domain(self, domain: str, *, deep: bool = False) -> Json:
|
|
158
185
|
return self._get(f"/domain/{_seg(domain)}", {"deep": deep})
|
|
159
186
|
|
|
@@ -163,12 +190,18 @@ class ParseAPI:
|
|
|
163
190
|
def useragent(self, ua: str, *, deep: bool = False) -> Json:
|
|
164
191
|
return self._get("/useragent", {"deep": deep}, headers={"User-Agent": ua})
|
|
165
192
|
|
|
193
|
+
def vin(self, vin: str, *, deep: bool = False) -> Json:
|
|
194
|
+
return self._get(f"/vin/{_seg(vin)}", {"deep": deep})
|
|
195
|
+
|
|
166
196
|
def timezone(self, id: str, *, at: Optional[str] = None) -> Json:
|
|
167
197
|
return self._get(f"/timezone/{_seg(id)}", {"at": at})
|
|
168
198
|
|
|
169
199
|
def language(self, code: str) -> Json:
|
|
170
200
|
return self._get(f"/language/{_seg(code)}")
|
|
171
201
|
|
|
202
|
+
def name(self, name: str) -> Json:
|
|
203
|
+
return self._get(f"/name/{_seg(name)}")
|
|
204
|
+
|
|
172
205
|
def elevation(self, lat: float, lon: float) -> Json:
|
|
173
206
|
return self._get("/elevation", {"lat": lat, "lon": lon})
|
|
174
207
|
|
|
@@ -201,6 +234,17 @@ class _ContinentSync:
|
|
|
201
234
|
return self._client._get(f"/continent/{_seg(code)}/countries")
|
|
202
235
|
|
|
203
236
|
|
|
237
|
+
class _BlocSync:
|
|
238
|
+
def __init__(self, client: ParseAPI):
|
|
239
|
+
self._client = client
|
|
240
|
+
|
|
241
|
+
def __call__(self, code: str) -> Json:
|
|
242
|
+
return self._client._get(f"/bloc/{_seg(code)}")
|
|
243
|
+
|
|
244
|
+
def countries(self, code: str) -> Json:
|
|
245
|
+
return self._client._get(f"/bloc/{_seg(code)}/countries")
|
|
246
|
+
|
|
247
|
+
|
|
204
248
|
class _CountrySync:
|
|
205
249
|
def __init__(self, client: ParseAPI):
|
|
206
250
|
self._client = client
|
|
@@ -216,10 +260,10 @@ class _StateSync:
|
|
|
216
260
|
def __init__(self, client: ParseAPI):
|
|
217
261
|
self._client = client
|
|
218
262
|
|
|
219
|
-
def __call__(self, code: str, *, country: str) -> Json:
|
|
263
|
+
def __call__(self, code: str, *, country: Optional[str] = None) -> Json:
|
|
220
264
|
return self._client._get(f"/state/{_seg(code)}", {"country": country})
|
|
221
265
|
|
|
222
|
-
def districts(self, code: str, *, country: str) -> Json:
|
|
266
|
+
def districts(self, code: str, *, country: Optional[str] = None) -> Json:
|
|
223
267
|
return self._client._get(f"/state/{_seg(code)}/districts", {"country": country})
|
|
224
268
|
|
|
225
269
|
|
|
@@ -246,25 +290,40 @@ class _CitySync:
|
|
|
246
290
|
def nearest(self, lat: float, lon: float) -> Json:
|
|
247
291
|
return self._client._get("/city", {"lat": lat, "lon": lon})
|
|
248
292
|
|
|
293
|
+
def nearby(
|
|
294
|
+
self,
|
|
295
|
+
name: str,
|
|
296
|
+
*,
|
|
297
|
+
radius: Optional[float] = None,
|
|
298
|
+
unit: Optional[str] = None,
|
|
299
|
+
country: Optional[str] = None,
|
|
300
|
+
state: Optional[str] = None,
|
|
301
|
+
limit: Optional[int] = None,
|
|
302
|
+
) -> Json:
|
|
303
|
+
return self._client._get(
|
|
304
|
+
f"/city/{_seg(name)}/nearby",
|
|
305
|
+
{"radius": radius, "unit": unit, "country": country, "state": state, "limit": limit},
|
|
306
|
+
)
|
|
307
|
+
|
|
249
308
|
|
|
250
309
|
class _PostalSync:
|
|
251
310
|
def __init__(self, client: ParseAPI):
|
|
252
311
|
self._client = client
|
|
253
312
|
|
|
254
|
-
def __call__(self, code: str, *, country: str) -> Json:
|
|
313
|
+
def __call__(self, code: str, *, country: Optional[str] = None) -> Json:
|
|
255
314
|
return self._client._get(f"/postal/{_seg(code)}", {"country": country})
|
|
256
315
|
|
|
257
316
|
def nearby(
|
|
258
317
|
self,
|
|
259
318
|
code: str,
|
|
260
319
|
*,
|
|
261
|
-
country: str,
|
|
320
|
+
country: Optional[str] = None,
|
|
262
321
|
radius: Optional[float] = None,
|
|
263
322
|
unit: Optional[str] = None,
|
|
264
323
|
) -> Json:
|
|
265
324
|
return self._client._get(f"/postal/{_seg(code)}/nearby", {"country": country, "radius": radius, "unit": unit})
|
|
266
325
|
|
|
267
|
-
def distance(self, from_postal: str, to_postal: str, *, country: str) -> Json:
|
|
326
|
+
def distance(self, from_postal: str, to_postal: str, *, country: Optional[str] = None) -> Json:
|
|
268
327
|
return self._client._get(f"/postal/{_seg(from_postal)}/distance/{_seg(to_postal)}", {"country": country})
|
|
269
328
|
|
|
270
329
|
|
|
@@ -275,8 +334,12 @@ class _CurrencySync:
|
|
|
275
334
|
def __call__(self, code: str) -> Json:
|
|
276
335
|
return self._client._get(f"/currency/{_seg(code)}")
|
|
277
336
|
|
|
278
|
-
def rate(
|
|
279
|
-
|
|
337
|
+
def rate(
|
|
338
|
+
self, base: str, quote_currency: str, *, date: Optional[str] = None, amount: Optional[float] = None
|
|
339
|
+
) -> Json:
|
|
340
|
+
return self._client._get(
|
|
341
|
+
f"/currency/{_seg(base)}/{_seg(quote_currency)}", {"date": date, "amount": amount}
|
|
342
|
+
)
|
|
280
343
|
|
|
281
344
|
|
|
282
345
|
class _HolidaySync:
|
|
@@ -301,6 +364,17 @@ class _EmojiSync:
|
|
|
301
364
|
return self._client._get("/emoji", {"q": q, "limit": limit})
|
|
302
365
|
|
|
303
366
|
|
|
367
|
+
class _TariffSync:
|
|
368
|
+
def __init__(self, client: ParseAPI):
|
|
369
|
+
self._client = client
|
|
370
|
+
|
|
371
|
+
def __call__(self, code: str, *, deep: bool = False, origin: Optional[str] = None) -> Json:
|
|
372
|
+
return self._client._get(f"/tariff/{_seg(code)}", {"deep": deep, "origin": origin})
|
|
373
|
+
|
|
374
|
+
def search(self, q: str) -> Json:
|
|
375
|
+
return self._client._get("/tariff", {"q": q})
|
|
376
|
+
|
|
377
|
+
|
|
304
378
|
class AsyncParseAPI:
|
|
305
379
|
"""Async client. `parse = AsyncParseAPI()` reads PARSEAPI_KEY from the env."""
|
|
306
380
|
|
|
@@ -322,6 +396,7 @@ class AsyncParseAPI:
|
|
|
322
396
|
)
|
|
323
397
|
self.ip = _IpAsync(self)
|
|
324
398
|
self.continent = _ContinentAsync(self)
|
|
399
|
+
self.bloc = _BlocAsync(self)
|
|
325
400
|
self.country = _CountryAsync(self)
|
|
326
401
|
self.state = _StateAsync(self)
|
|
327
402
|
self.city = _CityAsync(self)
|
|
@@ -329,6 +404,7 @@ class AsyncParseAPI:
|
|
|
329
404
|
self.currency = _CurrencyAsync(self)
|
|
330
405
|
self.holiday = _HolidayAsync(self)
|
|
331
406
|
self.emoji = _EmojiAsync(self)
|
|
407
|
+
self.tariff = _TariffAsync(self)
|
|
332
408
|
|
|
333
409
|
async def close(self) -> None:
|
|
334
410
|
await self._http.aclose()
|
|
@@ -362,15 +438,40 @@ class AsyncParseAPI:
|
|
|
362
438
|
continue
|
|
363
439
|
raise _error_from(response)
|
|
364
440
|
|
|
365
|
-
async def district(self, code: str, *, country: Optional[str] = None) -> Json:
|
|
366
|
-
return await self._get(f"/district/{_seg(code)}", {"country": country})
|
|
441
|
+
async def district(self, code: str, *, country: Optional[str] = None, state: Optional[str] = None) -> Json:
|
|
442
|
+
return await self._get(f"/district/{_seg(code)}", {"country": country, "state": state})
|
|
367
443
|
|
|
368
444
|
async def email(self, email: str, *, deep: bool = False) -> Json:
|
|
369
445
|
return await self._get(f"/email/{_seg(email)}", {"deep": deep})
|
|
370
446
|
|
|
447
|
+
async def vat(
|
|
448
|
+
self,
|
|
449
|
+
number: str,
|
|
450
|
+
*,
|
|
451
|
+
country: Optional[str] = None,
|
|
452
|
+
deep: bool = False,
|
|
453
|
+
from_vat: Optional[str] = None,
|
|
454
|
+
) -> Json:
|
|
455
|
+
return await self._get(f"/vat/{_seg(number)}", {"country": country, "deep": deep, "from": from_vat})
|
|
456
|
+
|
|
457
|
+
async def iban(self, iban: str, *, country: Optional[str] = None) -> Json:
|
|
458
|
+
return await self._get(f"/iban/{_seg(iban)}", {"country": country})
|
|
459
|
+
|
|
460
|
+
async def npi(self, npi: str, *, deep: bool = False) -> Json:
|
|
461
|
+
return await self._get(f"/npi/{_seg(npi)}", {"deep": deep})
|
|
462
|
+
|
|
371
463
|
async def phone(self, number: str, *, country: Optional[str] = None, deep: bool = False) -> Json:
|
|
372
464
|
return await self._get(f"/phone/{_seg(number)}", {"country": country, "deep": deep})
|
|
373
465
|
|
|
466
|
+
async def carrier(self, number: str, *, country: Optional[str] = None) -> Json:
|
|
467
|
+
return await self._get(f"/carrier/{_seg(number)}", {"country": country})
|
|
468
|
+
|
|
469
|
+
async def caller(self, number: str, *, country: Optional[str] = None) -> Json:
|
|
470
|
+
return await self._get(f"/caller/{_seg(number)}", {"country": country})
|
|
471
|
+
|
|
472
|
+
async def hlr(self, number: str, *, country: Optional[str] = None) -> Json:
|
|
473
|
+
return await self._get(f"/hlr/{_seg(number)}", {"country": country})
|
|
474
|
+
|
|
374
475
|
async def domain(self, domain: str, *, deep: bool = False) -> Json:
|
|
375
476
|
return await self._get(f"/domain/{_seg(domain)}", {"deep": deep})
|
|
376
477
|
|
|
@@ -380,12 +481,18 @@ class AsyncParseAPI:
|
|
|
380
481
|
async def useragent(self, ua: str, *, deep: bool = False) -> Json:
|
|
381
482
|
return await self._get("/useragent", {"deep": deep}, headers={"User-Agent": ua})
|
|
382
483
|
|
|
484
|
+
async def vin(self, vin: str, *, deep: bool = False) -> Json:
|
|
485
|
+
return await self._get(f"/vin/{_seg(vin)}", {"deep": deep})
|
|
486
|
+
|
|
383
487
|
async def timezone(self, id: str, *, at: Optional[str] = None) -> Json:
|
|
384
488
|
return await self._get(f"/timezone/{_seg(id)}", {"at": at})
|
|
385
489
|
|
|
386
490
|
async def language(self, code: str) -> Json:
|
|
387
491
|
return await self._get(f"/language/{_seg(code)}")
|
|
388
492
|
|
|
493
|
+
async def name(self, name: str) -> Json:
|
|
494
|
+
return await self._get(f"/name/{_seg(name)}")
|
|
495
|
+
|
|
389
496
|
async def elevation(self, lat: float, lon: float) -> Json:
|
|
390
497
|
return await self._get("/elevation", {"lat": lat, "lon": lon})
|
|
391
498
|
|
|
@@ -418,6 +525,17 @@ class _ContinentAsync:
|
|
|
418
525
|
return await self._client._get(f"/continent/{_seg(code)}/countries")
|
|
419
526
|
|
|
420
527
|
|
|
528
|
+
class _BlocAsync:
|
|
529
|
+
def __init__(self, client: AsyncParseAPI):
|
|
530
|
+
self._client = client
|
|
531
|
+
|
|
532
|
+
async def __call__(self, code: str) -> Json:
|
|
533
|
+
return await self._client._get(f"/bloc/{_seg(code)}")
|
|
534
|
+
|
|
535
|
+
async def countries(self, code: str) -> Json:
|
|
536
|
+
return await self._client._get(f"/bloc/{_seg(code)}/countries")
|
|
537
|
+
|
|
538
|
+
|
|
421
539
|
class _CountryAsync:
|
|
422
540
|
def __init__(self, client: AsyncParseAPI):
|
|
423
541
|
self._client = client
|
|
@@ -433,10 +551,10 @@ class _StateAsync:
|
|
|
433
551
|
def __init__(self, client: AsyncParseAPI):
|
|
434
552
|
self._client = client
|
|
435
553
|
|
|
436
|
-
async def __call__(self, code: str, *, country: str) -> Json:
|
|
554
|
+
async def __call__(self, code: str, *, country: Optional[str] = None) -> Json:
|
|
437
555
|
return await self._client._get(f"/state/{_seg(code)}", {"country": country})
|
|
438
556
|
|
|
439
|
-
async def districts(self, code: str, *, country: str) -> Json:
|
|
557
|
+
async def districts(self, code: str, *, country: Optional[str] = None) -> Json:
|
|
440
558
|
return await self._client._get(f"/state/{_seg(code)}/districts", {"country": country})
|
|
441
559
|
|
|
442
560
|
|
|
@@ -463,19 +581,34 @@ class _CityAsync:
|
|
|
463
581
|
async def nearest(self, lat: float, lon: float) -> Json:
|
|
464
582
|
return await self._client._get("/city", {"lat": lat, "lon": lon})
|
|
465
583
|
|
|
584
|
+
async def nearby(
|
|
585
|
+
self,
|
|
586
|
+
name: str,
|
|
587
|
+
*,
|
|
588
|
+
radius: Optional[float] = None,
|
|
589
|
+
unit: Optional[str] = None,
|
|
590
|
+
country: Optional[str] = None,
|
|
591
|
+
state: Optional[str] = None,
|
|
592
|
+
limit: Optional[int] = None,
|
|
593
|
+
) -> Json:
|
|
594
|
+
return await self._client._get(
|
|
595
|
+
f"/city/{_seg(name)}/nearby",
|
|
596
|
+
{"radius": radius, "unit": unit, "country": country, "state": state, "limit": limit},
|
|
597
|
+
)
|
|
598
|
+
|
|
466
599
|
|
|
467
600
|
class _PostalAsync:
|
|
468
601
|
def __init__(self, client: AsyncParseAPI):
|
|
469
602
|
self._client = client
|
|
470
603
|
|
|
471
|
-
async def __call__(self, code: str, *, country: str) -> Json:
|
|
604
|
+
async def __call__(self, code: str, *, country: Optional[str] = None) -> Json:
|
|
472
605
|
return await self._client._get(f"/postal/{_seg(code)}", {"country": country})
|
|
473
606
|
|
|
474
607
|
async def nearby(
|
|
475
608
|
self,
|
|
476
609
|
code: str,
|
|
477
610
|
*,
|
|
478
|
-
country: str,
|
|
611
|
+
country: Optional[str] = None,
|
|
479
612
|
radius: Optional[float] = None,
|
|
480
613
|
unit: Optional[str] = None,
|
|
481
614
|
) -> Json:
|
|
@@ -483,7 +616,7 @@ class _PostalAsync:
|
|
|
483
616
|
f"/postal/{_seg(code)}/nearby", {"country": country, "radius": radius, "unit": unit}
|
|
484
617
|
)
|
|
485
618
|
|
|
486
|
-
async def distance(self, from_postal: str, to_postal: str, *, country: str) -> Json:
|
|
619
|
+
async def distance(self, from_postal: str, to_postal: str, *, country: Optional[str] = None) -> Json:
|
|
487
620
|
return await self._client._get(f"/postal/{_seg(from_postal)}/distance/{_seg(to_postal)}", {"country": country})
|
|
488
621
|
|
|
489
622
|
|
|
@@ -494,8 +627,12 @@ class _CurrencyAsync:
|
|
|
494
627
|
async def __call__(self, code: str) -> Json:
|
|
495
628
|
return await self._client._get(f"/currency/{_seg(code)}")
|
|
496
629
|
|
|
497
|
-
async def rate(
|
|
498
|
-
|
|
630
|
+
async def rate(
|
|
631
|
+
self, base: str, quote_currency: str, *, date: Optional[str] = None, amount: Optional[float] = None
|
|
632
|
+
) -> Json:
|
|
633
|
+
return await self._client._get(
|
|
634
|
+
f"/currency/{_seg(base)}/{_seg(quote_currency)}", {"date": date, "amount": amount}
|
|
635
|
+
)
|
|
499
636
|
|
|
500
637
|
|
|
501
638
|
class _HolidayAsync:
|
|
@@ -518,3 +655,14 @@ class _EmojiAsync:
|
|
|
518
655
|
|
|
519
656
|
async def search(self, q: str, *, limit: Optional[int] = None) -> Json:
|
|
520
657
|
return await self._client._get("/emoji", {"q": q, "limit": limit})
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
class _TariffAsync:
|
|
661
|
+
def __init__(self, client: AsyncParseAPI):
|
|
662
|
+
self._client = client
|
|
663
|
+
|
|
664
|
+
async def __call__(self, code: str, *, deep: bool = False, origin: Optional[str] = None) -> Json:
|
|
665
|
+
return await self._client._get(f"/tariff/{_seg(code)}", {"deep": deep, "origin": origin})
|
|
666
|
+
|
|
667
|
+
async def search(self, q: str) -> Json:
|
|
668
|
+
return await self._client._get("/tariff", {"q": q})
|
|
@@ -28,16 +28,24 @@ URL_TABLE = [
|
|
|
28
28
|
(lambda p: p.ip("8.8.8.8", deep=True), "https://api.parseapi.com/ip/8.8.8.8?deep=true"),
|
|
29
29
|
(lambda p: p.continent("NA"), "https://api.parseapi.com/continent/NA"),
|
|
30
30
|
(lambda p: p.continent.countries("NA"), "https://api.parseapi.com/continent/NA/countries"),
|
|
31
|
+
(lambda p: p.bloc("EU"), "https://api.parseapi.com/bloc/EU"),
|
|
32
|
+
(lambda p: p.bloc.countries("SCHENGEN"), "https://api.parseapi.com/bloc/SCHENGEN/countries"),
|
|
31
33
|
(lambda p: p.country("US"), "https://api.parseapi.com/country/US"),
|
|
32
34
|
(lambda p: p.country.states("US"), "https://api.parseapi.com/country/US/states"),
|
|
33
35
|
(lambda p: p.state("NC", country="US"), "https://api.parseapi.com/state/NC?country=US"),
|
|
36
|
+
(lambda p: p.state("colorado"), "https://api.parseapi.com/state/colorado"),
|
|
34
37
|
(lambda p: p.state.districts("NC", country="US"), "https://api.parseapi.com/state/NC/districts?country=US"),
|
|
35
38
|
(lambda p: p.district("37081"), "https://api.parseapi.com/district/37081"),
|
|
36
39
|
(lambda p: p.city("charlotte", state="NC"), "https://api.parseapi.com/city/charlotte?state=NC"),
|
|
37
40
|
(lambda p: p.city.id("city_mb8mbqrkz8zb"), "https://api.parseapi.com/city/id/city_mb8mbqrkz8zb"),
|
|
38
41
|
(lambda p: p.city.search("char", country="US", limit=10), "https://api.parseapi.com/city?q=char&country=US&limit=10"),
|
|
39
42
|
(lambda p: p.city.nearest(35.2271, -80.8431), "https://api.parseapi.com/city?lat=35.2271&lon=-80.8431"),
|
|
43
|
+
(
|
|
44
|
+
lambda p: p.city.nearby("denver", radius=8, unit="mi", limit=3),
|
|
45
|
+
"https://api.parseapi.com/city/denver/nearby?radius=8&unit=mi&limit=3",
|
|
46
|
+
),
|
|
40
47
|
(lambda p: p.postal("28202", country="US"), "https://api.parseapi.com/postal/28202?country=US"),
|
|
48
|
+
(lambda p: p.postal("SW1A 1AA"), "https://api.parseapi.com/postal/SW1A%201AA"),
|
|
41
49
|
(
|
|
42
50
|
lambda p: p.postal.nearby("28202", country="US", radius=40, unit="km"),
|
|
43
51
|
"https://api.parseapi.com/postal/28202/nearby?country=US&radius=40&unit=km",
|
|
@@ -47,13 +55,40 @@ URL_TABLE = [
|
|
|
47
55
|
"https://api.parseapi.com/postal/28202/distance/10001?country=US",
|
|
48
56
|
),
|
|
49
57
|
(lambda p: p.email("a@b.com"), "https://api.parseapi.com/email/a%40b.com"),
|
|
58
|
+
(
|
|
59
|
+
lambda p: p.vat("DE136695976", from_vat="IE6388047V", deep=True),
|
|
60
|
+
"https://api.parseapi.com/vat/DE136695976?deep=true&from=IE6388047V",
|
|
61
|
+
),
|
|
62
|
+
(
|
|
63
|
+
lambda p: p.iban("DE89370400440532013000"),
|
|
64
|
+
"https://api.parseapi.com/iban/DE89370400440532013000",
|
|
65
|
+
),
|
|
66
|
+
(
|
|
67
|
+
lambda p: p.iban("89370400440532013000", country="DE"),
|
|
68
|
+
"https://api.parseapi.com/iban/89370400440532013000?country=DE",
|
|
69
|
+
),
|
|
70
|
+
(lambda p: p.npi("1881018208"), "https://api.parseapi.com/npi/1881018208"),
|
|
71
|
+
(lambda p: p.npi("1881018208", deep=True), "https://api.parseapi.com/npi/1881018208?deep=true"),
|
|
50
72
|
(lambda p: p.phone("+14155552671", deep=True), "https://api.parseapi.com/phone/%2B14155552671?deep=true"),
|
|
73
|
+
(lambda p: p.carrier("+14155552671"), "https://api.parseapi.com/carrier/%2B14155552671"),
|
|
74
|
+
(lambda p: p.caller("4155552671", country="US"), "https://api.parseapi.com/caller/4155552671?country=US"),
|
|
75
|
+
(lambda p: p.hlr("+447712345678"), "https://api.parseapi.com/hlr/%2B447712345678"),
|
|
51
76
|
(lambda p: p.domain("example.com"), "https://api.parseapi.com/domain/example.com"),
|
|
52
77
|
(lambda p: p.mx("example.com"), "https://api.parseapi.com/mx/example.com"),
|
|
53
78
|
(lambda p: p.useragent("TestUA/1.0"), "https://api.parseapi.com/useragent"),
|
|
79
|
+
(lambda p: p.vin("1HGCM82633A004352"), "https://api.parseapi.com/vin/1HGCM82633A004352"),
|
|
80
|
+
(
|
|
81
|
+
lambda p: p.vin("1HGCM82633A004352", deep=True),
|
|
82
|
+
"https://api.parseapi.com/vin/1HGCM82633A004352?deep=true",
|
|
83
|
+
),
|
|
54
84
|
(lambda p: p.currency("USD"), "https://api.parseapi.com/currency/USD"),
|
|
55
85
|
(lambda p: p.currency.rate("USD", "EUR"), "https://api.parseapi.com/currency/USD/EUR"),
|
|
86
|
+
(
|
|
87
|
+
lambda p: p.currency.rate("USD", "JPY", date="2026-08-28", amount=100),
|
|
88
|
+
"https://api.parseapi.com/currency/USD/JPY?date=2026-08-28&amount=100",
|
|
89
|
+
),
|
|
56
90
|
(lambda p: p.language("en"), "https://api.parseapi.com/language/en"),
|
|
91
|
+
(lambda p: p.name("Smith, John"), "https://api.parseapi.com/name/Smith%2C%20John"),
|
|
57
92
|
(lambda p: p.timezone("America/New_York"), "https://api.parseapi.com/timezone/America%2FNew_York"),
|
|
58
93
|
(lambda p: p.holiday("US", year=1955), "https://api.parseapi.com/holiday/US?year=1955"),
|
|
59
94
|
(lambda p: p.holiday.date("US", "2026-12-25"), "https://api.parseapi.com/holiday/US/2026-12-25"),
|
|
File without changes
|
|
File without changes
|