Skip to content

Commit 9a414a1

Browse files
update client settings
1 parent 0e62d34 commit 9a414a1

File tree

8 files changed

+47
-33
lines changed

8 files changed

+47
-33
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "oxylabs-ai-studio"
3-
version = "0.2.12"
3+
version = "0.2.13"
44
description = "Oxylabs studio python sdk"
55
readme = "README.md"
66
keywords = ["oxylabs", "ai", "studio"]

src/oxylabs_ai_studio/apps/ai_crawler.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ def crawl(
5050
"return_sources_limit": return_sources_limit,
5151
"geo_location": geo_location,
5252
}
53-
create_response = self.client.post(url="/extract/run", json=body)
53+
client = self.get_client()
54+
create_response = client.post(url="/extract/run", json=body)
5455
if create_response.status_code != 200:
5556
raise Exception(
5657
f"Failed to create crawl job for {url}: {create_response.text}"
@@ -60,7 +61,7 @@ def crawl(
6061
logger.info(f"Starting crawl for url: {url}. Job id: {run_id}.")
6162
try:
6263
for _ in range(POLL_MAX_ATTEMPTS):
63-
get_response = self.client.get(
64+
get_response = client.get(
6465
"/extract/run/data", params={"run_id": run_id}
6566
)
6667
if get_response.status_code == 202:
@@ -89,7 +90,7 @@ def crawl(
8990
def generate_schema(self, prompt: str) -> dict[str, Any] | None:
9091
logger.info("Generating schema")
9192
body = {"user_prompt": prompt}
92-
response = self.client.post(url="/extract/generate-params", json=body)
93+
response = self.get_client().post(url="/extract/generate-params", json=body)
9394
if response.status_code != 200:
9495
raise Exception(f"Failed to generate schema: {response.text}")
9596
json_response: SchemaResponse = response.json()

src/oxylabs_ai_studio/apps/ai_map.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class AiMapJob(BaseModel):
2424
class AiMap(OxyStudioAIClient):
2525
"""AI Map app."""
2626

27-
def __init__(self, api_key: str):
27+
def __init__(self, api_key: str | None = None):
2828
super().__init__(api_key=api_key)
2929

3030
def map(
@@ -42,7 +42,8 @@ def map(
4242
"geo_location": geo_location,
4343
"render_html": render_javascript,
4444
}
45-
create_response = self.client.post(url="/map", json=body)
45+
client = self.get_client()
46+
create_response = client.post(url="/map", json=body)
4647
if create_response.status_code != 200:
4748
raise Exception(
4849
f"Failed to create map job for {url}: {create_response.text}"
@@ -51,15 +52,15 @@ def map(
5152
run_id = resp_body["run_id"]
5253
try:
5354
for _ in range(POLL_MAX_ATTEMPTS):
54-
get_response = self.client.get("/map/run", params={"run_id": run_id})
55+
get_response = client.get("/map/run", params={"run_id": run_id})
5556
if get_response.status_code != 200:
5657
raise Exception(f"Failed to map {url}: {get_response.text}")
5758
resp_body = get_response.json()
5859
if resp_body["status"] == "completed":
5960
return AiMapJob(
6061
run_id=run_id,
6162
message=resp_body.get("message", None),
62-
data=self._get_data(run_id=run_id),
63+
data=self._get_data(client=client, run_id=run_id),
6364
)
6465
if resp_body["status"] == "failed":
6566
raise Exception(f"Failed to map {url}.")
@@ -71,8 +72,8 @@ def map(
7172
raise e
7273
raise TimeoutError(f"Failed to map {url}: timeout.")
7374

74-
def _get_data(self, run_id: str) -> dict[str, Any]:
75-
get_response = self.client.get("/map/run/data", params={"run_id": run_id})
75+
def _get_data(self, client: httpx.Client, run_id: str) -> dict[str, Any]:
76+
get_response = client.get("/map/run/data", params={"run_id": run_id})
7677
if get_response.status_code != 200:
7778
raise Exception(f"Failed to get data for run {run_id}: {get_response.text}")
7879
return get_response.json().get("data", {}) or {}

src/oxylabs_ai_studio/apps/ai_scraper.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class AiScraperJob(BaseModel):
2525
class AiScraper(OxyStudioAIClient):
2626
"""AI Scraper app."""
2727

28-
def __init__(self, api_key: str):
28+
def __init__(self, api_key: str | None = None):
2929
super().__init__(api_key=api_key)
3030

3131
def scrape(
@@ -46,7 +46,8 @@ def scrape(
4646
"render_html": render_javascript,
4747
"geo_location": geo_location,
4848
}
49-
create_response = self.client.post(url="/scrape", json=body)
49+
client = self.get_client()
50+
create_response = client.post(url="/scrape", json=body)
5051
if create_response.status_code != 200:
5152
raise Exception(
5253
f"Failed to create scrape job for {url}: {create_response.text}"
@@ -55,15 +56,15 @@ def scrape(
5556
run_id = resp_body["run_id"]
5657
try:
5758
for _ in range(POLL_MAX_ATTEMPTS):
58-
get_response = self.client.get("/scrape/run", params={"run_id": run_id})
59+
get_response = client.get("/scrape/run", params={"run_id": run_id})
5960
if get_response.status_code != 200:
6061
raise Exception(f"Failed to scrape {url}: {get_response.text}")
6162
resp_body = get_response.json()
6263
if resp_body["status"] == "completed":
6364
return AiScraperJob(
6465
run_id=run_id,
6566
message=resp_body.get("message", None),
66-
data=self._get_data(run_id=run_id),
67+
data=self._get_data(client=client, run_id=run_id),
6768
)
6869
if resp_body["status"] == "failed":
6970
raise Exception(f"Failed to scrape {url}.")
@@ -75,16 +76,16 @@ def scrape(
7576
raise e
7677
raise TimeoutError(f"Failed to scrape {url}: timeout.")
7778

78-
def _get_data(self, run_id: str) -> dict[str, Any]:
79-
get_response = self.client.get("/scrape/run/data", params={"run_id": run_id})
79+
def _get_data(self, client: httpx.Client, run_id: str) -> dict[str, Any]:
80+
get_response = client.get("/scrape/run/data", params={"run_id": run_id})
8081
if get_response.status_code != 200:
8182
raise Exception(f"Failed to get data for run {run_id}: {get_response.text}")
8283
return get_response.json().get("data", {}) or {}
8384

8485
def generate_schema(self, prompt: str) -> dict[str, Any] | None:
8586
logger.info("Generating schema")
8687
body = {"user_prompt": prompt}
87-
response = self.client.post(url="/scrape/schema", json=body)
88+
response = self.get_client().post(url="/scrape/schema", json=body)
8889
if response.status_code != 200:
8990
raise Exception(f"Failed to generate schema: {response.text}")
9091
json_response: SchemaResponse = response.json()

src/oxylabs_ai_studio/apps/ai_search.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class AiSearchJob(BaseModel):
2929
class AiSearch(OxyStudioAIClient):
3030
"""AI Search app."""
3131

32-
def __init__(self, api_key: str):
32+
def __init__(self, api_key: str | None = None):
3333
super().__init__(api_key=api_key)
3434

3535
def search(
@@ -50,16 +50,15 @@ def search(
5050
"return_content": return_content,
5151
"geo_location": geo_location,
5252
}
53-
create_response = self.client.post(url="/search/run", json=body)
53+
client = self.get_client()
54+
create_response = client.post(url="/search/run", json=body)
5455
if create_response.status_code != 200:
5556
raise Exception(f"Failed to create search job: {create_response.text}")
5657
resp_body = create_response.json()
5758
run_id = resp_body["run_id"]
5859
try:
5960
for _ in range(POLL_MAX_ATTEMPTS):
60-
get_response = self.client.get(
61-
"/search/run/data", params={"run_id": run_id}
62-
)
61+
get_response = client.get("/search/run/data", params={"run_id": run_id})
6362
if get_response.status_code == 202:
6463
time.sleep(POLL_INTERVAL_SECONDS)
6564
continue

src/oxylabs_ai_studio/apps/browser_agent.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class BrowserAgentJob(BaseModel):
2727

2828

2929
class BrowserAgent(OxyStudioAIClient):
30-
def __init__(self, api_key: str):
30+
def __init__(self, api_key: str | None = None):
3131
super().__init__(api_key=api_key)
3232

3333
def run(
@@ -48,15 +48,16 @@ def run(
4848
"auxiliary_prompt": user_prompt,
4949
"geo_location": geo_location,
5050
}
51-
create_response = self.client.post(url="/browser-agent/run", json=body)
51+
client = self.get_client()
52+
create_response = client.post(url="/browser-agent/run", json=body)
5253
if create_response.status_code != 200:
5354
raise Exception(f"Failed to launch browser agent: {create_response.text}")
5455
resp_body = create_response.json()
5556
run_id = resp_body["run_id"]
5657
logger.info(f"Starting browser agent run for url: {url}. Job id: {run_id}.")
5758
try:
5859
for _ in range(POLL_MAX_ATTEMPTS):
59-
get_response = self.client.get(
60+
get_response = client.get(
6061
"/browser-agent/run/data", params={"run_id": run_id}
6162
)
6263
if get_response.status_code == 202:
@@ -85,7 +86,9 @@ def run(
8586
def generate_schema(self, prompt: str) -> dict[str, Any] | None:
8687
logger.info("Generating schema")
8788
body = {"user_prompt": prompt}
88-
response = self.client.post(url="/browser-agent/generate-params", json=body)
89+
response = self.get_client().post(
90+
url="/browser-agent/generate-params", json=body
91+
)
8992
if response.status_code != 200:
9093
raise Exception(f"Failed to generate schema: {response.text}")
9194
json_response: SchemaResponse = response.json()

src/oxylabs_ai_studio/client.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88

99
logger = get_logger(__name__)
1010

11+
_UA_API: str | None = None
12+
13+
14+
def _resolve_ua() -> str:
15+
return (
16+
_UA_API.strip() if isinstance(_UA_API, str) and _UA_API.strip() else None
17+
) or "python-sdk"
18+
1119

1220
class OxyStudioAIClient:
1321
"""Main client for interacting with the Oxy Studio AI API."""
@@ -25,15 +33,16 @@ def __init__(self, api_key: str | None = None, timeout: float = 30.0):
2533
self.api_key = resolved_key
2634
self.base_url = settings.OXYLABS_AI_STUDIO_API_URL
2735
self.timeout = timeout
28-
# Initialize HTTP client with proper headers
29-
self.client = httpx.Client(
36+
37+
def get_client(self) -> httpx.Client:
38+
return httpx.Client(
3039
base_url=self.base_url,
3140
headers={
3241
"x-api-key": self.api_key,
3342
"Content-Type": "application/json",
34-
"User-Agent": "python-sdk",
43+
"User-Agent": _resolve_ua(),
3544
},
36-
timeout=timeout,
45+
timeout=self.timeout,
3746
)
3847

3948
@asynccontextmanager
@@ -44,7 +53,7 @@ async def async_client(self) -> AsyncGenerator[httpx.AsyncClient, None]:
4453
headers={
4554
"x-api-key": self.api_key,
4655
"Content-Type": "application/json",
47-
"User-Agent": "python-sdk",
56+
"User-Agent": _resolve_ua(),
4857
},
4958
timeout=self.timeout,
5059
)

uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)