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.
@@ -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.4
1
+ Metadata-Version: 2.5
2
2
  Name: parseapi
3
- Version: 0.1.0
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
  ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "parseapi"
7
- version = "0.1.0"
7
+ version = "0.2.1"
8
8
  description = "Official parseAPI client for Python. One key, minimal JSON, fast."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -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("phone", lambda: parse.phone("+14155552671"), lambda r: None if r["e164"] == "+14155552671" else "wrong e164")
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")
@@ -2,5 +2,5 @@
2
2
 
3
3
  from ._client import AsyncParseAPI, ParseAPI, ParseAPIError
4
4
 
5
- __version__ = "0.1.0"
5
+ __version__ = "0.2.1"
6
6
  __all__ = ["ParseAPI", "AsyncParseAPI", "ParseAPIError", "__version__"]
@@ -8,7 +8,7 @@ from urllib.parse import quote
8
8
 
9
9
  import httpx
10
10
 
11
- VERSION = "0.1.0"
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(self, base: str, quote_currency: str) -> Json:
279
- return self._client._get(f"/currency/{_seg(base)}/{_seg(quote_currency)}")
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(self, base: str, quote_currency: str) -> Json:
498
- return await self._client._get(f"/currency/{_seg(base)}/{_seg(quote_currency)}")
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