getanyapi 0.61.2__tar.gz → 0.63.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.
- {getanyapi-0.61.2 → getanyapi-0.63.0}/PKG-INFO +4 -3
- {getanyapi-0.61.2 → getanyapi-0.63.0}/README.md +3 -2
- {getanyapi-0.61.2 → getanyapi-0.63.0}/pyproject.toml +1 -1
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/__init__.py +1 -1
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/maps.py +2 -2
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/zillow.py +118 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/types.py +5 -6
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_account.py +18 -13
- {getanyapi-0.61.2 → getanyapi-0.63.0}/.gitignore +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/_account.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/_async_client.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/_client.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/_errors.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/_idempotency.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/_pagination.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/_transport.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/discovery_types.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/__init__.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/ahrefs.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/airbnb.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/alibaba.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/amazon.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/apollo.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/appstore.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/bluesky.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/booking.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/capterra.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/chatgpt.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/coinmarketcap.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/company.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/company_enrichment.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/company_identify.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/company_search.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/congress.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/contact_enrichment.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/douyin.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/ebay.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/email.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/email_finding.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/email_verification.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/facebook.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/fiverr.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/g2.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/gemini.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/github.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/glassdoor.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/google.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/google_ads.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/google_finance.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/google_shopping.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/hackernews.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/indeed.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/instagram.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/job_search.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/linkedin.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/mobile_phone.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/naver.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/nextdoor.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/people_search.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/perplexity.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/person.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/person_enrichment.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/pinterest.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/playstore.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/polymarket.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/property_records.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/realtor.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/reddit.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/redfin.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/rednote.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/sec.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/semrush.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/seo.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/similarweb.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/snapchat.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/social.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/spotify.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/substack.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/technographics.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/threads.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/tiktok.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/tiktok_shop.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/tripadvisor.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/trustpilot.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/truthsocial.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/twitter.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/upwork.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/walmart.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/web.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/weibo.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/yahoo_finance.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/yelp.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/youtube.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/platforms/zhihu.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/src/getanyapi/py.typed +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/conftest.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_client.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_durable_requests.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_envelope.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_errors.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_fixture_roundtrip.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_fixture_sweep.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_not_found_reason.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_pagination.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/tests/test_transport.py +0 -0
- {getanyapi-0.61.2 → getanyapi-0.63.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: getanyapi
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.63.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
|
|
@@ -195,8 +195,9 @@ result = agent_signup(label="my-agent")
|
|
|
195
195
|
client = AnyAPI(api_key=result.secret)
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
-
The key ships with a small starter balance and a per-key spend cap;
|
|
199
|
-
|
|
198
|
+
The key ships with a small starter balance and a per-key spend cap; to go past the cap, a human
|
|
199
|
+
authorizes an AnyAPI wallet over OAuth, as described in
|
|
200
|
+
[agent self-signup](https://getanyapi.com/docs/agent-self-signup).
|
|
200
201
|
|
|
201
202
|
## Docs
|
|
202
203
|
|
|
@@ -166,8 +166,9 @@ result = agent_signup(label="my-agent")
|
|
|
166
166
|
client = AnyAPI(api_key=result.secret)
|
|
167
167
|
```
|
|
168
168
|
|
|
169
|
-
The key ships with a small starter balance and a per-key spend cap;
|
|
170
|
-
|
|
169
|
+
The key ships with a small starter balance and a per-key spend cap; to go past the cap, a human
|
|
170
|
+
authorizes an AnyAPI wallet over OAuth, as described in
|
|
171
|
+
[agent self-signup](https://getanyapi.com/docs/agent-self-signup).
|
|
171
172
|
|
|
172
173
|
## Docs
|
|
173
174
|
|
|
@@ -746,7 +746,7 @@ class MapsNamespace:
|
|
|
746
746
|
Fetch up to 100 Google Maps reviews for a place by place ID, sorted the way
|
|
747
747
|
you need, in one normalized response.
|
|
748
748
|
|
|
749
|
-
Price: $0.
|
|
749
|
+
Price: $0.0035 per request.
|
|
750
750
|
|
|
751
751
|
Example:
|
|
752
752
|
res = client.maps.reviews(limit=3, placeId="ChIJN1t_tDeuEmsRUsoyG83frY4")
|
|
@@ -881,7 +881,7 @@ class AsyncMapsNamespace:
|
|
|
881
881
|
Fetch up to 100 Google Maps reviews for a place by place ID, sorted the way
|
|
882
882
|
you need, in one normalized response.
|
|
883
883
|
|
|
884
|
-
Price: $0.
|
|
884
|
+
Price: $0.0035 per request.
|
|
885
885
|
|
|
886
886
|
Example:
|
|
887
887
|
res = client.maps.reviews(limit=3, placeId="ChIJN1t_tDeuEmsRUsoyG83frY4")
|
|
@@ -15,6 +15,21 @@ if TYPE_CHECKING:
|
|
|
15
15
|
from .._client import AnyAPI
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
class ZillowAgentInput(TypedDict, total=False):
|
|
19
|
+
"""Input for Zillow Agent."""
|
|
20
|
+
|
|
21
|
+
allowFallbacks: NotRequired[bool]
|
|
22
|
+
"""Optional, default true. When false, only the sources listed in `source` may serve; the request is refused with no charge if none of them can. When true, the listed sources are tried first and any other source may serve after them, at the normal price. Default: true."""
|
|
23
|
+
ignoreSources: NotRequired[list[str]]
|
|
24
|
+
"""Optional. Source ids to skip for this request, taken from this endpoint's `lanes[].source.id`. The cheapest remaining source serves and the price is that of the dearest remaining source. An id that does not serve this endpoint, or that is also in `source`, is rejected as invalid input with no charge; skipping every source is rejected the same way."""
|
|
25
|
+
preferLatencyUnderMs: NotRequired[int]
|
|
26
|
+
"""Optional; omit it and routing is unchanged, with the cheapest source serving. Prefer sources whose typical response time (median over the trailing 30 days, as published on this endpoint's lane health) is under this many milliseconds; among those, the cheapest serves. This can raise your price: when the cheapest source misses the target, a faster and dearer one serves, and you are quoted and charged its price. If no source is that fast the request is still served, by whichever source offers the best speed for its price - it is never refused for being slow. Sources we have not timed are tried last. This is a preference, not a guarantee: the median describes past requests and is not a ceiling on this one, and it excludes any wait this request itself asks for. On a paginated walk it applies to the first page only: later pages stay with the source that page chose, at the price it was quoted. Minimum: 1."""
|
|
27
|
+
source: NotRequired[list[str]]
|
|
28
|
+
"""Optional. Source ids to prefer, in order, taken from this endpoint's `lanes[].source.id` in /catalog or /apis. Omit it and the cheapest source serves, with automatic failover. Listed sources are tried first in the order given, then the others, unless `allowFallbacks` is false. A single source with `allowFallbacks` false is served only by that source at its price, quoted and charged exactly, with no failover. The price is that of the dearest source that may serve. An id that does not serve this endpoint is rejected as invalid input with no charge; a listed source that is not serving right now is refused with no charge, so omit `source` to be served by another. On a paginated walk, later pages must include the source that served page one, or omit `source`."""
|
|
29
|
+
url: Required[str]
|
|
30
|
+
"""Zillow agent profile URL (e.g. https://www.zillow.com/profile/gregorycarlsonATX/)."""
|
|
31
|
+
|
|
32
|
+
|
|
18
33
|
class ZillowPropertyInput(TypedDict, total=False):
|
|
19
34
|
"""Input for Zillow Property."""
|
|
20
35
|
|
|
@@ -152,6 +167,67 @@ class ZillowSearchInput(TypedDict, total=False):
|
|
|
152
167
|
"""Optional. Source ids to prefer, in order, taken from this endpoint's `lanes[].source.id` in /catalog or /apis. Omit it and the cheapest source serves, with automatic failover. Listed sources are tried first in the order given, then the others, unless `allowFallbacks` is false. A single source with `allowFallbacks` false is served only by that source at its price, quoted and charged exactly, with no failover. The price is that of the dearest source that may serve. An id that does not serve this endpoint is rejected as invalid input with no charge; a listed source that is not serving right now is refused with no charge, so omit `source` to be served by another. On a paginated walk, later pages must include the source that served page one, or omit `source`."""
|
|
153
168
|
|
|
154
169
|
|
|
170
|
+
class ZillowAgentData(BaseModel):
|
|
171
|
+
model_config = ConfigDict(extra="allow", populate_by_name=True)
|
|
172
|
+
|
|
173
|
+
bio: str | None = Field(
|
|
174
|
+
default=None, description="Agent's self-written biography, as HTML."
|
|
175
|
+
)
|
|
176
|
+
company: str | None = Field(
|
|
177
|
+
default=None,
|
|
178
|
+
description="Brokerage or business name the agent works under. Populated whenever the provider has data for the entity. Present whenever the upstream returns this record.",
|
|
179
|
+
)
|
|
180
|
+
email: str | None = Field(
|
|
181
|
+
default=None,
|
|
182
|
+
description="Agent's email address as listed on the profile. Populated whenever the provider has data for the entity. Present whenever the upstream returns this record.",
|
|
183
|
+
)
|
|
184
|
+
for_sale_count: int | None = Field(
|
|
185
|
+
default=None,
|
|
186
|
+
alias="forSaleCount",
|
|
187
|
+
description="Number of active for-sale listings.",
|
|
188
|
+
)
|
|
189
|
+
image: str | None = Field(
|
|
190
|
+
default=None,
|
|
191
|
+
description="Profile photo URL. Populated whenever the provider has data for the entity. Present whenever the upstream returns this record.",
|
|
192
|
+
)
|
|
193
|
+
is_top_agent: bool | None = Field(
|
|
194
|
+
default=None,
|
|
195
|
+
alias="isTopAgent",
|
|
196
|
+
description="True when Zillow flags the agent as a top agent.",
|
|
197
|
+
)
|
|
198
|
+
name: str = Field(
|
|
199
|
+
description="Agent's full name. Populated whenever the provider has data for the entity."
|
|
200
|
+
)
|
|
201
|
+
phone: str | None = Field(
|
|
202
|
+
default=None,
|
|
203
|
+
description="Agent's phone number as listed on the profile (the cell number when one is listed). Populated whenever the provider has data for the entity. Present whenever the upstream returns this record.",
|
|
204
|
+
)
|
|
205
|
+
rating: float | None = Field(
|
|
206
|
+
default=None, description="Average review rating out of 5."
|
|
207
|
+
)
|
|
208
|
+
review_count: int | None = Field(
|
|
209
|
+
default=None,
|
|
210
|
+
alias="reviewCount",
|
|
211
|
+
description="Number of reviews on the profile.",
|
|
212
|
+
)
|
|
213
|
+
service_areas: list[str] | None = Field(
|
|
214
|
+
default=None,
|
|
215
|
+
alias="serviceAreas",
|
|
216
|
+
description='Cities and areas the agent lists as served, e.g. "Austin, TX".',
|
|
217
|
+
)
|
|
218
|
+
total_sales: int | None = Field(
|
|
219
|
+
default=None,
|
|
220
|
+
alias="totalSales",
|
|
221
|
+
description="Total sales on record for the agent (for a team lead, the team's total).",
|
|
222
|
+
)
|
|
223
|
+
url: str = Field(
|
|
224
|
+
description="Canonical Zillow profile URL. Populated whenever the provider has data for the entity."
|
|
225
|
+
)
|
|
226
|
+
username: str = Field(
|
|
227
|
+
description="Zillow screen name, the last segment of the profile URL. Populated whenever the provider has data for the entity."
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
|
|
155
231
|
class ZillowPropertyData(BaseModel):
|
|
156
232
|
items: list[ZillowPropertyItem] = Field(
|
|
157
233
|
description="The matched property record (single element for a property lookup). Populated whenever the provider has data for the entity."
|
|
@@ -344,6 +420,27 @@ class ZillowNamespace:
|
|
|
344
420
|
def __init__(self, client: "AnyAPI") -> None:
|
|
345
421
|
self._client = client
|
|
346
422
|
|
|
423
|
+
def agent(
|
|
424
|
+
self,
|
|
425
|
+
*,
|
|
426
|
+
options: RequestOptions | None = None,
|
|
427
|
+
**input: Unpack[ZillowAgentInput],
|
|
428
|
+
) -> RunResult[ZillowAgentData]:
|
|
429
|
+
"""Zillow Agent
|
|
430
|
+
|
|
431
|
+
Fetch one Zillow real estate agent's profile by URL: name, phone, email,
|
|
432
|
+
brokerage, rating, review count, sales, and service areas.
|
|
433
|
+
|
|
434
|
+
Price: $0.0005 per request.
|
|
435
|
+
|
|
436
|
+
Example:
|
|
437
|
+
res = client.zillow.agent(url="https://www.zillow.com/profile/gregorycarlsonATX/")
|
|
438
|
+
"""
|
|
439
|
+
raw = self._client._run_raw( # pyright: ignore[reportPrivateUsage]
|
|
440
|
+
"zillow.agent", dict(input), options
|
|
441
|
+
)
|
|
442
|
+
return RunResult[ZillowAgentData].model_validate(raw)
|
|
443
|
+
|
|
347
444
|
def property(
|
|
348
445
|
self,
|
|
349
446
|
*,
|
|
@@ -396,6 +493,27 @@ class AsyncZillowNamespace:
|
|
|
396
493
|
def __init__(self, client: "AsyncAnyAPI") -> None:
|
|
397
494
|
self._client = client
|
|
398
495
|
|
|
496
|
+
async def agent(
|
|
497
|
+
self,
|
|
498
|
+
*,
|
|
499
|
+
options: RequestOptions | None = None,
|
|
500
|
+
**input: Unpack[ZillowAgentInput],
|
|
501
|
+
) -> RunResult[ZillowAgentData]:
|
|
502
|
+
"""Zillow Agent
|
|
503
|
+
|
|
504
|
+
Fetch one Zillow real estate agent's profile by URL: name, phone, email,
|
|
505
|
+
brokerage, rating, review count, sales, and service areas.
|
|
506
|
+
|
|
507
|
+
Price: $0.0005 per request.
|
|
508
|
+
|
|
509
|
+
Example:
|
|
510
|
+
res = client.zillow.agent(url="https://www.zillow.com/profile/gregorycarlsonATX/")
|
|
511
|
+
"""
|
|
512
|
+
raw = await self._client._arun_raw( # pyright: ignore[reportPrivateUsage]
|
|
513
|
+
"zillow.agent", dict(input), options
|
|
514
|
+
)
|
|
515
|
+
return RunResult[ZillowAgentData].model_validate(raw)
|
|
516
|
+
|
|
399
517
|
async def property(
|
|
400
518
|
self,
|
|
401
519
|
*,
|
|
@@ -10,7 +10,7 @@ unknown fields, exposed via ``.model_extra``.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
-
from typing import Any, Generic, Literal, TypeVar, cast
|
|
13
|
+
from typing import Any, Generic, Literal, TypeVar, cast, get_args
|
|
14
14
|
|
|
15
15
|
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
16
16
|
from typing_extensions import TypedDict
|
|
@@ -73,9 +73,10 @@ class OutputFound(BaseModel, Generic[T]):
|
|
|
73
73
|
# words; ``tests/test_not_found_reason.py`` holds the two together once the live
|
|
74
74
|
# OpenAPI carries the field. ``not_found``: the source states the target does not
|
|
75
75
|
# exist, or returned nothing for it. ``suspended``: the platform has suspended the
|
|
76
|
-
# account.
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
# account. ``unavailable``: the platform did not show this to the source: it may not
|
|
77
|
+
# exist, or it may be visible only to signed-in users.
|
|
78
|
+
NotFoundReason = Literal["not_found", "suspended", "unavailable"]
|
|
79
|
+
NOT_FOUND_REASONS: tuple[str, ...] = get_args(NotFoundReason)
|
|
79
80
|
|
|
80
81
|
|
|
81
82
|
class OutputNotFound(BaseModel):
|
|
@@ -283,8 +284,6 @@ class AgentSignupResult(BaseModel):
|
|
|
283
284
|
|
|
284
285
|
secret: str
|
|
285
286
|
cap_usd: float = Field(alias="capUsd")
|
|
286
|
-
claim_token: str = Field(alias="claimToken")
|
|
287
|
-
claim_url: str = Field(alias="claimUrl")
|
|
288
287
|
|
|
289
288
|
|
|
290
289
|
# Convenience aliases used by the transport for untyped generic runs.
|
|
@@ -464,23 +464,30 @@ def test_describe_404_raises_not_found() -> None:
|
|
|
464
464
|
client.describe("nope.gone")
|
|
465
465
|
|
|
466
466
|
|
|
467
|
-
|
|
467
|
+
SIGNUP_BODY: dict[str, object] = {"secret": "sk_live_x", "capUsd": 0.15, "keyId": "key_1"}
|
|
468
|
+
# The gateway still sends these retired claim-flow fields until it drops them.
|
|
469
|
+
RETIRED_SIGNUP_FIELDS: dict[str, object] = {
|
|
470
|
+
"verificationStatus": "pending",
|
|
471
|
+
"claimToken": "",
|
|
472
|
+
"claimUrl": "https://getanyapi.com/dashboard",
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
@pytest.mark.parametrize(
|
|
477
|
+
"body",
|
|
478
|
+
[SIGNUP_BODY, {**SIGNUP_BODY, **RETIRED_SIGNUP_FIELDS}],
|
|
479
|
+
ids=["without-retired-fields", "with-retired-fields"],
|
|
480
|
+
)
|
|
481
|
+
def test_agent_signup_maps_result(
|
|
482
|
+
monkeypatch: pytest.MonkeyPatch, body: dict[str, object]
|
|
483
|
+
) -> None:
|
|
468
484
|
captured: dict[str, object] = {}
|
|
469
485
|
|
|
470
486
|
def handler(request: httpx.Request) -> httpx.Response:
|
|
471
487
|
captured["path"] = request.url.path
|
|
472
488
|
captured["auth"] = request.headers.get("authorization")
|
|
473
489
|
captured["body"] = json.loads(request.content)
|
|
474
|
-
return json_response(
|
|
475
|
-
200,
|
|
476
|
-
{
|
|
477
|
-
"secret": "sk_live_x",
|
|
478
|
-
"capUsd": 0.15,
|
|
479
|
-
"claimToken": "tok",
|
|
480
|
-
"claimUrl": "https://getanyapi.com/dashboard",
|
|
481
|
-
"keyId": "key_1",
|
|
482
|
-
},
|
|
483
|
-
)
|
|
490
|
+
return json_response(200, body)
|
|
484
491
|
|
|
485
492
|
transport = httpx.MockTransport(handler)
|
|
486
493
|
import getanyapi._client as client_mod
|
|
@@ -498,8 +505,6 @@ def test_agent_signup_maps_result(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
|
498
505
|
assert captured["body"] == {"sponsorEmail": "me@x.com", "label": "bot"}
|
|
499
506
|
assert result.secret == "sk_live_x"
|
|
500
507
|
assert result.cap_usd == 0.15
|
|
501
|
-
assert result.claim_token == "tok"
|
|
502
|
-
assert result.claim_url == "https://getanyapi.com/dashboard"
|
|
503
508
|
|
|
504
509
|
|
|
505
510
|
async def test_async_account() -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|