From 645e897348d54bef40cb2d9470838da6617cfb34 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 22:18:20 +0000 Subject: [PATCH 01/10] feat(api): api update (#48) --- .stats.yml | 2 +- src/browserbase/resources/projects.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1a6b2b5..b04bed2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-b341dd9d5bb77c4f217b94b186763e730fd798fbb773a5e90bb4e2a8d4a2c822.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-d8e42f141c0955e8100ca3ce041ce8dedf5dcf68b04e554a5704e4c2003c2fd4.yml diff --git a/src/browserbase/resources/projects.py b/src/browserbase/resources/projects.py index f8b1936..bf4a5df 100644 --- a/src/browserbase/resources/projects.py +++ b/src/browserbase/resources/projects.py @@ -84,7 +84,7 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ProjectListResponse: - """List all projects""" + """List projects""" return self._get( "/v1/projects", options=make_request_options( @@ -190,7 +190,7 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ProjectListResponse: - """List all projects""" + """List projects""" return await self._get( "/v1/projects", options=make_request_options( From f5c90937330f2acfe4c6a97983136f3f482c7d39 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Fri, 1 Nov 2024 23:44:52 +0000 Subject: [PATCH 02/10] feat: migrating docs --- examples/migrations/get_connect_url.py | 63 +++++++ examples/playwright_proxy.py | 31 +++- migrating.md | 243 +++++++++++++++++++++++++ 3 files changed, 332 insertions(+), 5 deletions(-) create mode 100644 examples/migrations/get_connect_url.py create mode 100644 migrating.md diff --git a/examples/migrations/get_connect_url.py b/examples/migrations/get_connect_url.py new file mode 100644 index 0000000..1c73036 --- /dev/null +++ b/examples/migrations/get_connect_url.py @@ -0,0 +1,63 @@ +from browserbase import Browserbase + +# import os +from typing import Optional + +# BROWSERBASE_API_KEY = os.environ.get("BROWSERBASE_API_KEY") +# BROWSERBASE_PROJECT_ID = os.environ.get("BROWSERBASE_PROJECT_ID") +# bb = Browserbase(api_key=BROWSERBASE_API_KEY) + + +def get_connect_url( + bb: Browserbase, session_id: Optional[str] = None, proxy: Optional[bool] = None +): + base_url = f"{BROWSERBASE_CONNECT_URL}?apiKey={bb.api_key}" + if session_id: + base_url += f"&sessionId={session_id}" + if proxy: + base_url += "&enableProxy=true" + + return base_url + + +def list_sessions(bb: Browserbase): + return bb.sessions.list() + + +# Original Signature: def create_session(self, options: Optional[CreateSessionOptions] = None) -> Session +# New Signature: https://github.com/browserbase/sdk-python/blob/548e0314002e2e9a8c1ab78b54b20bb6e7dea769/src/browserbase/resources/sessions/sessions.py#L101-L117 +def create_session(bb: Browserbase, project_id: str, **kwargs): + return bb.sessions.create(project_id=project_id, **kwargs) + + +def complete_session(bb: Browserbase, project_id: str, session_id: str): + return bb.sessions.update( + id=session_id, project_id=project_id, status="REQUEST_RELEASE" + ) + + +def get_session(bb: Browserbase, session_id: str): + return bb.sessions.retrieve(id=session_id) + + +def get_session_recording(bb: Browserbase, session_id: str): + return bb.sessions.recording.retrieve(id=session_id) + + +# Original Signature: def get_session_downloads(self, session_id: str, retry_interval: int = 2000, retry_count: int = 2) -> Optional[bytes]: +# To avoid rate limiting, we don't allow retry_interval to be configured; however, you can configure retries with the following syntax on bb init: +# bb = Browserbase(api_key=BROWSERBASE_API_KEY, max_retries=5) +def get_session_downloads(bb: Browserbase, session_id: str): + return bb.sessions.downloads.list(id=session_id) + + +def get_debug_connection_urls(bb: Browserbase, session_id: str): + return bb.sessions.debug(id=session_id) + + +def get_session_logs(bb: Browserbase, session_id: str): + return bb.sessions.logs.list(id=session_id) + + +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +bb.sessions.debug() diff --git a/examples/playwright_proxy.py b/examples/playwright_proxy.py index 8378e29..62ecb29 100644 --- a/examples/playwright_proxy.py +++ b/examples/playwright_proxy.py @@ -24,11 +24,15 @@ def check_proxy_bytes(session_id: str) -> None: def run_enable_via_create_session(playwright: Playwright) -> None: session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID, proxies=True) + print("Connecting") browser = playwright.chromium.connect_over_cdp(session.connect_url) + print("Connected") context = browser.contexts[0] page = context.pages[0] + print("Going to google") page.goto("https://www.google.com") + print("Got title") page_title = page.title() page.close() @@ -176,9 +180,26 @@ def run_geolocation_non_american_city(playwright: Playwright) -> None: if __name__ == "__main__": with sync_playwright() as playwright: # You can run any of these tests by uncommenting them + print("\nRunning: enable_via_create_session") run_enable_via_create_session(playwright) - # run_enable_via_querystring_with_created_session(playwright) - # run_geolocation_country(playwright) - # run_geolocation_state(playwright) - # run_geolocation_american_city(playwright) - # run_geolocation_non_american_city(playwright) + print("✓ Completed: enable_via_create_session\n") + + print("Running: enable_via_querystring_with_created_session") + run_enable_via_querystring_with_created_session(playwright) + print("✓ Completed: enable_via_querystring_with_created_session\n") + + print("Running: geolocation_country") + run_geolocation_country(playwright) + print("✓ Completed: geolocation_country\n") + + print("Running: geolocation_state") + run_geolocation_state(playwright) + print("✓ Completed: geolocation_state\n") + + print("Running: geolocation_american_city") + run_geolocation_american_city(playwright) + print("✓ Completed: geolocation_american_city\n") + + print("Running: geolocation_non_american_city") + run_geolocation_non_american_city(playwright) + print("✓ Completed: geolocation_non_american_city\n") diff --git a/migrating.md b/migrating.md new file mode 100644 index 0000000..23aa7b9 --- /dev/null +++ b/migrating.md @@ -0,0 +1,243 @@ +# Upgrade guide to v1.0 + +The Browserbase v1.0.0 Python SDK has been rewritten from the ground up and ships with a ton of new features and better support that we can't wait for you to try. Unfortunately, however, this means that the old SDKs will be deprecated and archived in favor of the new SDK. + +We hope this guide is useful to you; if you have any questions don't hesitate to reach out to support@browserbase.com or [create a new issue](https://github.com/browserbase/sdk-python/issues/new). + +## Create Session + +### Old SDK + +```python +from browserbase import Browserbase, CreateSessionOptions + +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +options = CreateSessionOptions(extensionId='123') +browserbase.create_session(options) +``` + +Function signature: `def create_session(self, options: Optional[CreateSessionOptions] = None)` + +`CreateSessionOptions` is a Pydantic object defined [here](https://github.com/browserbase/python-sdk/blob/0a499ba29853f20bb3055d7c81c5f61c24fcd9ec/browserbase/__init__.py#L52) in the old SDK. + +### New SDK + +```python +from browserbase import Browserbase + +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) +``` + +For more complex session creation, you can import `BrowserSettings` and use Pydantic's `TypeAdapter` to conform JSON spec to the appropriate Pydantic class. You can also import each individual subclass, but this may be rather tedious. + +```python +from browserbase import Browserbase +from pydantic import TypeAdapter +from browserbase.types.session_create_params import BrowserSettings + +session = bb.sessions.create( + project_id=BROWSERBASE_PROJECT_ID, + extension_id="some_extension_id" + browser_settings=TypeAdapter(BrowserSettings).validate_python( + {"context": {"id": context_id, "persist": True}} + ), + ) +``` + +## Get Connection Url + +### Old SDK + +```python +from browserbase import Browserbase + +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) + +# To create a new session and connect to it +connect_url = browserbase.get_connect_url() + +# To connect to a created session +connect_url = browserbase.get_connect_url(session_id=some_session.id) +``` + +### New SDK + +```python +from browserbase import Browserbase +bb = Browserbase(api_key=BROWSERBASE_API_KEY) + +# We must create a session first +session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) +connect_url = session.connect_url +``` + +## List Sessions + +### Old SDK + +```python +from browserbase import Browserbase +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +sessions = browserbase.list_sessions() +``` + +### New SDK + +```python +from browserbase import Browserbase +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +sessions = bb.sessions.list() +``` + +## Complete Session + +### Old SDK + +```python +from browserbase import Browserbase + +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +browserbase.complete_session(session_id=some_session.id) +``` + +### New SDK + +```python +from browserbase import Browserbase +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +bb.sessions.update(id=some_session.id, status="REQUEST_RELEASE") +``` + +## Get Session + +### Old SDK + +```python +from browserbase import Browserbase +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +session = browserbase.get_session(session_id=some_session.id) +``` + +### New SDK + +```python +from browserbase import Browserbase +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +session = bb.sessions.retrieve(id=some_session.id) +``` + +## Get Session Recording + +### Old SDK + +```python +from browserbase import Browserbase +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +recording = browserbase.get_session_recording(session_id=some_session.id) +``` + +### New SDK + +```python +from browserbase import Browserbase +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +recording = bb.sessions.recording.retrieve(id=some_session.id) +``` + +## Get Session Downloads + +### Old SDK + +> [!NOTE] +> The parameter `retry_interval` is no longer supported. You can configure retries with the following syntax on bb init: +> +> `bb = Browserbase(api_key=BROWSERBASE_API_KEY, max_retries=5)` + +```python +from browserbase import Browserbase +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +downloads = browserbase.get_session_downloads(session_id=some_session.id) +``` + +### New SDK + +```python +from browserbase import Browserbase +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +downloads = bb.sessions.downloads.list(id=some_session.id) +``` + +## Get Debug Connection URLs + +### Old SDK + +```python +from browserbase import Browserbase +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +debug_urls = browserbase.get_debug_connection_urls(session_id=some_session.id) +``` + +### New SDK + +```python +from browserbase import Browserbase +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +debug_urls = bb.sessions.debug(id=some_session.id) +``` + +## Get Session Logs + +### Old SDK + +```python +from browserbase import Browserbase +browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +logs = browserbase.get_session_logs(session_id=some_session.id) +``` + +### New SDK + +```python +from browserbase import Browserbase +bb = Browserbase(api_key=BROWSERBASE_API_KEY) +logs = bb.sessions.logs.list(id=some_session.id) +``` + +# Deprecated Methods + +`load`, `load_url`, and `screenshot` are fully deprecated. You can use the following example instead that encapsulates the same functionality using Playwright + +```python +from playwright.sync_api import Playwright, sync_playwright +from browserbase import Browserbase + +bb = Browserbase(api_key=BROWSERBASE_API_KEY) + +def run(playwright: Playwright) -> None: + # Create a session on Browserbase + session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) + + # Connect to the remote session + chromium = playwright.chromium + browser = chromium.connect_over_cdp(session.connect_url) + context = browser.contexts[0] + page = context.pages[0] + + # Execute Playwright actions on the remote browser tab + page.goto("https://news.ycombinator.com/") + page_title = page.title() + assert ( + page_title == "Hacker News" + ), f"Page title is not 'Hacker News', it is '{page_title}'" + page.screenshot(path="screenshot.png") + + page.close() + browser.close() + print("Done!") + + +if __name__ == "__main__": + with sync_playwright() as playwright: + run(playwright) +``` From 2530a9c6aa9c8aa29b180a7a5a912251dca4b2d9 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Fri, 1 Nov 2024 23:44:53 +0000 Subject: [PATCH 03/10] feat: undo playwright_roxy --- examples/playwright_proxy.py | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/examples/playwright_proxy.py b/examples/playwright_proxy.py index 62ecb29..8378e29 100644 --- a/examples/playwright_proxy.py +++ b/examples/playwright_proxy.py @@ -24,15 +24,11 @@ def check_proxy_bytes(session_id: str) -> None: def run_enable_via_create_session(playwright: Playwright) -> None: session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID, proxies=True) - print("Connecting") browser = playwright.chromium.connect_over_cdp(session.connect_url) - print("Connected") context = browser.contexts[0] page = context.pages[0] - print("Going to google") page.goto("https://www.google.com") - print("Got title") page_title = page.title() page.close() @@ -180,26 +176,9 @@ def run_geolocation_non_american_city(playwright: Playwright) -> None: if __name__ == "__main__": with sync_playwright() as playwright: # You can run any of these tests by uncommenting them - print("\nRunning: enable_via_create_session") run_enable_via_create_session(playwright) - print("✓ Completed: enable_via_create_session\n") - - print("Running: enable_via_querystring_with_created_session") - run_enable_via_querystring_with_created_session(playwright) - print("✓ Completed: enable_via_querystring_with_created_session\n") - - print("Running: geolocation_country") - run_geolocation_country(playwright) - print("✓ Completed: geolocation_country\n") - - print("Running: geolocation_state") - run_geolocation_state(playwright) - print("✓ Completed: geolocation_state\n") - - print("Running: geolocation_american_city") - run_geolocation_american_city(playwright) - print("✓ Completed: geolocation_american_city\n") - - print("Running: geolocation_non_american_city") - run_geolocation_non_american_city(playwright) - print("✓ Completed: geolocation_non_american_city\n") + # run_enable_via_querystring_with_created_session(playwright) + # run_geolocation_country(playwright) + # run_geolocation_state(playwright) + # run_geolocation_american_city(playwright) + # run_geolocation_non_american_city(playwright) From bc333a4d9ab906e73bfbdd145bb6698ce9842318 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Fri, 1 Nov 2024 23:44:53 +0000 Subject: [PATCH 04/10] feat: rm scratch --- examples/migrations/get_connect_url.py | 63 -------------------------- 1 file changed, 63 deletions(-) delete mode 100644 examples/migrations/get_connect_url.py diff --git a/examples/migrations/get_connect_url.py b/examples/migrations/get_connect_url.py deleted file mode 100644 index 1c73036..0000000 --- a/examples/migrations/get_connect_url.py +++ /dev/null @@ -1,63 +0,0 @@ -from browserbase import Browserbase - -# import os -from typing import Optional - -# BROWSERBASE_API_KEY = os.environ.get("BROWSERBASE_API_KEY") -# BROWSERBASE_PROJECT_ID = os.environ.get("BROWSERBASE_PROJECT_ID") -# bb = Browserbase(api_key=BROWSERBASE_API_KEY) - - -def get_connect_url( - bb: Browserbase, session_id: Optional[str] = None, proxy: Optional[bool] = None -): - base_url = f"{BROWSERBASE_CONNECT_URL}?apiKey={bb.api_key}" - if session_id: - base_url += f"&sessionId={session_id}" - if proxy: - base_url += "&enableProxy=true" - - return base_url - - -def list_sessions(bb: Browserbase): - return bb.sessions.list() - - -# Original Signature: def create_session(self, options: Optional[CreateSessionOptions] = None) -> Session -# New Signature: https://github.com/browserbase/sdk-python/blob/548e0314002e2e9a8c1ab78b54b20bb6e7dea769/src/browserbase/resources/sessions/sessions.py#L101-L117 -def create_session(bb: Browserbase, project_id: str, **kwargs): - return bb.sessions.create(project_id=project_id, **kwargs) - - -def complete_session(bb: Browserbase, project_id: str, session_id: str): - return bb.sessions.update( - id=session_id, project_id=project_id, status="REQUEST_RELEASE" - ) - - -def get_session(bb: Browserbase, session_id: str): - return bb.sessions.retrieve(id=session_id) - - -def get_session_recording(bb: Browserbase, session_id: str): - return bb.sessions.recording.retrieve(id=session_id) - - -# Original Signature: def get_session_downloads(self, session_id: str, retry_interval: int = 2000, retry_count: int = 2) -> Optional[bytes]: -# To avoid rate limiting, we don't allow retry_interval to be configured; however, you can configure retries with the following syntax on bb init: -# bb = Browserbase(api_key=BROWSERBASE_API_KEY, max_retries=5) -def get_session_downloads(bb: Browserbase, session_id: str): - return bb.sessions.downloads.list(id=session_id) - - -def get_debug_connection_urls(bb: Browserbase, session_id: str): - return bb.sessions.debug(id=session_id) - - -def get_session_logs(bb: Browserbase, session_id: str): - return bb.sessions.logs.list(id=session_id) - - -bb = Browserbase(api_key=BROWSERBASE_API_KEY) -bb.sessions.debug() From 6389dcfa255f2dbccba21e213697f45130985f29 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Fri, 1 Nov 2024 23:44:54 +0000 Subject: [PATCH 05/10] feat: following migration guide --- migrating.md | 177 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 127 insertions(+), 50 deletions(-) diff --git a/migrating.md b/migrating.md index 23aa7b9..a44537a 100644 --- a/migrating.md +++ b/migrating.md @@ -1,9 +1,65 @@ -# Upgrade guide to v1.0 +# V1 Migration Guide -The Browserbase v1.0.0 Python SDK has been rewritten from the ground up and ships with a ton of new features and better support that we can't wait for you to try. Unfortunately, however, this means that the old SDKs will be deprecated and archived in favor of the new SDK. +The Browserbase v1 Python SDK has been rewritten from the ground up and ships with a ton of new features and better support that we can't wait for you to try. This guide is designed to help you maximize your experience with V1. We hope this guide is useful to you; if you have any questions don't hesitate to reach out to support@browserbase.com or [create a new issue](https://github.com/browserbase/sdk-python/issues/new). +## Major Changes + +V1 SDK is a complete rewrite of the old SDK. The new SDK is more flexible, easier to use, and has a more consistent API. It is also a lot more modular. The majority of the syntax changes are as follows: + +```python +# Old SDK +browserbase.list_sessions() + +# New SDK +bb.sessions.list() +``` + +### Creating a Session + +Similar to the above, the new way to create a session is to use the `create` method on the `sessions` object. However, the `CreateSessionOptions` object is now broken up into several params, saving you from having to import and instantiate a Pydantic object. For more on this, see [below](#create-session). + +## Deprecated Methods + +`load`, `load_url`, and `screenshot` are fully deprecated. You can use the following example instead that encapsulates the same functionality using Playwright. + +```python +from playwright.sync_api import Playwright, sync_playwright +from browserbase import Browserbase + +bb = Browserbase(api_key=BROWSERBASE_API_KEY) + +def run(playwright: Playwright) -> None: + # Create a session on Browserbase + session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) + + # Connect to the remote session + chromium = playwright.chromium + browser = chromium.connect_over_cdp(session.connect_url) + context = browser.contexts[0] + page = context.pages[0] + + # Execute Playwright actions on the remote browser tab + page.goto("https://news.ycombinator.com/") + page_title = page.title() + assert ( + page_title == "Hacker News" + ), f"Page title is not 'Hacker News', it is '{page_title}'" + page.screenshot(path="screenshot.png") + + page.close() + browser.close() + print("Done!") + + +if __name__ == "__main__": + with sync_playwright() as playwright: + run(playwright) +``` + +For async Playwright, you can import `async_playwright` instead. + ## Create Session ### Old SDK @@ -45,7 +101,7 @@ session = bb.sessions.create( ) ``` -## Get Connection Url +## Get Connect Url ### Old SDK @@ -67,9 +123,20 @@ connect_url = browserbase.get_connect_url(session_id=some_session.id) from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) -# We must create a session first -session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) -connect_url = session.connect_url +def get_connect_url(bb: Browserbase, session_id: str = None): + """ + Retrieve a connect url for a given session or create a new one. + + If a session id is provided, retrieve the connect url for the existing session. + Otherwise, create a new session and return the connect url. + """ + if session_id: + session = bb.sessions.retrieve(id=session_id) + else: + session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) + return session.connect_url + +connect_url = get_connect_url(bb, session_id="some_session_id") ``` ## List Sessions @@ -87,7 +154,14 @@ sessions = browserbase.list_sessions() ```python from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) -sessions = bb.sessions.list() + +def list_sessions(bb: Browserbase): + """ + List all sessions for the given project. + """ + return bb.sessions.list() + +sessions = list_sessions(bb) ``` ## Complete Session @@ -106,7 +180,14 @@ browserbase.complete_session(session_id=some_session.id) ```python from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) -bb.sessions.update(id=some_session.id, status="REQUEST_RELEASE") + +def complete_session(bb: Browserbase, session_id: str): + """ + Complete a session by updating its status to REQUEST_RELEASE. + """ + bb.sessions.update(id=session_id, status="REQUEST_RELEASE") + +complete_session(bb, session_id="some_session_id") ``` ## Get Session @@ -116,7 +197,7 @@ bb.sessions.update(id=some_session.id, status="REQUEST_RELEASE") ```python from browserbase import Browserbase browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) -session = browserbase.get_session(session_id=some_session.id) +session = browserbase.get_session(session_id="some_session_id") ``` ### New SDK @@ -124,7 +205,14 @@ session = browserbase.get_session(session_id=some_session.id) ```python from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) -session = bb.sessions.retrieve(id=some_session.id) + +def get_session(bb: Browserbase, session_id: str): + """ + Retrieve a session by id. + """ + return bb.sessions.retrieve(id=session_id) + +session = get_session(bb, session_id="some_session_id") ``` ## Get Session Recording @@ -142,7 +230,13 @@ recording = browserbase.get_session_recording(session_id=some_session.id) ```python from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) -recording = bb.sessions.recording.retrieve(id=some_session.id) +def get_session_recording(bb: Browserbase, session_id: str): + """ + Retrieve a session recording by id. + """ + return bb.sessions.recording.retrieve(id=session_id) + +recording = get_session_recording(bb, session_id="some_session_id") ``` ## Get Session Downloads @@ -165,7 +259,14 @@ downloads = browserbase.get_session_downloads(session_id=some_session.id) ```python from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) -downloads = bb.sessions.downloads.list(id=some_session.id) + +def get_session_downloads(bb: Browserbase, session_id: str): + """ + Retrieve a session's downloads by id. + """ + return bb.sessions.downloads.list(id=session_id) + +downloads = get_session_downloads(bb, session_id="some_session_id") ``` ## Get Debug Connection URLs @@ -183,7 +284,14 @@ debug_urls = browserbase.get_debug_connection_urls(session_id=some_session.id) ```python from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) -debug_urls = bb.sessions.debug(id=some_session.id) + +def get_debug_connection_urls(bb: Browserbase, session_id: str): + """ + Retrieve a session's debug connection urls by id. + """ + return bb.sessions.debug(id=session_id) + +debug_urls = get_debug_connection_urls(bb, session_id="some_session_id") ``` ## Get Session Logs @@ -201,43 +309,12 @@ logs = browserbase.get_session_logs(session_id=some_session.id) ```python from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) -logs = bb.sessions.logs.list(id=some_session.id) -``` - -# Deprecated Methods - -`load`, `load_url`, and `screenshot` are fully deprecated. You can use the following example instead that encapsulates the same functionality using Playwright - -```python -from playwright.sync_api import Playwright, sync_playwright -from browserbase import Browserbase - -bb = Browserbase(api_key=BROWSERBASE_API_KEY) - -def run(playwright: Playwright) -> None: - # Create a session on Browserbase - session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) - # Connect to the remote session - chromium = playwright.chromium - browser = chromium.connect_over_cdp(session.connect_url) - context = browser.contexts[0] - page = context.pages[0] +def get_session_logs(bb: Browserbase, session_id: str): + """ + Retrieve a session's logs by id. + """ + return bb.sessions.logs.list(id=session_id) - # Execute Playwright actions on the remote browser tab - page.goto("https://news.ycombinator.com/") - page_title = page.title() - assert ( - page_title == "Hacker News" - ), f"Page title is not 'Hacker News', it is '{page_title}'" - page.screenshot(path="screenshot.png") - - page.close() - browser.close() - print("Done!") - - -if __name__ == "__main__": - with sync_playwright() as playwright: - run(playwright) +logs = get_session_logs(bb, session_id="some_session_id") ``` From c04f506802c8b4995883433e41e52b6f6a3cc4e6 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Fri, 1 Nov 2024 23:44:55 +0000 Subject: [PATCH 06/10] feat: comment --- migrating.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/migrating.md b/migrating.md index a44537a..2726572 100644 --- a/migrating.md +++ b/migrating.md @@ -4,6 +4,8 @@ The Browserbase v1 Python SDK has been rewritten from the ground up and ships wi We hope this guide is useful to you; if you have any questions don't hesitate to reach out to support@browserbase.com or [create a new issue](https://github.com/browserbase/sdk-python/issues/new). +We've also rewritten our old SDK functionalities to use the new SDK with analogous function signatures below. + ## Major Changes V1 SDK is a complete rewrite of the old SDK. The new SDK is more flexible, easier to use, and has a more consistent API. It is also a lot more modular. The majority of the syntax changes are as follows: From 9ffd582fa4b869dbfdd91154eb17c0cbe7aa7120 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Fri, 1 Nov 2024 23:44:55 +0000 Subject: [PATCH 07/10] feat: uppacase --- migrating.md => MIGRATION.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename migrating.md => MIGRATION.md (100%) diff --git a/migrating.md b/MIGRATION.md similarity index 100% rename from migrating.md rename to MIGRATION.md From 27c1113c47fdca5306d3d87c924d24ab66e8ab78 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Fri, 1 Nov 2024 23:44:56 +0000 Subject: [PATCH 08/10] feat: syntax --- MIGRATION.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 2726572..b62b9ea 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -82,9 +82,10 @@ Function signature: `def create_session(self, options: Optional[CreateSessionOpt ```python from browserbase import Browserbase +from pydantic import TypeAdapter bb = Browserbase(api_key=BROWSERBASE_API_KEY) -session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) +session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID, extension_id="some_extension_id") ``` For more complex session creation, you can import `BrowserSettings` and use Pydantic's `TypeAdapter` to conform JSON spec to the appropriate Pydantic class. You can also import each individual subclass, but this may be rather tedious. @@ -96,7 +97,7 @@ from browserbase.types.session_create_params import BrowserSettings session = bb.sessions.create( project_id=BROWSERBASE_PROJECT_ID, - extension_id="some_extension_id" + extension_id="some_extension_id", browser_settings=TypeAdapter(BrowserSettings).validate_python( {"context": {"id": context_id, "persist": True}} ), From 09923239bf5206adc9d119f89bad9608681a5d30 Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Fri, 1 Nov 2024 23:44:56 +0000 Subject: [PATCH 09/10] feat: migration guide final --- MIGRATION.md | 218 ++++++++++++++++----------------------------------- 1 file changed, 68 insertions(+), 150 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index b62b9ea..4b49205 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,30 +1,26 @@ -# V1 Migration Guide +# Migration Guide -The Browserbase v1 Python SDK has been rewritten from the ground up and ships with a ton of new features and better support that we can't wait for you to try. This guide is designed to help you maximize your experience with V1. +The Browserbase v1 Python SDK has been rewritten from the ground up and ships with a ton of new features and better support that we can't wait for you to try. This guide is designed to help you maximize your experience with v1. We hope this guide is useful to you; if you have any questions don't hesitate to reach out to support@browserbase.com or [create a new issue](https://github.com/browserbase/sdk-python/issues/new). -We've also rewritten our old SDK functionalities to use the new SDK with analogous function signatures below. +We've written out specific guidelines on how to migrate each v0 method to v1 below. v1 also adds one-to-one mappings for every API endpoint, so you can incorporate new Browserbase features in your codebase with much less lift. -## Major Changes +## Breaking Changes -V1 SDK is a complete rewrite of the old SDK. The new SDK is more flexible, easier to use, and has a more consistent API. It is also a lot more modular. The majority of the syntax changes are as follows: +The v1 SDK is more flexible, easier to use, and has a more consistent API. It is also a lot more modular, meaning the majority of function calls have changed from `browserbase.$thing_$do()` to `browserbase.$thing.$do()`. For example: ```python -# Old SDK +# v0 SDK browserbase.list_sessions() -# New SDK +# v1 SDK bb.sessions.list() ``` -### Creating a Session +### Deleted Methods -Similar to the above, the new way to create a session is to use the `create` method on the `sessions` object. However, the `CreateSessionOptions` object is now broken up into several params, saving you from having to import and instantiate a Pydantic object. For more on this, see [below](#create-session). - -## Deprecated Methods - -`load`, `load_url`, and `screenshot` are fully deprecated. You can use the following example instead that encapsulates the same functionality using Playwright. +`load`, `load_url`, and `screenshot` have been fully removed in the v1 SDK. You can use the following example instead that encapsulates the same functionality using Playwright. ```python from playwright.sync_api import Playwright, sync_playwright @@ -52,7 +48,7 @@ def run(playwright: Playwright) -> None: page.close() browser.close() - print("Done!") + print(f"Done! View replay at https://browserbase.com/sessions/{session.id}") if __name__ == "__main__": @@ -60,13 +56,16 @@ if __name__ == "__main__": run(playwright) ``` -For async Playwright, you can import `async_playwright` instead. +For async Playwright (like in Jupyter notebooks or IPython environments), you can import `async_playwright` instead of `sync_playwright`. + +## Updates to Common Workflows -## Create Session +### Create Session -### Old SDK +This is how you would create a session with the v0 SDK, where `CreateSessionOptions` is a Pydantic object defined [here](https://github.com/browserbase/python-sdk/blob/0a499ba29853f20bb3055d7c81c5f61c24fcd9ec/browserbase/__init__.py#L52). ```python +# v0 SDK from browserbase import Browserbase, CreateSessionOptions browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) @@ -74,23 +73,20 @@ options = CreateSessionOptions(extensionId='123') browserbase.create_session(options) ``` -Function signature: `def create_session(self, options: Optional[CreateSessionOptions] = None)` - -`CreateSessionOptions` is a Pydantic object defined [here](https://github.com/browserbase/python-sdk/blob/0a499ba29853f20bb3055d7c81c5f61c24fcd9ec/browserbase/__init__.py#L52) in the old SDK. - -### New SDK +Now, you can create a session with the v1 SDK by calling the `create` method on `sessions`. ```python +# v1 SDK from browserbase import Browserbase -from pydantic import TypeAdapter bb = Browserbase(api_key=BROWSERBASE_API_KEY) session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID, extension_id="some_extension_id") ``` -For more complex session creation, you can import `BrowserSettings` and use Pydantic's `TypeAdapter` to conform JSON spec to the appropriate Pydantic class. You can also import each individual subclass, but this may be rather tedious. +For more complex session creation, you can import `BrowserSettings` and use Pydantic's `TypeAdapter` to conform JSON spec to the appropriate Pydantic class. You can also import each individual subclass. ```python +# v1 SDK from browserbase import Browserbase from pydantic import TypeAdapter from browserbase.types.session_create_params import BrowserSettings @@ -104,11 +100,14 @@ session = bb.sessions.create( ) ``` -## Get Connect Url +### Get Connect URL -### Old SDK +In the v0 SDK, you could run `browserbase.get_connect_url()` to create a new session and retrieve its connect url, or `browserbase.get_connect_url(session_id=some_session.id)` to retrieve the connect url for an existing session. + +In the v1 SDK, you can create a session and retrieve its connect url in a single call with `bb.sessions.create()`. ```python +# v0 SDK from browserbase import Browserbase browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) @@ -116,13 +115,12 @@ browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PR # To create a new session and connect to it connect_url = browserbase.get_connect_url() -# To connect to a created session +# To connect to an existing session connect_url = browserbase.get_connect_url(session_id=some_session.id) ``` -### New SDK - ```python +# v1 SDK from browserbase import Browserbase bb = Browserbase(api_key=BROWSERBASE_API_KEY) @@ -142,182 +140,102 @@ def get_connect_url(bb: Browserbase, session_id: str = None): connect_url = get_connect_url(bb, session_id="some_session_id") ``` -## List Sessions +### Complete Session -### Old SDK +v0 allowed you to complete a session by calling `browserbase.complete_session(session_id=some_session.id)`. ```python -from browserbase import Browserbase -browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) -sessions = browserbase.list_sessions() +# v0 SDK +browserbase.complete_session(session_id=some_session.id) ``` -### New SDK +In the v1 SDK, completing a session is done by updating its status to `REQUEST_RELEASE`. ```python -from browserbase import Browserbase -bb = Browserbase(api_key=BROWSERBASE_API_KEY) - -def list_sessions(bb: Browserbase): - """ - List all sessions for the given project. - """ - return bb.sessions.list() - -sessions = list_sessions(bb) +# v1 SDK +bb.sessions.update(id=session_id, status="REQUEST_RELEASE") ``` -## Complete Session +## Reference for other methods -### Old SDK +These methods have been rewritten for modularity and flexibility. As mentioned above, the pattern here is that the method has been renamed from `browserbase.$thing_$do()` to `bb.$thing.$do()`. -```python -from browserbase import Browserbase +### List Sessions -browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) -browserbase.complete_session(session_id=some_session.id) +```python +# v0 SDK +sessions = browserbase.list_sessions() ``` -### New SDK - ```python -from browserbase import Browserbase -bb = Browserbase(api_key=BROWSERBASE_API_KEY) - -def complete_session(bb: Browserbase, session_id: str): - """ - Complete a session by updating its status to REQUEST_RELEASE. - """ - bb.sessions.update(id=session_id, status="REQUEST_RELEASE") - -complete_session(bb, session_id="some_session_id") +# v1 SDK +sessions = bb.sessions.list() ``` -## Get Session - -### Old SDK +### Get Session ```python -from browserbase import Browserbase -browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +# v0 SDK session = browserbase.get_session(session_id="some_session_id") ``` -### New SDK - ```python -from browserbase import Browserbase -bb = Browserbase(api_key=BROWSERBASE_API_KEY) - -def get_session(bb: Browserbase, session_id: str): - """ - Retrieve a session by id. - """ - return bb.sessions.retrieve(id=session_id) - -session = get_session(bb, session_id="some_session_id") +# v1 SDK +session = bb.sessions.retrieve(id="some_session_id") ``` -## Get Session Recording - -### Old SDK +### Get Session Recording ```python -from browserbase import Browserbase -browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +# v0 SDK recording = browserbase.get_session_recording(session_id=some_session.id) ``` -### New SDK - ```python -from browserbase import Browserbase -bb = Browserbase(api_key=BROWSERBASE_API_KEY) -def get_session_recording(bb: Browserbase, session_id: str): - """ - Retrieve a session recording by id. - """ - return bb.sessions.recording.retrieve(id=session_id) - -recording = get_session_recording(bb, session_id="some_session_id") +# v1 SDK +recording = bb.sessions.recording.retrieve(id="some_session_id") ``` -## Get Session Downloads +### Get Session Downloads -### Old SDK - -> [!NOTE] -> The parameter `retry_interval` is no longer supported. You can configure retries with the following syntax on bb init: -> -> `bb = Browserbase(api_key=BROWSERBASE_API_KEY, max_retries=5)` +**Note:** The parameter `retry_interval` is no longer supported. You can configure retries with the following syntax on bb init: ```python -from browserbase import Browserbase -browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) -downloads = browserbase.get_session_downloads(session_id=some_session.id) +bb = Browserbase(api_key=BROWSERBASE_API_KEY, max_retries=5) ``` -### New SDK +Keep in mind, however, that this only affects the default retry behavior, which will only retry on 4xx/5xx errors. The remaining pattern still applies: ```python -from browserbase import Browserbase -bb = Browserbase(api_key=BROWSERBASE_API_KEY) - -def get_session_downloads(bb: Browserbase, session_id: str): - """ - Retrieve a session's downloads by id. - """ - return bb.sessions.downloads.list(id=session_id) - -downloads = get_session_downloads(bb, session_id="some_session_id") +# v0 SDK +downloads = browserbase.get_session_downloads(session_id=some_session.id) ``` -## Get Debug Connection URLs +```python +# v1 SDK +downloads = bb.sessions.downloads.retrieve(id="some_session_id") +``` -### Old SDK +### Get Debug Connection URLs ```python -from browserbase import Browserbase -browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +# v0 SDK debug_urls = browserbase.get_debug_connection_urls(session_id=some_session.id) ``` -### New SDK - ```python -from browserbase import Browserbase -bb = Browserbase(api_key=BROWSERBASE_API_KEY) - -def get_debug_connection_urls(bb: Browserbase, session_id: str): - """ - Retrieve a session's debug connection urls by id. - """ - return bb.sessions.debug(id=session_id) - -debug_urls = get_debug_connection_urls(bb, session_id="some_session_id") +# v1 SDK +debug_urls = bb.sessions.debug.list(id="some_session_id") ``` -## Get Session Logs - -### Old SDK +### Get Session Logs ```python -from browserbase import Browserbase -browserbase = Browserbase(api_key=BROWSERBASE_API_KEY, project_id=BROWSERBASE_PROJECT_ID) +# v0 SDK logs = browserbase.get_session_logs(session_id=some_session.id) ``` -### New SDK - ```python -from browserbase import Browserbase -bb = Browserbase(api_key=BROWSERBASE_API_KEY) - -def get_session_logs(bb: Browserbase, session_id: str): - """ - Retrieve a session's logs by id. - """ - return bb.sessions.logs.list(id=session_id) - -logs = get_session_logs(bb, session_id="some_session_id") +# v1 SDK +logs = bb.sessions.logs.list(id="some_session_id") ``` From 512cc8a56802f3f9181e56288788e74c2375ec1a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 23:45:18 +0000 Subject: [PATCH 10/10] release: 1.1.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 16 ++++++++++++++++ pyproject.toml | 2 +- src/browserbase/_version.py | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fea3454..2601677 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.0.0" + ".": "1.1.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a17bbc5..1ff2dce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 1.1.0 (2024-11-01) + +Full Changelog: [v1.0.0...v1.1.0](https://github.com/browserbase/sdk-python/compare/v1.0.0...v1.1.0) + +### Features + +* **api:** api update ([#48](https://github.com/browserbase/sdk-python/issues/48)) ([645e897](https://github.com/browserbase/sdk-python/commit/645e897348d54bef40cb2d9470838da6617cfb34)) +* comment ([c04f506](https://github.com/browserbase/sdk-python/commit/c04f506802c8b4995883433e41e52b6f6a3cc4e6)) +* following migration guide ([6389dcf](https://github.com/browserbase/sdk-python/commit/6389dcfa255f2dbccba21e213697f45130985f29)) +* migrating docs ([f5c9093](https://github.com/browserbase/sdk-python/commit/f5c90937330f2acfe4c6a97983136f3f482c7d39)) +* migration guide final ([0992323](https://github.com/browserbase/sdk-python/commit/09923239bf5206adc9d119f89bad9608681a5d30)) +* rm scratch ([bc333a4](https://github.com/browserbase/sdk-python/commit/bc333a4d9ab906e73bfbdd145bb6698ce9842318)) +* syntax ([27c1113](https://github.com/browserbase/sdk-python/commit/27c1113c47fdca5306d3d87c924d24ab66e8ab78)) +* undo playwright_roxy ([2530a9c](https://github.com/browserbase/sdk-python/commit/2530a9c6aa9c8aa29b180a7a5a912251dca4b2d9)) +* uppacase ([9ffd582](https://github.com/browserbase/sdk-python/commit/9ffd582fa4b869dbfdd91154eb17c0cbe7aa7120)) + ## 1.0.0 (2024-10-29) Full Changelog: [v1.0.0-alpha.0...v1.0.0](https://github.com/browserbase/sdk-python/compare/v1.0.0-alpha.0...v1.0.0) diff --git a/pyproject.toml b/pyproject.toml index 9cdf351..ec42980 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "browserbase" -version = "1.0.0" +version = "1.1.0" description = "The official Python library for the Browserbase API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/browserbase/_version.py b/src/browserbase/_version.py index 1f27c64..9621169 100644 --- a/src/browserbase/_version.py +++ b/src/browserbase/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "browserbase" -__version__ = "1.0.0" # x-release-please-version +__version__ = "1.1.0" # x-release-please-version