From a7bdc57ab7f327da61121986ba7b006238d0e5b5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 04:10:46 +0000 Subject: [PATCH 01/15] chore: make the `Omit` type public (#78) --- src/browserbase/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/browserbase/__init__.py b/src/browserbase/__init__.py index 4b1d280..ce50c4e 100644 --- a/src/browserbase/__init__.py +++ b/src/browserbase/__init__.py @@ -1,7 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from . import types -from ._types import NOT_GIVEN, NoneType, NotGiven, Transport, ProxiesTypes +from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes from ._utils import file_from_path from ._client import ( Client, @@ -46,6 +46,7 @@ "ProxiesTypes", "NotGiven", "NOT_GIVEN", + "Omit", "BrowserbaseError", "APIError", "APIStatusError", From e35a0d85ef0e45aed1a5f58757427bf7c16a76f5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 04:09:24 +0000 Subject: [PATCH 02/15] chore(internal): bump pydantic dependency (#81) --- requirements-dev.lock | 4 ++-- requirements.lock | 4 ++-- src/browserbase/_types.py | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 48e714f..b9e2216 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -81,9 +81,9 @@ playwright==1.48.0 # via pytest-playwright pluggy==1.5.0 # via pytest -pydantic==2.9.2 +pydantic==2.10.3 # via browserbase -pydantic-core==2.23.4 +pydantic-core==2.27.1 # via pydantic pyee==12.0.0 # via playwright diff --git a/requirements.lock b/requirements.lock index 4bff3dd..2f757eb 100644 --- a/requirements.lock +++ b/requirements.lock @@ -31,9 +31,9 @@ httpx==0.25.2 idna==3.4 # via anyio # via httpx -pydantic==2.9.2 +pydantic==2.10.3 # via browserbase -pydantic-core==2.23.4 +pydantic-core==2.27.1 # via pydantic sniffio==1.3.0 # via anyio diff --git a/src/browserbase/_types.py b/src/browserbase/_types.py index 1691090..a8833dc 100644 --- a/src/browserbase/_types.py +++ b/src/browserbase/_types.py @@ -192,10 +192,8 @@ def get(self, __key: str) -> str | None: ... StrBytesIntFloat = Union[str, bytes, int, float] # Note: copied from Pydantic -# https://github.com/pydantic/pydantic/blob/32ea570bf96e84234d2992e1ddf40ab8a565925a/pydantic/main.py#L49 -IncEx: TypeAlias = Union[ - Set[int], Set[str], Mapping[int, Union["IncEx", Literal[True]]], Mapping[str, Union["IncEx", Literal[True]]] -] +# https://github.com/pydantic/pydantic/blob/6f31f8f68ef011f84357330186f603ff295312fd/pydantic/main.py#L79 +IncEx: TypeAlias = Union[Set[int], Set[str], Mapping[int, Union["IncEx", bool]], Mapping[str, Union["IncEx", bool]]] PostParser = Callable[[Any], Any] From cc67c773b11b42b406b677f466c7c0ef090b254e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 04:14:19 +0000 Subject: [PATCH 03/15] docs(readme): fix http client proxies example (#82) --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1f1c0f9..7b4e202 100644 --- a/README.md +++ b/README.md @@ -290,18 +290,19 @@ can also get all the extra fields on the Pydantic model as a dict with You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including: -- Support for proxies -- Custom transports +- Support for [proxies](https://www.python-httpx.org/advanced/proxies/) +- Custom [transports](https://www.python-httpx.org/advanced/transports/) - Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality ```python +import httpx from browserbase import Browserbase, DefaultHttpxClient client = Browserbase( # Or use the `BROWSERBASE_BASE_URL` env var base_url="http://my.test.server.example.com:8083", http_client=DefaultHttpxClient( - proxies="http://my.test.proxy.example.com", + proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0"), ), ) From 894b4c45b0c36963822923535391aa34dbfec766 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:58:15 +0000 Subject: [PATCH 04/15] chore(internal): bump pyright (#83) --- README.md | 5 ++--- examples/e2e/test_playwright.py | 1 + examples/playwright_basic.py | 4 +--- examples/playwright_captcha.py | 4 +--- examples/playwright_contexts.py | 16 ++++----------- examples/playwright_extensions.py | 20 +++++-------------- examples/playwright_proxy.py | 4 +--- examples/playwright_upload.py | 8 ++------ examples/selenium_basic.py | 3 ++- requirements-dev.lock | 4 ++-- .../resources/sessions/sessions.py | 2 +- 11 files changed, 22 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 7b4e202..27f28c5 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ session = client.sessions.create( ) print(session.id) + def run(playwright: Playwright) -> None: # Connect to the remote session chromium = playwright.chromium @@ -51,9 +52,7 @@ def run(playwright: Playwright) -> None: # 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}'" + assert page_title == "Hacker News", f"Page title is not 'Hacker News', it is '{page_title}'" page.screenshot(path="screenshot.png") page.close() diff --git a/examples/e2e/test_playwright.py b/examples/e2e/test_playwright.py index 2e58c70..afd94f1 100644 --- a/examples/e2e/test_playwright.py +++ b/examples/e2e/test_playwright.py @@ -29,6 +29,7 @@ def playwright() -> Generator[Playwright, None, None]: with sync_playwright() as p: yield p + def test_playwright_basic(playwright: Playwright) -> None: playwright_basic.run(playwright) diff --git a/examples/playwright_basic.py b/examples/playwright_basic.py index 06fc93c..33bf88a 100644 --- a/examples/playwright_basic.py +++ b/examples/playwright_basic.py @@ -19,9 +19,7 @@ def run(playwright: Playwright) -> None: # 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}'" + assert page_title == "Hacker News", f"Page title is not 'Hacker News', it is '{page_title}'" page.screenshot(path="screenshot.png") page.close() diff --git a/examples/playwright_captcha.py b/examples/playwright_captcha.py index 7bc2ff4..980504f 100644 --- a/examples/playwright_captcha.py +++ b/examples/playwright_captcha.py @@ -34,9 +34,7 @@ def handle_console(msg: ConsoleMessage) -> None: page.on("console", handle_console) page.goto(DEFAULT_CAPTCHA_URL, wait_until="networkidle") - page.wait_for_function( - "() => window.captchaSolvingFinished === true", timeout=OVERRIDE_TIMEOUT - ) + page.wait_for_function("() => window.captchaSolvingFinished === true", timeout=OVERRIDE_TIMEOUT) assert captcha_solving_started, "Captcha solving did not start" assert captcha_solving_finished, "Captcha solving did not finish" diff --git a/examples/playwright_contexts.py b/examples/playwright_contexts.py index 610636f..acf4633 100644 --- a/examples/playwright_contexts.py +++ b/examples/playwright_contexts.py @@ -41,15 +41,11 @@ def run(playwright: Playwright) -> None: # Step 2: Creates a session with the context session = bb.sessions.create( project_id=BROWSERBASE_PROJECT_ID, - browser_settings=TypeAdapter(BrowserSettings).validate_python( - {"context": {"id": context_id, "persist": True}} - ), + browser_settings=TypeAdapter(BrowserSettings).validate_python({"context": {"id": context_id, "persist": True}}), ) print(session) - assert ( - session.context_id == context_id - ), f"Session context_id is {session.context_id}, expected {context_id}" + assert session.context_id == context_id, f"Session context_id is {session.context_id}, expected {context_id}" session_id = session.id # Step 3: Populates and persists the context @@ -90,13 +86,9 @@ def run(playwright: Playwright) -> None: # Step 4: Creates another session with the same context session = bb.sessions.create( project_id=BROWSERBASE_PROJECT_ID, - browser_settings=BrowserSettings( - context=BrowserSettingsContext(id=context_id, persist=True) - ), + browser_settings=BrowserSettings(context=BrowserSettingsContext(id=context_id, persist=True)), ) - assert ( - session.context_id == context_id - ), f"Session context_id is {session.context_id}, expected {context_id}" + assert session.context_id == context_id, f"Session context_id is {session.context_id}, expected {context_id}" session_id = session.id # Step 5: Uses context to find previous state diff --git a/examples/playwright_extensions.py b/examples/playwright_extensions.py index 7bdb942..6ef1f98 100644 --- a/examples/playwright_extensions.py +++ b/examples/playwright_extensions.py @@ -12,9 +12,7 @@ ) from browserbase.types import Extension, SessionCreateResponse -PATH_TO_EXTENSION = ( - Path.cwd() / "examples" / "packages" / "extensions" / "browserbase-test" -) +PATH_TO_EXTENSION = Path.cwd() / "examples" / "packages" / "extensions" / "browserbase-test" def zip_extension(path: Path = PATH_TO_EXTENSION, save_local: bool = False) -> BytesIO: @@ -23,9 +21,7 @@ def zip_extension(path: Path = PATH_TO_EXTENSION, save_local: bool = False) -> B Mark save_local=True to save the zip file to a local file. """ # Ensure we're looking at an extension - assert "manifest.json" in os.listdir( - path - ), "No manifest.json found in the extension folder." + assert "manifest.json" in os.listdir(path), "No manifest.json found in the extension folder." # Create a BytesIO object to hold the zip file in memory memory_zip = BytesIO() @@ -51,9 +47,7 @@ def zip_extension(path: Path = PATH_TO_EXTENSION, save_local: bool = False) -> B def create_extension() -> str: zip_data = zip_extension(save_local=True) - extension: Extension = bb.extensions.create( - file=("extension.zip", zip_data.getvalue()) - ) + extension: Extension = bb.extensions.create(file=("extension.zip", zip_data.getvalue())) return extension.id @@ -75,9 +69,7 @@ def check_for_message(page: Page, message: str) -> None: while time.time() - start < 10: if message in console_messages: break - assert ( - message in console_messages - ), f"Expected message not found in console logs. Messages: {console_messages}" + assert message in console_messages, f"Expected message not found in console logs. Messages: {console_messages}" def run(playwright: Playwright) -> None: @@ -141,9 +133,7 @@ def run(playwright: Playwright) -> None: project_id=BROWSERBASE_PROJECT_ID, extension_id=extension_id, ) - raise AssertionError( - "Expected to fail when creating session with deleted extension" - ) + raise AssertionError("Expected to fail when creating session with deleted extension") except Exception as e: print(f"Failed to create session with deleted extension as expected: {str(e)}") diff --git a/examples/playwright_proxy.py b/examples/playwright_proxy.py index 8378e29..47c706b 100644 --- a/examples/playwright_proxy.py +++ b/examples/playwright_proxy.py @@ -11,9 +11,7 @@ def check_proxy_bytes(session_id: str) -> None: - bb.sessions.update( - id=session_id, project_id=BROWSERBASE_PROJECT_ID, status="REQUEST_RELEASE" - ) + bb.sessions.update(id=session_id, project_id=BROWSERBASE_PROJECT_ID, status="REQUEST_RELEASE") time.sleep(GRACEFUL_SHUTDOWN_TIMEOUT / 1000) updated_session = bb.sessions.retrieve(id=session_id) assert ( diff --git a/examples/playwright_upload.py b/examples/playwright_upload.py index da1e32c..6bba6e0 100644 --- a/examples/playwright_upload.py +++ b/examples/playwright_upload.py @@ -33,12 +33,8 @@ def run(playwright: Playwright) -> None: file_size = int(file_size_span.inner_text()) # Assert the file name and size - assert ( - file_name == "logo.png" - ), f"Expected file name to be 'logo.png', but got '{file_name}'" - assert ( - file_size > 0 - ), f"Expected file size to be greater than 0, but got {file_size}" + assert file_name == "logo.png", f"Expected file name to be 'logo.png', but got '{file_name}'" + assert file_size > 0, f"Expected file size to be greater than 0, but got {file_size}" print("File upload test passed successfully!") diff --git a/examples/selenium_basic.py b/examples/selenium_basic.py index 83b7307..91c7c32 100644 --- a/examples/selenium_basic.py +++ b/examples/selenium_basic.py @@ -34,7 +34,8 @@ def run() -> None: session = bb.sessions.create(project_id=BROWSERBASE_PROJECT_ID) connection = BrowserbaseConnection(session.id, session.selenium_remote_url) driver = webdriver.Remote( - command_executor=connection, options=webdriver.ChromeOptions() # type: ignore + command_executor=connection, + options=webdriver.ChromeOptions(), # type: ignore ) # Print a bit of info about the browser we've connected to diff --git a/requirements-dev.lock b/requirements-dev.lock index b9e2216..3d52e74 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -4,7 +4,7 @@ # last locked with the following flags: # pre: false # features: [] -# all-features: false +# all-features: true # with-sources: false # generate-hashes: false # universal: false @@ -89,7 +89,7 @@ pyee==12.0.0 # via playwright pygments==2.18.0 # via rich -pyright==1.1.386 +pyright==1.1.390 pysocks==1.7.1 # via urllib3 pytest==8.3.3 diff --git a/src/browserbase/resources/sessions/sessions.py b/src/browserbase/resources/sessions/sessions.py index 45ef082..15d8e70 100644 --- a/src/browserbase/resources/sessions/sessions.py +++ b/src/browserbase/resources/sessions/sessions.py @@ -715,4 +715,4 @@ def recording(self) -> AsyncRecordingResourceWithStreamingResponse: @cached_property def uploads(self) -> AsyncUploadsResourceWithStreamingResponse: - return AsyncUploadsResourceWithStreamingResponse(self._sessions.uploads) \ No newline at end of file + return AsyncUploadsResourceWithStreamingResponse(self._sessions.uploads) From 64448c6e020aaeb4b39b7ec8f1b28a6b8f0c746a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 04:08:56 +0000 Subject: [PATCH 05/15] chore(internal): add support for TypeAliasType (#85) --- pyproject.toml | 2 +- src/browserbase/_models.py | 3 +++ src/browserbase/_response.py | 20 +++++++++---------- src/browserbase/_utils/__init__.py | 1 + src/browserbase/_utils/_typing.py | 31 +++++++++++++++++++++++++++++- tests/test_models.py | 18 ++++++++++++++++- tests/utils.py | 4 ++++ 7 files changed, 66 insertions(+), 13 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 82209c4..b3a79be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ authors = [ dependencies = [ "httpx>=0.23.0, <1", "pydantic>=1.9.0, <3", - "typing-extensions>=4.7, <5", + "typing-extensions>=4.10, <5", "anyio>=3.5.0, <5", "distro>=1.7.0, <2", "sniffio", diff --git a/src/browserbase/_models.py b/src/browserbase/_models.py index 6cb469e..7a547ce 100644 --- a/src/browserbase/_models.py +++ b/src/browserbase/_models.py @@ -46,6 +46,7 @@ strip_not_given, extract_type_arg, is_annotated_type, + is_type_alias_type, strip_annotated_type, ) from ._compat import ( @@ -428,6 +429,8 @@ def construct_type(*, value: object, type_: object) -> object: # we allow `object` as the input type because otherwise, passing things like # `Literal['value']` will be reported as a type error by type checkers type_ = cast("type[object]", type_) + if is_type_alias_type(type_): + type_ = type_.__value__ # type: ignore[unreachable] # unwrap `Annotated[T, ...]` -> `T` if is_annotated_type(type_): diff --git a/src/browserbase/_response.py b/src/browserbase/_response.py index 81ae082..1876805 100644 --- a/src/browserbase/_response.py +++ b/src/browserbase/_response.py @@ -25,7 +25,7 @@ import pydantic from ._types import NoneType -from ._utils import is_given, extract_type_arg, is_annotated_type, extract_type_var_from_base +from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type @@ -126,9 +126,15 @@ def __repr__(self) -> str: ) def _parse(self, *, to: type[_T] | None = None) -> R | _T: + cast_to = to if to is not None else self._cast_to + + # unwrap `TypeAlias('Name', T)` -> `T` + if is_type_alias_type(cast_to): + cast_to = cast_to.__value__ # type: ignore[unreachable] + # unwrap `Annotated[T, ...]` -> `T` - if to and is_annotated_type(to): - to = extract_type_arg(to, 0) + if cast_to and is_annotated_type(cast_to): + cast_to = extract_type_arg(cast_to, 0) if self._is_sse_stream: if to: @@ -164,18 +170,12 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: return cast( R, stream_cls( - cast_to=self._cast_to, + cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), ), ) - cast_to = to if to is not None else self._cast_to - - # unwrap `Annotated[T, ...]` -> `T` - if is_annotated_type(cast_to): - cast_to = extract_type_arg(cast_to, 0) - if cast_to is NoneType: return cast(R, None) diff --git a/src/browserbase/_utils/__init__.py b/src/browserbase/_utils/__init__.py index a7cff3c..d4fda26 100644 --- a/src/browserbase/_utils/__init__.py +++ b/src/browserbase/_utils/__init__.py @@ -39,6 +39,7 @@ is_iterable_type as is_iterable_type, is_required_type as is_required_type, is_annotated_type as is_annotated_type, + is_type_alias_type as is_type_alias_type, strip_annotated_type as strip_annotated_type, extract_type_var_from_base as extract_type_var_from_base, ) diff --git a/src/browserbase/_utils/_typing.py b/src/browserbase/_utils/_typing.py index c036991..278749b 100644 --- a/src/browserbase/_utils/_typing.py +++ b/src/browserbase/_utils/_typing.py @@ -1,8 +1,17 @@ from __future__ import annotations +import sys +import typing +import typing_extensions from typing import Any, TypeVar, Iterable, cast from collections import abc as _c_abc -from typing_extensions import Required, Annotated, get_args, get_origin +from typing_extensions import ( + TypeIs, + Required, + Annotated, + get_args, + get_origin, +) from .._types import InheritsGeneric from .._compat import is_union as _is_union @@ -36,6 +45,26 @@ def is_typevar(typ: type) -> bool: return type(typ) == TypeVar # type: ignore +_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,) +if sys.version_info >= (3, 12): + _TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType) + + +def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]: + """Return whether the provided argument is an instance of `TypeAliasType`. + + ```python + type Int = int + is_type_alias_type(Int) + # > True + Str = TypeAliasType("Str", str) + is_type_alias_type(Str) + # > True + ``` + """ + return isinstance(tp, _TYPE_ALIAS_TYPES) + + # Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]] def strip_annotated_type(typ: type) -> type: if is_required_type(typ) or is_annotated_type(typ): diff --git a/tests/test_models.py b/tests/test_models.py index 37671b0..0db453c 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,7 @@ import json from typing import Any, Dict, List, Union, Optional, cast from datetime import datetime, timezone -from typing_extensions import Literal, Annotated +from typing_extensions import Literal, Annotated, TypeAliasType import pytest import pydantic @@ -828,3 +828,19 @@ class B(BaseModel): # if the discriminator details object stays the same between invocations then # we hit the cache assert UnionType.__discriminator__ is discriminator + + +@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +def test_type_alias_type() -> None: + Alias = TypeAliasType("Alias", str) + + class Model(BaseModel): + alias: Alias + union: Union[int, Alias] + + m = construct_type(value={"alias": "foo", "union": "bar"}, type_=Model) + assert isinstance(m, Model) + assert isinstance(m.alias, str) + assert m.alias == "foo" + assert isinstance(m.union, str) + assert m.union == "bar" diff --git a/tests/utils.py b/tests/utils.py index ad9be37..ac183a7 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -16,6 +16,7 @@ is_union_type, extract_type_arg, is_annotated_type, + is_type_alias_type, ) from browserbase._compat import PYDANTIC_V2, field_outer_type, get_model_fields from browserbase._models import BaseModel @@ -51,6 +52,9 @@ def assert_matches_type( path: list[str], allow_none: bool = False, ) -> None: + if is_type_alias_type(type_): + type_ = type_.__value__ + # unwrap `Annotated[T, ...]` -> `T` if is_annotated_type(type_): type_ = extract_type_arg(type_, 0) From ab76578bdce5eba2410b09f497758fbf0e0d8cf0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:09:11 +0000 Subject: [PATCH 06/15] chore(internal): codegen related update (#86) --- src/browserbase/_client.py | 69 +++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/browserbase/_client.py b/src/browserbase/_client.py index b3ed32f..b845ea8 100644 --- a/src/browserbase/_client.py +++ b/src/browserbase/_client.py @@ -8,7 +8,7 @@ import httpx -from . import resources, _exceptions +from . import _exceptions from ._qs import Querystring from ._types import ( NOT_GIVEN, @@ -24,6 +24,7 @@ get_async_library, ) from ._version import __version__ +from .resources import contexts, projects, extensions from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import APIStatusError, BrowserbaseError from ._base_client import ( @@ -31,13 +32,13 @@ SyncAPIClient, AsyncAPIClient, ) +from .resources.sessions import sessions __all__ = [ "Timeout", "Transport", "ProxiesTypes", "RequestOptions", - "resources", "Browserbase", "AsyncBrowserbase", "Client", @@ -46,10 +47,10 @@ class Browserbase(SyncAPIClient): - contexts: resources.ContextsResource - extensions: resources.ExtensionsResource - projects: resources.ProjectsResource - sessions: resources.SessionsResource + contexts: contexts.ContextsResource + extensions: extensions.ExtensionsResource + projects: projects.ProjectsResource + sessions: sessions.SessionsResource with_raw_response: BrowserbaseWithRawResponse with_streaming_response: BrowserbaseWithStreamedResponse @@ -107,10 +108,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = resources.ContextsResource(self) - self.extensions = resources.ExtensionsResource(self) - self.projects = resources.ProjectsResource(self) - self.sessions = resources.SessionsResource(self) + self.contexts = contexts.ContextsResource(self) + self.extensions = extensions.ExtensionsResource(self) + self.projects = projects.ProjectsResource(self) + self.sessions = sessions.SessionsResource(self) self.with_raw_response = BrowserbaseWithRawResponse(self) self.with_streaming_response = BrowserbaseWithStreamedResponse(self) @@ -220,10 +221,10 @@ def _make_status_error( class AsyncBrowserbase(AsyncAPIClient): - contexts: resources.AsyncContextsResource - extensions: resources.AsyncExtensionsResource - projects: resources.AsyncProjectsResource - sessions: resources.AsyncSessionsResource + contexts: contexts.AsyncContextsResource + extensions: extensions.AsyncExtensionsResource + projects: projects.AsyncProjectsResource + sessions: sessions.AsyncSessionsResource with_raw_response: AsyncBrowserbaseWithRawResponse with_streaming_response: AsyncBrowserbaseWithStreamedResponse @@ -281,10 +282,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = resources.AsyncContextsResource(self) - self.extensions = resources.AsyncExtensionsResource(self) - self.projects = resources.AsyncProjectsResource(self) - self.sessions = resources.AsyncSessionsResource(self) + self.contexts = contexts.AsyncContextsResource(self) + self.extensions = extensions.AsyncExtensionsResource(self) + self.projects = projects.AsyncProjectsResource(self) + self.sessions = sessions.AsyncSessionsResource(self) self.with_raw_response = AsyncBrowserbaseWithRawResponse(self) self.with_streaming_response = AsyncBrowserbaseWithStreamedResponse(self) @@ -395,34 +396,34 @@ def _make_status_error( class BrowserbaseWithRawResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = resources.ContextsResourceWithRawResponse(client.contexts) - self.extensions = resources.ExtensionsResourceWithRawResponse(client.extensions) - self.projects = resources.ProjectsResourceWithRawResponse(client.projects) - self.sessions = resources.SessionsResourceWithRawResponse(client.sessions) + self.contexts = contexts.ContextsResourceWithRawResponse(client.contexts) + self.extensions = extensions.ExtensionsResourceWithRawResponse(client.extensions) + self.projects = projects.ProjectsResourceWithRawResponse(client.projects) + self.sessions = sessions.SessionsResourceWithRawResponse(client.sessions) class AsyncBrowserbaseWithRawResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = resources.AsyncContextsResourceWithRawResponse(client.contexts) - self.extensions = resources.AsyncExtensionsResourceWithRawResponse(client.extensions) - self.projects = resources.AsyncProjectsResourceWithRawResponse(client.projects) - self.sessions = resources.AsyncSessionsResourceWithRawResponse(client.sessions) + self.contexts = contexts.AsyncContextsResourceWithRawResponse(client.contexts) + self.extensions = extensions.AsyncExtensionsResourceWithRawResponse(client.extensions) + self.projects = projects.AsyncProjectsResourceWithRawResponse(client.projects) + self.sessions = sessions.AsyncSessionsResourceWithRawResponse(client.sessions) class BrowserbaseWithStreamedResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = resources.ContextsResourceWithStreamingResponse(client.contexts) - self.extensions = resources.ExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = resources.ProjectsResourceWithStreamingResponse(client.projects) - self.sessions = resources.SessionsResourceWithStreamingResponse(client.sessions) + self.contexts = contexts.ContextsResourceWithStreamingResponse(client.contexts) + self.extensions = extensions.ExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = projects.ProjectsResourceWithStreamingResponse(client.projects) + self.sessions = sessions.SessionsResourceWithStreamingResponse(client.sessions) class AsyncBrowserbaseWithStreamedResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = resources.AsyncContextsResourceWithStreamingResponse(client.contexts) - self.extensions = resources.AsyncExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = resources.AsyncProjectsResourceWithStreamingResponse(client.projects) - self.sessions = resources.AsyncSessionsResourceWithStreamingResponse(client.sessions) + self.contexts = contexts.AsyncContextsResourceWithStreamingResponse(client.contexts) + self.extensions = extensions.AsyncExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = projects.AsyncProjectsResourceWithStreamingResponse(client.projects) + self.sessions = sessions.AsyncSessionsResourceWithStreamingResponse(client.sessions) Client = Browserbase From f7f189ec317394f2fc532b8f95c3d15304298027 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:09:51 +0000 Subject: [PATCH 07/15] chore(internal): codegen related update (#87) --- src/browserbase/_client.py | 69 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/src/browserbase/_client.py b/src/browserbase/_client.py index b845ea8..b3ed32f 100644 --- a/src/browserbase/_client.py +++ b/src/browserbase/_client.py @@ -8,7 +8,7 @@ import httpx -from . import _exceptions +from . import resources, _exceptions from ._qs import Querystring from ._types import ( NOT_GIVEN, @@ -24,7 +24,6 @@ get_async_library, ) from ._version import __version__ -from .resources import contexts, projects, extensions from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import APIStatusError, BrowserbaseError from ._base_client import ( @@ -32,13 +31,13 @@ SyncAPIClient, AsyncAPIClient, ) -from .resources.sessions import sessions __all__ = [ "Timeout", "Transport", "ProxiesTypes", "RequestOptions", + "resources", "Browserbase", "AsyncBrowserbase", "Client", @@ -47,10 +46,10 @@ class Browserbase(SyncAPIClient): - contexts: contexts.ContextsResource - extensions: extensions.ExtensionsResource - projects: projects.ProjectsResource - sessions: sessions.SessionsResource + contexts: resources.ContextsResource + extensions: resources.ExtensionsResource + projects: resources.ProjectsResource + sessions: resources.SessionsResource with_raw_response: BrowserbaseWithRawResponse with_streaming_response: BrowserbaseWithStreamedResponse @@ -108,10 +107,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = contexts.ContextsResource(self) - self.extensions = extensions.ExtensionsResource(self) - self.projects = projects.ProjectsResource(self) - self.sessions = sessions.SessionsResource(self) + self.contexts = resources.ContextsResource(self) + self.extensions = resources.ExtensionsResource(self) + self.projects = resources.ProjectsResource(self) + self.sessions = resources.SessionsResource(self) self.with_raw_response = BrowserbaseWithRawResponse(self) self.with_streaming_response = BrowserbaseWithStreamedResponse(self) @@ -221,10 +220,10 @@ def _make_status_error( class AsyncBrowserbase(AsyncAPIClient): - contexts: contexts.AsyncContextsResource - extensions: extensions.AsyncExtensionsResource - projects: projects.AsyncProjectsResource - sessions: sessions.AsyncSessionsResource + contexts: resources.AsyncContextsResource + extensions: resources.AsyncExtensionsResource + projects: resources.AsyncProjectsResource + sessions: resources.AsyncSessionsResource with_raw_response: AsyncBrowserbaseWithRawResponse with_streaming_response: AsyncBrowserbaseWithStreamedResponse @@ -282,10 +281,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = contexts.AsyncContextsResource(self) - self.extensions = extensions.AsyncExtensionsResource(self) - self.projects = projects.AsyncProjectsResource(self) - self.sessions = sessions.AsyncSessionsResource(self) + self.contexts = resources.AsyncContextsResource(self) + self.extensions = resources.AsyncExtensionsResource(self) + self.projects = resources.AsyncProjectsResource(self) + self.sessions = resources.AsyncSessionsResource(self) self.with_raw_response = AsyncBrowserbaseWithRawResponse(self) self.with_streaming_response = AsyncBrowserbaseWithStreamedResponse(self) @@ -396,34 +395,34 @@ def _make_status_error( class BrowserbaseWithRawResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = contexts.ContextsResourceWithRawResponse(client.contexts) - self.extensions = extensions.ExtensionsResourceWithRawResponse(client.extensions) - self.projects = projects.ProjectsResourceWithRawResponse(client.projects) - self.sessions = sessions.SessionsResourceWithRawResponse(client.sessions) + self.contexts = resources.ContextsResourceWithRawResponse(client.contexts) + self.extensions = resources.ExtensionsResourceWithRawResponse(client.extensions) + self.projects = resources.ProjectsResourceWithRawResponse(client.projects) + self.sessions = resources.SessionsResourceWithRawResponse(client.sessions) class AsyncBrowserbaseWithRawResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = contexts.AsyncContextsResourceWithRawResponse(client.contexts) - self.extensions = extensions.AsyncExtensionsResourceWithRawResponse(client.extensions) - self.projects = projects.AsyncProjectsResourceWithRawResponse(client.projects) - self.sessions = sessions.AsyncSessionsResourceWithRawResponse(client.sessions) + self.contexts = resources.AsyncContextsResourceWithRawResponse(client.contexts) + self.extensions = resources.AsyncExtensionsResourceWithRawResponse(client.extensions) + self.projects = resources.AsyncProjectsResourceWithRawResponse(client.projects) + self.sessions = resources.AsyncSessionsResourceWithRawResponse(client.sessions) class BrowserbaseWithStreamedResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = contexts.ContextsResourceWithStreamingResponse(client.contexts) - self.extensions = extensions.ExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = projects.ProjectsResourceWithStreamingResponse(client.projects) - self.sessions = sessions.SessionsResourceWithStreamingResponse(client.sessions) + self.contexts = resources.ContextsResourceWithStreamingResponse(client.contexts) + self.extensions = resources.ExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = resources.ProjectsResourceWithStreamingResponse(client.projects) + self.sessions = resources.SessionsResourceWithStreamingResponse(client.sessions) class AsyncBrowserbaseWithStreamedResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = contexts.AsyncContextsResourceWithStreamingResponse(client.contexts) - self.extensions = extensions.AsyncExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = projects.AsyncProjectsResourceWithStreamingResponse(client.projects) - self.sessions = sessions.AsyncSessionsResourceWithStreamingResponse(client.sessions) + self.contexts = resources.AsyncContextsResourceWithStreamingResponse(client.contexts) + self.extensions = resources.AsyncExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = resources.AsyncProjectsResourceWithStreamingResponse(client.projects) + self.sessions = resources.AsyncSessionsResourceWithStreamingResponse(client.sessions) Client = Browserbase From 85f1492efc58d86ebc34511ca1269a0db2a4d223 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:22:12 +0000 Subject: [PATCH 08/15] chore(internal): codegen related update (#88) --- src/browserbase/_client.py | 69 +++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/browserbase/_client.py b/src/browserbase/_client.py index b3ed32f..b845ea8 100644 --- a/src/browserbase/_client.py +++ b/src/browserbase/_client.py @@ -8,7 +8,7 @@ import httpx -from . import resources, _exceptions +from . import _exceptions from ._qs import Querystring from ._types import ( NOT_GIVEN, @@ -24,6 +24,7 @@ get_async_library, ) from ._version import __version__ +from .resources import contexts, projects, extensions from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import APIStatusError, BrowserbaseError from ._base_client import ( @@ -31,13 +32,13 @@ SyncAPIClient, AsyncAPIClient, ) +from .resources.sessions import sessions __all__ = [ "Timeout", "Transport", "ProxiesTypes", "RequestOptions", - "resources", "Browserbase", "AsyncBrowserbase", "Client", @@ -46,10 +47,10 @@ class Browserbase(SyncAPIClient): - contexts: resources.ContextsResource - extensions: resources.ExtensionsResource - projects: resources.ProjectsResource - sessions: resources.SessionsResource + contexts: contexts.ContextsResource + extensions: extensions.ExtensionsResource + projects: projects.ProjectsResource + sessions: sessions.SessionsResource with_raw_response: BrowserbaseWithRawResponse with_streaming_response: BrowserbaseWithStreamedResponse @@ -107,10 +108,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = resources.ContextsResource(self) - self.extensions = resources.ExtensionsResource(self) - self.projects = resources.ProjectsResource(self) - self.sessions = resources.SessionsResource(self) + self.contexts = contexts.ContextsResource(self) + self.extensions = extensions.ExtensionsResource(self) + self.projects = projects.ProjectsResource(self) + self.sessions = sessions.SessionsResource(self) self.with_raw_response = BrowserbaseWithRawResponse(self) self.with_streaming_response = BrowserbaseWithStreamedResponse(self) @@ -220,10 +221,10 @@ def _make_status_error( class AsyncBrowserbase(AsyncAPIClient): - contexts: resources.AsyncContextsResource - extensions: resources.AsyncExtensionsResource - projects: resources.AsyncProjectsResource - sessions: resources.AsyncSessionsResource + contexts: contexts.AsyncContextsResource + extensions: extensions.AsyncExtensionsResource + projects: projects.AsyncProjectsResource + sessions: sessions.AsyncSessionsResource with_raw_response: AsyncBrowserbaseWithRawResponse with_streaming_response: AsyncBrowserbaseWithStreamedResponse @@ -281,10 +282,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = resources.AsyncContextsResource(self) - self.extensions = resources.AsyncExtensionsResource(self) - self.projects = resources.AsyncProjectsResource(self) - self.sessions = resources.AsyncSessionsResource(self) + self.contexts = contexts.AsyncContextsResource(self) + self.extensions = extensions.AsyncExtensionsResource(self) + self.projects = projects.AsyncProjectsResource(self) + self.sessions = sessions.AsyncSessionsResource(self) self.with_raw_response = AsyncBrowserbaseWithRawResponse(self) self.with_streaming_response = AsyncBrowserbaseWithStreamedResponse(self) @@ -395,34 +396,34 @@ def _make_status_error( class BrowserbaseWithRawResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = resources.ContextsResourceWithRawResponse(client.contexts) - self.extensions = resources.ExtensionsResourceWithRawResponse(client.extensions) - self.projects = resources.ProjectsResourceWithRawResponse(client.projects) - self.sessions = resources.SessionsResourceWithRawResponse(client.sessions) + self.contexts = contexts.ContextsResourceWithRawResponse(client.contexts) + self.extensions = extensions.ExtensionsResourceWithRawResponse(client.extensions) + self.projects = projects.ProjectsResourceWithRawResponse(client.projects) + self.sessions = sessions.SessionsResourceWithRawResponse(client.sessions) class AsyncBrowserbaseWithRawResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = resources.AsyncContextsResourceWithRawResponse(client.contexts) - self.extensions = resources.AsyncExtensionsResourceWithRawResponse(client.extensions) - self.projects = resources.AsyncProjectsResourceWithRawResponse(client.projects) - self.sessions = resources.AsyncSessionsResourceWithRawResponse(client.sessions) + self.contexts = contexts.AsyncContextsResourceWithRawResponse(client.contexts) + self.extensions = extensions.AsyncExtensionsResourceWithRawResponse(client.extensions) + self.projects = projects.AsyncProjectsResourceWithRawResponse(client.projects) + self.sessions = sessions.AsyncSessionsResourceWithRawResponse(client.sessions) class BrowserbaseWithStreamedResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = resources.ContextsResourceWithStreamingResponse(client.contexts) - self.extensions = resources.ExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = resources.ProjectsResourceWithStreamingResponse(client.projects) - self.sessions = resources.SessionsResourceWithStreamingResponse(client.sessions) + self.contexts = contexts.ContextsResourceWithStreamingResponse(client.contexts) + self.extensions = extensions.ExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = projects.ProjectsResourceWithStreamingResponse(client.projects) + self.sessions = sessions.SessionsResourceWithStreamingResponse(client.sessions) class AsyncBrowserbaseWithStreamedResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = resources.AsyncContextsResourceWithStreamingResponse(client.contexts) - self.extensions = resources.AsyncExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = resources.AsyncProjectsResourceWithStreamingResponse(client.projects) - self.sessions = resources.AsyncSessionsResourceWithStreamingResponse(client.sessions) + self.contexts = contexts.AsyncContextsResourceWithStreamingResponse(client.contexts) + self.extensions = extensions.AsyncExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = projects.AsyncProjectsResourceWithStreamingResponse(client.projects) + self.sessions = sessions.AsyncSessionsResourceWithStreamingResponse(client.sessions) Client = Browserbase From a82ae7d418b1daf68c85e70dea61e628eb785b79 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:22:50 +0000 Subject: [PATCH 09/15] chore(internal): remove some duplicated imports (#89) --- src/browserbase/_client.py | 69 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/src/browserbase/_client.py b/src/browserbase/_client.py index b845ea8..b3ed32f 100644 --- a/src/browserbase/_client.py +++ b/src/browserbase/_client.py @@ -8,7 +8,7 @@ import httpx -from . import _exceptions +from . import resources, _exceptions from ._qs import Querystring from ._types import ( NOT_GIVEN, @@ -24,7 +24,6 @@ get_async_library, ) from ._version import __version__ -from .resources import contexts, projects, extensions from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import APIStatusError, BrowserbaseError from ._base_client import ( @@ -32,13 +31,13 @@ SyncAPIClient, AsyncAPIClient, ) -from .resources.sessions import sessions __all__ = [ "Timeout", "Transport", "ProxiesTypes", "RequestOptions", + "resources", "Browserbase", "AsyncBrowserbase", "Client", @@ -47,10 +46,10 @@ class Browserbase(SyncAPIClient): - contexts: contexts.ContextsResource - extensions: extensions.ExtensionsResource - projects: projects.ProjectsResource - sessions: sessions.SessionsResource + contexts: resources.ContextsResource + extensions: resources.ExtensionsResource + projects: resources.ProjectsResource + sessions: resources.SessionsResource with_raw_response: BrowserbaseWithRawResponse with_streaming_response: BrowserbaseWithStreamedResponse @@ -108,10 +107,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = contexts.ContextsResource(self) - self.extensions = extensions.ExtensionsResource(self) - self.projects = projects.ProjectsResource(self) - self.sessions = sessions.SessionsResource(self) + self.contexts = resources.ContextsResource(self) + self.extensions = resources.ExtensionsResource(self) + self.projects = resources.ProjectsResource(self) + self.sessions = resources.SessionsResource(self) self.with_raw_response = BrowserbaseWithRawResponse(self) self.with_streaming_response = BrowserbaseWithStreamedResponse(self) @@ -221,10 +220,10 @@ def _make_status_error( class AsyncBrowserbase(AsyncAPIClient): - contexts: contexts.AsyncContextsResource - extensions: extensions.AsyncExtensionsResource - projects: projects.AsyncProjectsResource - sessions: sessions.AsyncSessionsResource + contexts: resources.AsyncContextsResource + extensions: resources.AsyncExtensionsResource + projects: resources.AsyncProjectsResource + sessions: resources.AsyncSessionsResource with_raw_response: AsyncBrowserbaseWithRawResponse with_streaming_response: AsyncBrowserbaseWithStreamedResponse @@ -282,10 +281,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = contexts.AsyncContextsResource(self) - self.extensions = extensions.AsyncExtensionsResource(self) - self.projects = projects.AsyncProjectsResource(self) - self.sessions = sessions.AsyncSessionsResource(self) + self.contexts = resources.AsyncContextsResource(self) + self.extensions = resources.AsyncExtensionsResource(self) + self.projects = resources.AsyncProjectsResource(self) + self.sessions = resources.AsyncSessionsResource(self) self.with_raw_response = AsyncBrowserbaseWithRawResponse(self) self.with_streaming_response = AsyncBrowserbaseWithStreamedResponse(self) @@ -396,34 +395,34 @@ def _make_status_error( class BrowserbaseWithRawResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = contexts.ContextsResourceWithRawResponse(client.contexts) - self.extensions = extensions.ExtensionsResourceWithRawResponse(client.extensions) - self.projects = projects.ProjectsResourceWithRawResponse(client.projects) - self.sessions = sessions.SessionsResourceWithRawResponse(client.sessions) + self.contexts = resources.ContextsResourceWithRawResponse(client.contexts) + self.extensions = resources.ExtensionsResourceWithRawResponse(client.extensions) + self.projects = resources.ProjectsResourceWithRawResponse(client.projects) + self.sessions = resources.SessionsResourceWithRawResponse(client.sessions) class AsyncBrowserbaseWithRawResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = contexts.AsyncContextsResourceWithRawResponse(client.contexts) - self.extensions = extensions.AsyncExtensionsResourceWithRawResponse(client.extensions) - self.projects = projects.AsyncProjectsResourceWithRawResponse(client.projects) - self.sessions = sessions.AsyncSessionsResourceWithRawResponse(client.sessions) + self.contexts = resources.AsyncContextsResourceWithRawResponse(client.contexts) + self.extensions = resources.AsyncExtensionsResourceWithRawResponse(client.extensions) + self.projects = resources.AsyncProjectsResourceWithRawResponse(client.projects) + self.sessions = resources.AsyncSessionsResourceWithRawResponse(client.sessions) class BrowserbaseWithStreamedResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = contexts.ContextsResourceWithStreamingResponse(client.contexts) - self.extensions = extensions.ExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = projects.ProjectsResourceWithStreamingResponse(client.projects) - self.sessions = sessions.SessionsResourceWithStreamingResponse(client.sessions) + self.contexts = resources.ContextsResourceWithStreamingResponse(client.contexts) + self.extensions = resources.ExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = resources.ProjectsResourceWithStreamingResponse(client.projects) + self.sessions = resources.SessionsResourceWithStreamingResponse(client.sessions) class AsyncBrowserbaseWithStreamedResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = contexts.AsyncContextsResourceWithStreamingResponse(client.contexts) - self.extensions = extensions.AsyncExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = projects.AsyncProjectsResourceWithStreamingResponse(client.projects) - self.sessions = sessions.AsyncSessionsResourceWithStreamingResponse(client.sessions) + self.contexts = resources.AsyncContextsResourceWithStreamingResponse(client.contexts) + self.extensions = resources.AsyncExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = resources.AsyncProjectsResourceWithStreamingResponse(client.projects) + self.sessions = resources.AsyncSessionsResourceWithStreamingResponse(client.sessions) Client = Browserbase From dc6e187bfe9585692b2de1b67fc83f027a52c43c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:23:31 +0000 Subject: [PATCH 10/15] chore(internal): updated imports (#90) --- src/browserbase/_client.py | 69 +++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/browserbase/_client.py b/src/browserbase/_client.py index b3ed32f..b845ea8 100644 --- a/src/browserbase/_client.py +++ b/src/browserbase/_client.py @@ -8,7 +8,7 @@ import httpx -from . import resources, _exceptions +from . import _exceptions from ._qs import Querystring from ._types import ( NOT_GIVEN, @@ -24,6 +24,7 @@ get_async_library, ) from ._version import __version__ +from .resources import contexts, projects, extensions from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import APIStatusError, BrowserbaseError from ._base_client import ( @@ -31,13 +32,13 @@ SyncAPIClient, AsyncAPIClient, ) +from .resources.sessions import sessions __all__ = [ "Timeout", "Transport", "ProxiesTypes", "RequestOptions", - "resources", "Browserbase", "AsyncBrowserbase", "Client", @@ -46,10 +47,10 @@ class Browserbase(SyncAPIClient): - contexts: resources.ContextsResource - extensions: resources.ExtensionsResource - projects: resources.ProjectsResource - sessions: resources.SessionsResource + contexts: contexts.ContextsResource + extensions: extensions.ExtensionsResource + projects: projects.ProjectsResource + sessions: sessions.SessionsResource with_raw_response: BrowserbaseWithRawResponse with_streaming_response: BrowserbaseWithStreamedResponse @@ -107,10 +108,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = resources.ContextsResource(self) - self.extensions = resources.ExtensionsResource(self) - self.projects = resources.ProjectsResource(self) - self.sessions = resources.SessionsResource(self) + self.contexts = contexts.ContextsResource(self) + self.extensions = extensions.ExtensionsResource(self) + self.projects = projects.ProjectsResource(self) + self.sessions = sessions.SessionsResource(self) self.with_raw_response = BrowserbaseWithRawResponse(self) self.with_streaming_response = BrowserbaseWithStreamedResponse(self) @@ -220,10 +221,10 @@ def _make_status_error( class AsyncBrowserbase(AsyncAPIClient): - contexts: resources.AsyncContextsResource - extensions: resources.AsyncExtensionsResource - projects: resources.AsyncProjectsResource - sessions: resources.AsyncSessionsResource + contexts: contexts.AsyncContextsResource + extensions: extensions.AsyncExtensionsResource + projects: projects.AsyncProjectsResource + sessions: sessions.AsyncSessionsResource with_raw_response: AsyncBrowserbaseWithRawResponse with_streaming_response: AsyncBrowserbaseWithStreamedResponse @@ -281,10 +282,10 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.contexts = resources.AsyncContextsResource(self) - self.extensions = resources.AsyncExtensionsResource(self) - self.projects = resources.AsyncProjectsResource(self) - self.sessions = resources.AsyncSessionsResource(self) + self.contexts = contexts.AsyncContextsResource(self) + self.extensions = extensions.AsyncExtensionsResource(self) + self.projects = projects.AsyncProjectsResource(self) + self.sessions = sessions.AsyncSessionsResource(self) self.with_raw_response = AsyncBrowserbaseWithRawResponse(self) self.with_streaming_response = AsyncBrowserbaseWithStreamedResponse(self) @@ -395,34 +396,34 @@ def _make_status_error( class BrowserbaseWithRawResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = resources.ContextsResourceWithRawResponse(client.contexts) - self.extensions = resources.ExtensionsResourceWithRawResponse(client.extensions) - self.projects = resources.ProjectsResourceWithRawResponse(client.projects) - self.sessions = resources.SessionsResourceWithRawResponse(client.sessions) + self.contexts = contexts.ContextsResourceWithRawResponse(client.contexts) + self.extensions = extensions.ExtensionsResourceWithRawResponse(client.extensions) + self.projects = projects.ProjectsResourceWithRawResponse(client.projects) + self.sessions = sessions.SessionsResourceWithRawResponse(client.sessions) class AsyncBrowserbaseWithRawResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = resources.AsyncContextsResourceWithRawResponse(client.contexts) - self.extensions = resources.AsyncExtensionsResourceWithRawResponse(client.extensions) - self.projects = resources.AsyncProjectsResourceWithRawResponse(client.projects) - self.sessions = resources.AsyncSessionsResourceWithRawResponse(client.sessions) + self.contexts = contexts.AsyncContextsResourceWithRawResponse(client.contexts) + self.extensions = extensions.AsyncExtensionsResourceWithRawResponse(client.extensions) + self.projects = projects.AsyncProjectsResourceWithRawResponse(client.projects) + self.sessions = sessions.AsyncSessionsResourceWithRawResponse(client.sessions) class BrowserbaseWithStreamedResponse: def __init__(self, client: Browserbase) -> None: - self.contexts = resources.ContextsResourceWithStreamingResponse(client.contexts) - self.extensions = resources.ExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = resources.ProjectsResourceWithStreamingResponse(client.projects) - self.sessions = resources.SessionsResourceWithStreamingResponse(client.sessions) + self.contexts = contexts.ContextsResourceWithStreamingResponse(client.contexts) + self.extensions = extensions.ExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = projects.ProjectsResourceWithStreamingResponse(client.projects) + self.sessions = sessions.SessionsResourceWithStreamingResponse(client.sessions) class AsyncBrowserbaseWithStreamedResponse: def __init__(self, client: AsyncBrowserbase) -> None: - self.contexts = resources.AsyncContextsResourceWithStreamingResponse(client.contexts) - self.extensions = resources.AsyncExtensionsResourceWithStreamingResponse(client.extensions) - self.projects = resources.AsyncProjectsResourceWithStreamingResponse(client.projects) - self.sessions = resources.AsyncSessionsResourceWithStreamingResponse(client.sessions) + self.contexts = contexts.AsyncContextsResourceWithStreamingResponse(client.contexts) + self.extensions = extensions.AsyncExtensionsResourceWithStreamingResponse(client.extensions) + self.projects = projects.AsyncProjectsResourceWithStreamingResponse(client.projects) + self.sessions = sessions.AsyncSessionsResourceWithStreamingResponse(client.sessions) Client = Browserbase From 950c8af19db4581fabd5b965ca4f0af3cc5cd6dc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 04:18:06 +0000 Subject: [PATCH 11/15] docs(readme): example snippet for client context manager (#91) --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 27f28c5..0aec43b 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,16 @@ client.with_options(http_client=DefaultHttpxClient(...)) By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting. +```py +from browserbase import Browserbase + +with Browserbase() as client: + # make requests here + ... + +# HTTP client is now closed +``` + ## Versioning This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: From 51d9f42a32d17d2d2277eb8a7b8f35a980c7c485 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 04:19:26 +0000 Subject: [PATCH 12/15] chore(internal): fix some typos (#92) --- tests/test_client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_client.py b/tests/test_client.py index aa0043e..776b48b 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -355,11 +355,11 @@ def test_default_query_option(self) -> None: FinalRequestOptions( method="get", url="/foo", - params={"foo": "baz", "query_param": "overriden"}, + params={"foo": "baz", "query_param": "overridden"}, ) ) url = httpx.URL(request.url) - assert dict(url.params) == {"foo": "baz", "query_param": "overriden"} + assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} def test_request_extra_json(self) -> None: request = self.client._build_request( @@ -1131,11 +1131,11 @@ def test_default_query_option(self) -> None: FinalRequestOptions( method="get", url="/foo", - params={"foo": "baz", "query_param": "overriden"}, + params={"foo": "baz", "query_param": "overridden"}, ) ) url = httpx.URL(request.url) - assert dict(url.params) == {"foo": "baz", "query_param": "overriden"} + assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} def test_request_extra_json(self) -> None: request = self.client._build_request( From 57f0977c8e050b85b2c2de91202f6775299f80bf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 04:25:19 +0000 Subject: [PATCH 13/15] chore(internal): codegen related update (#93) --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 915e6f8..2cec9d4 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2024 Browserbase + Copyright 2025 Browserbase Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From de5856dac77567813f681615bef7d147e505a6a0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 04:34:28 +0000 Subject: [PATCH 14/15] chore: add missing isclass check (#94) --- src/browserbase/_models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/browserbase/_models.py b/src/browserbase/_models.py index 7a547ce..d56ea1d 100644 --- a/src/browserbase/_models.py +++ b/src/browserbase/_models.py @@ -488,7 +488,11 @@ def construct_type(*, value: object, type_: object) -> object: _, items_type = get_args(type_) # Dict[_, items_type] return {key: construct_type(value=item, type_=items_type) for key, item in value.items()} - if not is_literal_type(type_) and (issubclass(origin, BaseModel) or issubclass(origin, GenericModel)): + if ( + not is_literal_type(type_) + and inspect.isclass(origin) + and (issubclass(origin, BaseModel) or issubclass(origin, GenericModel)) + ): if is_list(value): return [cast(Any, type_).construct(**entry) if is_mapping(entry) else entry for entry in value] From 8748221bdcb083ebe933987a7e62bfd03cc56b52 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 04:34:47 +0000 Subject: [PATCH 15/15] release: 1.0.6 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 25 +++++++++++++++++++++++++ pyproject.toml | 2 +- src/browserbase/_version.py | 2 +- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1214610..15c8c05 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.0.5" + ".": "1.0.6" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bb2966..2724bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## 1.0.6 (2025-01-07) + +Full Changelog: [v1.0.5...v1.0.6](https://github.com/browserbase/sdk-python/compare/v1.0.5...v1.0.6) + +### Chores + +* add missing isclass check ([#94](https://github.com/browserbase/sdk-python/issues/94)) ([de5856d](https://github.com/browserbase/sdk-python/commit/de5856dac77567813f681615bef7d147e505a6a0)) +* **internal:** add support for TypeAliasType ([#85](https://github.com/browserbase/sdk-python/issues/85)) ([64448c6](https://github.com/browserbase/sdk-python/commit/64448c6e020aaeb4b39b7ec8f1b28a6b8f0c746a)) +* **internal:** bump pydantic dependency ([#81](https://github.com/browserbase/sdk-python/issues/81)) ([e35a0d8](https://github.com/browserbase/sdk-python/commit/e35a0d85ef0e45aed1a5f58757427bf7c16a76f5)) +* **internal:** bump pyright ([#83](https://github.com/browserbase/sdk-python/issues/83)) ([894b4c4](https://github.com/browserbase/sdk-python/commit/894b4c45b0c36963822923535391aa34dbfec766)) +* **internal:** codegen related update ([#86](https://github.com/browserbase/sdk-python/issues/86)) ([ab76578](https://github.com/browserbase/sdk-python/commit/ab76578bdce5eba2410b09f497758fbf0e0d8cf0)) +* **internal:** codegen related update ([#87](https://github.com/browserbase/sdk-python/issues/87)) ([f7f189e](https://github.com/browserbase/sdk-python/commit/f7f189ec317394f2fc532b8f95c3d15304298027)) +* **internal:** codegen related update ([#88](https://github.com/browserbase/sdk-python/issues/88)) ([85f1492](https://github.com/browserbase/sdk-python/commit/85f1492efc58d86ebc34511ca1269a0db2a4d223)) +* **internal:** codegen related update ([#93](https://github.com/browserbase/sdk-python/issues/93)) ([57f0977](https://github.com/browserbase/sdk-python/commit/57f0977c8e050b85b2c2de91202f6775299f80bf)) +* **internal:** fix some typos ([#92](https://github.com/browserbase/sdk-python/issues/92)) ([51d9f42](https://github.com/browserbase/sdk-python/commit/51d9f42a32d17d2d2277eb8a7b8f35a980c7c485)) +* **internal:** remove some duplicated imports ([#89](https://github.com/browserbase/sdk-python/issues/89)) ([a82ae7d](https://github.com/browserbase/sdk-python/commit/a82ae7d418b1daf68c85e70dea61e628eb785b79)) +* **internal:** updated imports ([#90](https://github.com/browserbase/sdk-python/issues/90)) ([dc6e187](https://github.com/browserbase/sdk-python/commit/dc6e187bfe9585692b2de1b67fc83f027a52c43c)) +* make the `Omit` type public ([#78](https://github.com/browserbase/sdk-python/issues/78)) ([a7bdc57](https://github.com/browserbase/sdk-python/commit/a7bdc57ab7f327da61121986ba7b006238d0e5b5)) + + +### Documentation + +* **readme:** example snippet for client context manager ([#91](https://github.com/browserbase/sdk-python/issues/91)) ([950c8af](https://github.com/browserbase/sdk-python/commit/950c8af19db4581fabd5b965ca4f0af3cc5cd6dc)) +* **readme:** fix http client proxies example ([#82](https://github.com/browserbase/sdk-python/issues/82)) ([cc67c77](https://github.com/browserbase/sdk-python/commit/cc67c773b11b42b406b677f466c7c0ef090b254e)) + ## 1.0.5 (2024-12-03) Full Changelog: [v1.0.4...v1.0.5](https://github.com/browserbase/sdk-python/compare/v1.0.4...v1.0.5) diff --git a/pyproject.toml b/pyproject.toml index b3a79be..a904e67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "browserbase" -version = "1.0.5" +version = "1.0.6" 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 c871d01..e824c8e 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.5" # x-release-please-version +__version__ = "1.0.6" # x-release-please-version