Skip to content

Commit ba72325

Browse files
authored
Den 331 Add browserless implementation (#64)
1 parent 8e3a2f4 commit ba72325

File tree

7 files changed

+92
-11
lines changed

7 files changed

+92
-11
lines changed

dendrite_sdk/async_api/_core/_impl_mapping.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33
from dendrite_sdk.async_api._core._impl_browser import ImplBrowser, LocalImpl
44

55
from dendrite_sdk.async_api._ext_impl.browserbase._impl import BrowserBaseImpl
6+
from dendrite_sdk.async_api._ext_impl.browserless._impl import BrowserlessImpl
7+
from dendrite_sdk.async_api._ext_impl.browserless._settings import BrowserlessConfig
68
from dendrite_sdk.remote import Providers
79
from dendrite_sdk.remote.browserbase_config import BrowserbaseConfig
810

911

1012
IMPL_MAPPING: Dict[Type[Providers], Type[ImplBrowser]] = {
1113
BrowserbaseConfig: BrowserBaseImpl,
14+
BrowserlessConfig: BrowserlessImpl,
1215
# BFloatProviderConfig: ,
1316
}
1417

15-
SETTINGS_CLASSES: Dict[str, Type[BrowserbaseConfig]] = {
18+
SETTINGS_CLASSES: Dict[str, Type[Providers]] = {
1619
"browserbase": BrowserbaseConfig,
20+
"browserless": BrowserlessConfig,
1721
}
1822

1923

dendrite_sdk/async_api/_ext_impl/browserbase/_impl.py

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from dendrite_sdk.async_api._ext_impl.browserbase._download import (
1414
AsyncBrowserbaseDownload,
1515
)
16-
from dendrite_sdk.async_api._ext_impl.browserbase._settings import BrowserBaseSettings
1716

1817

1918
class BrowserBaseImpl(ImplBrowser):

dendrite_sdk/async_api/_ext_impl/browserbase/_settings.py

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import json
2+
from typing import TYPE_CHECKING, Optional
3+
from dendrite_sdk._common._exceptions.dendrite_exception import BrowserNotLaunchedError
4+
from dendrite_sdk.async_api._core._impl_browser import ImplBrowser
5+
from dendrite_sdk.async_api._core._type_spec import PlaywrightPage
6+
from dendrite_sdk.async_api._ext_impl.browserless._settings import BrowserlessConfig
7+
8+
if TYPE_CHECKING:
9+
from dendrite_sdk.async_api._core.dendrite_browser import AsyncDendrite
10+
from dendrite_sdk.async_api._ext_impl.browserbase._client import BrowserbaseClient
11+
from playwright.async_api import Playwright
12+
from loguru import logger
13+
import urllib.parse
14+
15+
from dendrite_sdk.async_api._ext_impl.browserbase._download import (
16+
AsyncBrowserbaseDownload,
17+
)
18+
19+
20+
class BrowserlessImpl(ImplBrowser):
21+
def __init__(self, settings: BrowserlessConfig) -> None:
22+
self.settings = settings
23+
self._session_id: Optional[str] = None
24+
25+
async def stop_session(self):
26+
pass
27+
28+
async def start_browser(self, playwright: Playwright, pw_options: dict):
29+
logger.debug("Starting browser")
30+
url = self._format_connection_url(pw_options)
31+
logger.debug(f"Connecting to browser at {url}")
32+
return await playwright.chromium.connect_over_cdp(url)
33+
34+
def _format_connection_url(self, pw_options: dict) -> str:
35+
url = self.settings.url.rstrip("?").rstrip("/")
36+
37+
query = {
38+
"token": self.settings.api_key,
39+
"blockAds": self.settings.block_ads,
40+
"launch": json.dumps(pw_options),
41+
}
42+
43+
if self.settings.proxy:
44+
query["proxy"] = (self.settings.proxy,)
45+
query["proxyCountry"] = (self.settings.proxy_country,)
46+
return f"{url}?{urllib.parse.urlencode(query)}"
47+
48+
async def configure_context(self, browser: "AsyncDendrite"):
49+
pass
50+
51+
async def get_download(
52+
self,
53+
dendrite_browser: "AsyncDendrite",
54+
pw_page: PlaywrightPage,
55+
timeout: float = 30000,
56+
) -> AsyncBrowserbaseDownload:
57+
raise NotImplementedError("Downloads are not supported for Browserless")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import os
2+
from typing import Any, Optional
3+
4+
from pydantic import BaseModel, Field, TypeAdapter, ValidationError, model_validator
5+
from dendrite_sdk.exceptions import MissingApiKeyError
6+
7+
8+
class BrowserlessConfig:
9+
10+
def __init__(
11+
self,
12+
url: str = "wss://production-sfo.browserless.io",
13+
api_key: Optional[str] = None,
14+
proxy: Optional[str] = None,
15+
proxy_country: Optional[str] = None,
16+
block_ads: bool = False,
17+
):
18+
api_key = api_key if api_key is not None else os.getenv("BROWSERLESS_API_KEY")
19+
if api_key is None:
20+
raise MissingApiKeyError("BROWSERLESS_API_KEY")
21+
22+
self.url = url
23+
self.api_key = api_key
24+
self.block_ads = block_ads
25+
self.proxy = proxy
26+
self.proxy_country = proxy_country

dendrite_sdk/remote/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
from typing import Union
2+
from dendrite_sdk.async_api._ext_impl.browserless._settings import BrowserlessConfig
13
from dendrite_sdk.remote.browserbase_config import BrowserbaseConfig
24

35

4-
Providers = BrowserbaseConfig
6+
Providers = Union[BrowserbaseConfig, BrowserlessConfig]
57

68
__all__ = ["Providers", "BrowserbaseConfig"]

0 commit comments

Comments
 (0)