getanyapi 0.35.2__tar.gz → 0.36.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.
Files changed (102) hide show
  1. {getanyapi-0.35.2 → getanyapi-0.36.0}/PKG-INFO +1 -1
  2. {getanyapi-0.35.2 → getanyapi-0.36.0}/pyproject.toml +1 -1
  3. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/__init__.py +1 -1
  4. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/_account.py +16 -3
  5. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/_async_client.py +1 -1
  6. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/_client.py +1 -1
  7. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/tiktok.py +2 -2
  8. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_account.py +35 -0
  9. {getanyapi-0.35.2 → getanyapi-0.36.0}/.gitignore +0 -0
  10. {getanyapi-0.35.2 → getanyapi-0.36.0}/README.md +0 -0
  11. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/_errors.py +0 -0
  12. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/_idempotency.py +0 -0
  13. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/_pagination.py +0 -0
  14. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/_transport.py +0 -0
  15. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/discovery_types.py +0 -0
  16. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/__init__.py +0 -0
  17. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/ahrefs.py +0 -0
  18. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/airbnb.py +0 -0
  19. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/alibaba.py +0 -0
  20. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/amazon.py +0 -0
  21. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/apollo.py +0 -0
  22. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/appstore.py +0 -0
  23. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/bluesky.py +0 -0
  24. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/booking.py +0 -0
  25. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/capterra.py +0 -0
  26. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/chatgpt.py +0 -0
  27. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/coinmarketcap.py +0 -0
  28. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/company.py +0 -0
  29. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/company_enrichment.py +0 -0
  30. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/company_search.py +0 -0
  31. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/congress.py +0 -0
  32. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/dexscreener.py +0 -0
  33. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/douyin.py +0 -0
  34. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/ebay.py +0 -0
  35. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/email.py +0 -0
  36. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/email_finding.py +0 -0
  37. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/email_verification.py +0 -0
  38. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/facebook.py +0 -0
  39. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/fiverr.py +0 -0
  40. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/g2.py +0 -0
  41. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/gemini.py +0 -0
  42. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/github.py +0 -0
  43. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/glassdoor.py +0 -0
  44. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/google.py +0 -0
  45. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/google_ads.py +0 -0
  46. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/google_finance.py +0 -0
  47. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/google_shopping.py +0 -0
  48. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/hackernews.py +0 -0
  49. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/indeed.py +0 -0
  50. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/instagram.py +0 -0
  51. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/job_search.py +0 -0
  52. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/linkedin.py +0 -0
  53. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/maps.py +0 -0
  54. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/mobile_phone.py +0 -0
  55. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/naver.py +0 -0
  56. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/pandaexpress.py +0 -0
  57. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/people_search.py +0 -0
  58. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/perplexity.py +0 -0
  59. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/person.py +0 -0
  60. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/person_enrichment.py +0 -0
  61. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/pinterest.py +0 -0
  62. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/playstore.py +0 -0
  63. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/polymarket.py +0 -0
  64. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/realtor.py +0 -0
  65. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/reddit.py +0 -0
  66. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/redfin.py +0 -0
  67. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/rednote.py +0 -0
  68. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/sec.py +0 -0
  69. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/semrush.py +0 -0
  70. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/seo.py +0 -0
  71. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/snapchat.py +0 -0
  72. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/social.py +0 -0
  73. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/spotify.py +0 -0
  74. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/substack.py +0 -0
  75. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/technographics.py +0 -0
  76. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/threads.py +0 -0
  77. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/tiktok_shop.py +0 -0
  78. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/tripadvisor.py +0 -0
  79. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/trustpilot.py +0 -0
  80. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/truthsocial.py +0 -0
  81. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/twitter.py +0 -0
  82. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/upwork.py +0 -0
  83. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/walmart.py +0 -0
  84. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/web.py +0 -0
  85. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/weibo.py +0 -0
  86. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/yahoo_finance.py +0 -0
  87. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/yelp.py +0 -0
  88. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/youtube.py +0 -0
  89. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/zhihu.py +0 -0
  90. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/platforms/zillow.py +0 -0
  91. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/py.typed +0 -0
  92. {getanyapi-0.35.2 → getanyapi-0.36.0}/src/getanyapi/types.py +0 -0
  93. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/conftest.py +0 -0
  94. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_client.py +0 -0
  95. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_durable_requests.py +0 -0
  96. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_envelope.py +0 -0
  97. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_errors.py +0 -0
  98. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_fixture_roundtrip.py +0 -0
  99. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_fixture_sweep.py +0 -0
  100. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_pagination.py +0 -0
  101. {getanyapi-0.35.2 → getanyapi-0.36.0}/tests/test_transport.py +0 -0
  102. {getanyapi-0.35.2 → getanyapi-0.36.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: getanyapi
3
- Version: 0.35.2
3
+ Version: 0.36.0
4
4
  Summary: Official typed Python SDK for AnyAPI: any API, one wallet, USD, no subscriptions.
5
5
  Project-URL: Homepage, https://getanyapi.com
6
6
  Project-URL: Documentation, https://getanyapi.com/docs
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "getanyapi"
7
- version = "0.35.2"
7
+ version = "0.36.0"
8
8
  description = "Official typed Python SDK for AnyAPI: any API, one wallet, USD, no subscriptions."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -54,7 +54,7 @@ from .types import (
54
54
  unwrap,
55
55
  )
56
56
 
57
- __version__ = "0.35.2"
57
+ __version__ = "0.36.0"
58
58
 
59
59
  __all__ = [
60
60
  # clients + top-level functions
@@ -49,13 +49,26 @@ def catalog_request(category: str | None) -> tuple[str, dict[str, str]]:
49
49
 
50
50
 
51
51
  def search_request(
52
- query: str,
52
+ query: str | None,
53
53
  category: str | None,
54
54
  platform: str | None,
55
55
  limit: int | None,
56
56
  ) -> tuple[str, dict[str, str]]:
57
- """Path and query params for dedicated ranked discovery search."""
58
- params = {"q": query}
57
+ """Path and query params for dedicated ranked discovery search.
58
+
59
+ The gateway needs at least one of query, category or platform, in any
60
+ combination, so a scope with no query at all is a valid search. An absent or
61
+ empty query omits ``q`` entirely, because an empty ``q`` is a different
62
+ request.
63
+ """
64
+ if not query and category is None and platform is None:
65
+ raise AnyAPIError(
66
+ "search needs at least one of query, category, or platform",
67
+ status=0,
68
+ )
69
+ params: dict[str, str] = {}
70
+ if query:
71
+ params["q"] = query
59
72
  if category is not None:
60
73
  params["category"] = category
61
74
  if platform is not None:
@@ -370,7 +370,7 @@ class AsyncAnyAPI:
370
370
  async def search(
371
371
  self,
372
372
  *,
373
- query: str,
373
+ query: str | None = None,
374
374
  category: str | None = None,
375
375
  platform: str | None = None,
376
376
  limit: int | None = None,
@@ -398,7 +398,7 @@ class AnyAPI:
398
398
  def search(
399
399
  self,
400
400
  *,
401
- query: str,
401
+ query: str | None = None,
402
402
  category: str | None = None,
403
403
  platform: str | None = None,
404
404
  limit: int | None = None,
@@ -1884,7 +1884,7 @@ class TiktokNamespace:
1884
1884
  List recent TikTok videos for a hashtag (creator, caption, views, likes,
1885
1885
  shares).
1886
1886
 
1887
- Price: $0.0036 per request.
1887
+ Price: $0.00144 per request.
1888
1888
 
1889
1889
  Example:
1890
1890
  res = client.tiktok.hashtag_videos(hashtag="cooking", limit=3)
@@ -2759,7 +2759,7 @@ class AsyncTiktokNamespace:
2759
2759
  List recent TikTok videos for a hashtag (creator, caption, views, likes,
2760
2760
  shares).
2761
2761
 
2762
- Price: $0.0036 per request.
2762
+ Price: $0.00144 per request.
2763
2763
 
2764
2764
  Example:
2765
2765
  res = client.tiktok.hashtag_videos(hashtag="cooking", limit=3)
@@ -12,6 +12,7 @@ import pytest
12
12
 
13
13
  from conftest import json_response, make_async_client, make_sync_client
14
14
  from getanyapi import (
15
+ AnyAPIError,
15
16
  DiscoveryPricing,
16
17
  FlatPricingOffer,
17
18
  LinearPricingOffer,
@@ -331,6 +332,40 @@ def test_search_reads_every_shared_ranked_field_and_forwards_filters() -> None:
331
332
  assert found.model_dump(by_alias=True, exclude_defaults=True) == body
332
333
 
333
334
 
335
+ def test_search_scopes_without_a_query_and_omits_q_entirely() -> None:
336
+ body = discovery_search()
337
+
338
+ def respond(req: httpx.Request) -> httpx.Response:
339
+ assert req.url.path == "/catalog/search"
340
+ assert dict(req.url.params) == {"platform": "reddit"}
341
+ return json_response(200, body)
342
+
343
+ client, _ = make_sync_client(respond)
344
+ assert client.search(platform="reddit").results
345
+
346
+
347
+ def test_search_omits_an_empty_query_rather_than_sending_it_empty() -> None:
348
+ body = discovery_search()
349
+
350
+ def respond(req: httpx.Request) -> httpx.Response:
351
+ assert "q" not in dict(req.url.params)
352
+ return json_response(200, body)
353
+
354
+ client, _ = make_sync_client(respond)
355
+ assert client.search(query="", category="social").results
356
+
357
+
358
+ def test_search_without_query_category_or_platform_never_calls_the_gateway() -> None:
359
+ client, recorder = make_sync_client(
360
+ lambda _req: json_response(200, discovery_search())
361
+ )
362
+ with pytest.raises(
363
+ AnyAPIError, match="at least one of query, category, or platform"
364
+ ):
365
+ client.search(limit=5)
366
+ assert recorder.requests == []
367
+
368
+
334
369
  def test_search_drops_safe_additive_result_and_envelope_fields() -> None:
335
370
  body = discovery_search()
336
371
  results = cast("list[dict[str, object]]", body["results"])
File without changes
File without changes
File without changes
File without changes