diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 051a17f..7e8b7f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 with: - version: '0.9.13' + version: '0.10.2' - name: Install dependencies run: uv sync --all-extras @@ -46,7 +46,7 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 with: - version: '0.9.13' + version: '0.10.2' - name: Install dependencies run: uv sync --all-extras @@ -55,14 +55,18 @@ jobs: run: uv build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/tabstack-python' + if: |- + github.repository == 'stainless-sdks/tabstack-python' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball - if: github.repository == 'stainless-sdks/tabstack-python' + if: |- + github.repository == 'stainless-sdks/tabstack-python' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} @@ -80,7 +84,7 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 with: - version: '0.9.13' + version: '0.10.2' - name: Bootstrap run: ./scripts/bootstrap diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bfc26f9..75ec52f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.2.0" + ".": "2.3.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index ae3546f..62b5e49 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 5 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla%2Ftabstack-48ec35c63b70165a6c25cc2a32f486f4a920e40d209b0a1611b23f6f2f5a7936.yml -openapi_spec_hash: 0ec2a57c0562d4dc260dd67a141db240 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla%2Ftabstack-8f80078ef30bc395d44843f9ce076188ba43a297e158d5f3672c45dc814ffcf0.yml +openapi_spec_hash: c615a817dcb27c55bd15b9b9346669c2 config_hash: 6b388b673b2a48895ab10da245fb6771 diff --git a/CHANGELOG.md b/CHANGELOG.md index 857f17c..55679a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 2.3.0 (2026-03-12) + +Full Changelog: [v2.2.0...v2.3.0](https://github.com/Mozilla-Ocho/tabstack-python/compare/v2.2.0...v2.3.0) + +### Features + +* **api:** api update ([8bb9280](https://github.com/Mozilla-Ocho/tabstack-python/commit/8bb92809a4d7967b25f4a288557d81c9eb6883d9)) +* **api:** api update ([2453efd](https://github.com/Mozilla-Ocho/tabstack-python/commit/2453efdf272307fd008f20f18be23be1430795b4)) + + +### Chores + +* **ci:** bump uv version ([b17a93a](https://github.com/Mozilla-Ocho/tabstack-python/commit/b17a93a8f667f43518db5a278acf440bfce3ddee)) +* **ci:** skip uploading artifacts on stainless-internal branches ([4af1491](https://github.com/Mozilla-Ocho/tabstack-python/commit/4af149100add3389ca29fc7448a49d3b53a7e709)) +* format all `api.md` files ([79c09d3](https://github.com/Mozilla-Ocho/tabstack-python/commit/79c09d3d4a871fa902dc4ce0b4153fab01bb1361)) +* **internal:** add request options to SSE classes ([36eb33c](https://github.com/Mozilla-Ocho/tabstack-python/commit/36eb33c1ace478eaa0b0489642abc7bc8ba08ad2)) +* **internal:** make `test_proxy_environment_variables` more resilient ([e8a44e9](https://github.com/Mozilla-Ocho/tabstack-python/commit/e8a44e9425b78f099a7a3aee65fb25b70c5bce69)) +* **internal:** make `test_proxy_environment_variables` more resilient to env ([e9e5e13](https://github.com/Mozilla-Ocho/tabstack-python/commit/e9e5e130d7a2f5b7dd718632673fc8e8d7eb36be)) +* **internal:** remove mock server code ([f61d3b4](https://github.com/Mozilla-Ocho/tabstack-python/commit/f61d3b4f5ea74b0da9ec9d2e71b96549361d0ea6)) +* **test:** update skip reason message ([911d25f](https://github.com/Mozilla-Ocho/tabstack-python/commit/911d25fcc361fc9cdb00de3684038ca6f5aed55f)) +* update mock server docs ([ca0bd54](https://github.com/Mozilla-Ocho/tabstack-python/commit/ca0bd54fc57b5b04db69034124dae1c489926f0d)) + ## 2.2.0 (2026-02-11) Full Changelog: [v2.1.0...v2.2.0](https://github.com/Mozilla-Ocho/tabstack-python/compare/v2.1.0...v2.2.0) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6241c33..b7a8b1c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,13 +85,6 @@ $ pip install ./path-to-wheel-file.whl ## Running tests -Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. - -```sh -# you will need npm installed -$ npx prism mock path/to/your/openapi.yml -``` - ```sh $ ./scripts/test ``` diff --git a/pyproject.toml b/pyproject.toml index 97dcdfb..4a373c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "tabstack" -version = "2.2.0" +version = "2.3.0" description = "The official Python library for the tabstack API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/scripts/format b/scripts/format index 1d2f9c6..c8e1f69 100755 --- a/scripts/format +++ b/scripts/format @@ -11,4 +11,4 @@ uv run ruff check --fix . uv run ruff format echo "==> Formatting docs" -uv run python scripts/utils/ruffen-docs.py README.md api.md +uv run python scripts/utils/ruffen-docs.py README.md $(find . -type f -name api.md) diff --git a/scripts/mock b/scripts/mock deleted file mode 100755 index 0b28f6e..0000000 --- a/scripts/mock +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "$(dirname "$0")/.." - -if [[ -n "$1" && "$1" != '--'* ]]; then - URL="$1" - shift -else - URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" -fi - -# Check if the URL is empty -if [ -z "$URL" ]; then - echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" - exit 1 -fi - -echo "==> Starting mock server with URL ${URL}" - -# Run prism mock on the given spec -if [ "$1" == "--daemon" ]; then - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & - - # Wait for server to come online - echo -n "Waiting for server" - while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do - echo -n "." - sleep 0.1 - done - - if grep -q "✖ fatal" ".prism.log"; then - cat .prism.log - exit 1 - fi - - echo -else - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" -fi diff --git a/scripts/test b/scripts/test index b56970b..fe50ebb 100755 --- a/scripts/test +++ b/scripts/test @@ -4,53 +4,7 @@ set -e cd "$(dirname "$0")/.." -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[0;33m' -NC='\033[0m' # No Color -function prism_is_running() { - curl --silent "http://localhost:4010" >/dev/null 2>&1 -} - -kill_server_on_port() { - pids=$(lsof -t -i tcp:"$1" || echo "") - if [ "$pids" != "" ]; then - kill "$pids" - echo "Stopped $pids." - fi -} - -function is_overriding_api_base_url() { - [ -n "$TEST_API_BASE_URL" ] -} - -if ! is_overriding_api_base_url && ! prism_is_running ; then - # When we exit this script, make sure to kill the background mock server process - trap 'kill_server_on_port 4010' EXIT - - # Start the dev server - ./scripts/mock --daemon -fi - -if is_overriding_api_base_url ; then - echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" - echo -elif ! prism_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" - echo -e "running against your OpenAPI spec." - echo - echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the prism command:" - echo - echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" - echo - - exit 1 -else - echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" - echo -fi export DEFER_PYDANTIC_BUILD=false diff --git a/src/tabstack/_response.py b/src/tabstack/_response.py index 7f56756..d907a55 100644 --- a/src/tabstack/_response.py +++ b/src/tabstack/_response.py @@ -152,6 +152,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: ), response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -162,6 +163,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to=extract_stream_chunk_type(self._stream_cls), response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) @@ -175,6 +177,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), + options=self._options, ), ) diff --git a/src/tabstack/_streaming.py b/src/tabstack/_streaming.py index 0d8c5ae..3377de8 100644 --- a/src/tabstack/_streaming.py +++ b/src/tabstack/_streaming.py @@ -4,7 +4,7 @@ import json import inspect from types import TracebackType -from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, AsyncIterator, cast +from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, Optional, AsyncIterator, cast from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable import httpx @@ -13,6 +13,7 @@ if TYPE_CHECKING: from ._client import Tabstack, AsyncTabstack + from ._models import FinalRequestOptions _T = TypeVar("_T") @@ -22,7 +23,7 @@ class Stream(Generic[_T]): """Provides the core interface to iterate over a synchronous stream response.""" response: httpx.Response - + _options: Optional[FinalRequestOptions] = None _decoder: SSEBytesDecoder def __init__( @@ -31,10 +32,12 @@ def __init__( cast_to: type[_T], response: httpx.Response, client: Tabstack, + options: Optional[FinalRequestOptions] = None, ) -> None: self.response = response self._cast_to = cast_to self._client = client + self._options = options self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() @@ -85,7 +88,7 @@ class AsyncStream(Generic[_T]): """Provides the core interface to iterate over an asynchronous stream response.""" response: httpx.Response - + _options: Optional[FinalRequestOptions] = None _decoder: SSEDecoder | SSEBytesDecoder def __init__( @@ -94,10 +97,12 @@ def __init__( cast_to: type[_T], response: httpx.Response, client: AsyncTabstack, + options: Optional[FinalRequestOptions] = None, ) -> None: self.response = response self._cast_to = cast_to self._client = client + self._options = options self._decoder = client._make_sse_decoder() self._iterator = self.__stream__() diff --git a/src/tabstack/_version.py b/src/tabstack/_version.py index 0b88184..42120a2 100644 --- a/src/tabstack/_version.py +++ b/src/tabstack/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "tabstack" -__version__ = "2.2.0" # x-release-please-version +__version__ = "2.3.0" # x-release-please-version diff --git a/src/tabstack/resources/extract.py b/src/tabstack/resources/extract.py index 20984a8..06f0ff3 100644 --- a/src/tabstack/resources/extract.py +++ b/src/tabstack/resources/extract.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx from ..types import extract_json_params, extract_markdown_params @@ -47,6 +49,7 @@ def json( *, json_schema: object, url: str, + effort: Literal["min", "standard", "max"] | Omit = omit, geo_target: extract_json_params.GeoTarget | Omit = omit, nocache: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -64,6 +67,10 @@ def json( url: URL to fetch and extract data from + effort: Fetch effort level controlling speed vs. capability tradeoff. "min": fastest, no + fallback (1-5s). "standard": balanced with enhanced reliability (default, + 3-15s). "max": full browser rendering for JS-heavy sites (15-60s). + geo_target: Optional geotargeting parameters for proxy requests nocache: Bypass cache and force fresh data retrieval @@ -82,6 +89,7 @@ def json( { "json_schema": json_schema, "url": url, + "effort": effort, "geo_target": geo_target, "nocache": nocache, }, @@ -97,6 +105,7 @@ def markdown( self, *, url: str, + effort: Literal["min", "standard", "max"] | Omit = omit, geo_target: extract_markdown_params.GeoTarget | Omit = omit, metadata: bool | Omit = omit, nocache: bool | Omit = omit, @@ -114,6 +123,10 @@ def markdown( Args: url: URL to fetch and convert to markdown + effort: Fetch effort level controlling speed vs. capability tradeoff. "min": fastest, no + fallback (1-5s). "standard": balanced with enhanced reliability (default, + 3-15s). "max": full browser rendering for JS-heavy sites (15-60s). + geo_target: Optional geotargeting parameters for proxy requests metadata: Include extracted metadata (Open Graph and HTML metadata) as a separate field in @@ -134,6 +147,7 @@ def markdown( body=maybe_transform( { "url": url, + "effort": effort, "geo_target": geo_target, "metadata": metadata, "nocache": nocache, @@ -172,6 +186,7 @@ async def json( *, json_schema: object, url: str, + effort: Literal["min", "standard", "max"] | Omit = omit, geo_target: extract_json_params.GeoTarget | Omit = omit, nocache: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -189,6 +204,10 @@ async def json( url: URL to fetch and extract data from + effort: Fetch effort level controlling speed vs. capability tradeoff. "min": fastest, no + fallback (1-5s). "standard": balanced with enhanced reliability (default, + 3-15s). "max": full browser rendering for JS-heavy sites (15-60s). + geo_target: Optional geotargeting parameters for proxy requests nocache: Bypass cache and force fresh data retrieval @@ -207,6 +226,7 @@ async def json( { "json_schema": json_schema, "url": url, + "effort": effort, "geo_target": geo_target, "nocache": nocache, }, @@ -222,6 +242,7 @@ async def markdown( self, *, url: str, + effort: Literal["min", "standard", "max"] | Omit = omit, geo_target: extract_markdown_params.GeoTarget | Omit = omit, metadata: bool | Omit = omit, nocache: bool | Omit = omit, @@ -239,6 +260,10 @@ async def markdown( Args: url: URL to fetch and convert to markdown + effort: Fetch effort level controlling speed vs. capability tradeoff. "min": fastest, no + fallback (1-5s). "standard": balanced with enhanced reliability (default, + 3-15s). "max": full browser rendering for JS-heavy sites (15-60s). + geo_target: Optional geotargeting parameters for proxy requests metadata: Include extracted metadata (Open Graph and HTML metadata) as a separate field in @@ -259,6 +284,7 @@ async def markdown( body=await async_maybe_transform( { "url": url, + "effort": effort, "geo_target": geo_target, "metadata": metadata, "nocache": nocache, diff --git a/src/tabstack/resources/generate.py b/src/tabstack/resources/generate.py index 49aabd2..36f4952 100644 --- a/src/tabstack/resources/generate.py +++ b/src/tabstack/resources/generate.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx from ..types import generate_json_params @@ -47,6 +49,7 @@ def json( instructions: str, json_schema: object, url: str, + effort: Literal["min", "standard", "max"] | Omit = omit, geo_target: generate_json_params.GeoTarget | Omit = omit, nocache: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -67,6 +70,10 @@ def json( url: URL to fetch content from + effort: Fetch effort level controlling speed vs. capability tradeoff. "min": fastest, no + fallback (1-5s). "standard": balanced with enhanced reliability (default, + 3-15s). "max": full browser rendering for JS-heavy sites (15-60s). + geo_target: Optional geotargeting parameters for proxy requests nocache: Bypass cache and force fresh data retrieval @@ -86,6 +93,7 @@ def json( "instructions": instructions, "json_schema": json_schema, "url": url, + "effort": effort, "geo_target": geo_target, "nocache": nocache, }, @@ -124,6 +132,7 @@ async def json( instructions: str, json_schema: object, url: str, + effort: Literal["min", "standard", "max"] | Omit = omit, geo_target: generate_json_params.GeoTarget | Omit = omit, nocache: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -144,6 +153,10 @@ async def json( url: URL to fetch content from + effort: Fetch effort level controlling speed vs. capability tradeoff. "min": fastest, no + fallback (1-5s). "standard": balanced with enhanced reliability (default, + 3-15s). "max": full browser rendering for JS-heavy sites (15-60s). + geo_target: Optional geotargeting parameters for proxy requests nocache: Bypass cache and force fresh data retrieval @@ -163,6 +176,7 @@ async def json( "instructions": instructions, "json_schema": json_schema, "url": url, + "effort": effort, "geo_target": geo_target, "nocache": nocache, }, diff --git a/src/tabstack/types/extract_json_params.py b/src/tabstack/types/extract_json_params.py index 8331e16..d6d27a7 100644 --- a/src/tabstack/types/extract_json_params.py +++ b/src/tabstack/types/extract_json_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict __all__ = ["ExtractJsonParams", "GeoTarget"] @@ -14,6 +14,14 @@ class ExtractJsonParams(TypedDict, total=False): url: Required[str] """URL to fetch and extract data from""" + effort: Literal["min", "standard", "max"] + """Fetch effort level controlling speed vs. + + capability tradeoff. "min": fastest, no fallback (1-5s). "standard": balanced + with enhanced reliability (default, 3-15s). "max": full browser rendering for + JS-heavy sites (15-60s). + """ + geo_target: GeoTarget """Optional geotargeting parameters for proxy requests""" diff --git a/src/tabstack/types/extract_markdown_params.py b/src/tabstack/types/extract_markdown_params.py index a13dc4d..bd57499 100644 --- a/src/tabstack/types/extract_markdown_params.py +++ b/src/tabstack/types/extract_markdown_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict __all__ = ["ExtractMarkdownParams", "GeoTarget"] @@ -11,6 +11,14 @@ class ExtractMarkdownParams(TypedDict, total=False): url: Required[str] """URL to fetch and convert to markdown""" + effort: Literal["min", "standard", "max"] + """Fetch effort level controlling speed vs. + + capability tradeoff. "min": fastest, no fallback (1-5s). "standard": balanced + with enhanced reliability (default, 3-15s). "max": full browser rendering for + JS-heavy sites (15-60s). + """ + geo_target: GeoTarget """Optional geotargeting parameters for proxy requests""" diff --git a/src/tabstack/types/generate_json_params.py b/src/tabstack/types/generate_json_params.py index 33cb829..bbe9b76 100644 --- a/src/tabstack/types/generate_json_params.py +++ b/src/tabstack/types/generate_json_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict __all__ = ["GenerateJsonParams", "GeoTarget"] @@ -17,6 +17,14 @@ class GenerateJsonParams(TypedDict, total=False): url: Required[str] """URL to fetch content from""" + effort: Literal["min", "standard", "max"] + """Fetch effort level controlling speed vs. + + capability tradeoff. "min": fastest, no fallback (1-5s). "standard": balanced + with enhanced reliability (default, 3-15s). "max": full browser rendering for + JS-heavy sites (15-60s). + """ + geo_target: GeoTarget """Optional geotargeting parameters for proxy requests""" diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 2174d9d..cabea82 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -15,7 +15,7 @@ class TestAgent: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_automate(self, client: Tabstack) -> None: agent_stream = client.agent.automate( @@ -23,7 +23,7 @@ def test_method_automate(self, client: Tabstack) -> None: ) agent_stream.response.close() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_automate_with_all_params(self, client: Tabstack) -> None: agent_stream = client.agent.automate( @@ -37,7 +37,7 @@ def test_method_automate_with_all_params(self, client: Tabstack) -> None: ) agent_stream.response.close() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_automate(self, client: Tabstack) -> None: response = client.agent.with_raw_response.automate( @@ -48,7 +48,7 @@ def test_raw_response_automate(self, client: Tabstack) -> None: stream = response.parse() stream.close() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_automate(self, client: Tabstack) -> None: with client.agent.with_streaming_response.automate( @@ -62,7 +62,7 @@ def test_streaming_response_automate(self, client: Tabstack) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_research(self, client: Tabstack) -> None: agent_stream = client.agent.research( @@ -70,7 +70,7 @@ def test_method_research(self, client: Tabstack) -> None: ) agent_stream.response.close() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_research_with_all_params(self, client: Tabstack) -> None: agent_stream = client.agent.research( @@ -81,7 +81,7 @@ def test_method_research_with_all_params(self, client: Tabstack) -> None: ) agent_stream.response.close() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_research(self, client: Tabstack) -> None: response = client.agent.with_raw_response.research( @@ -92,7 +92,7 @@ def test_raw_response_research(self, client: Tabstack) -> None: stream = response.parse() stream.close() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_research(self, client: Tabstack) -> None: with client.agent.with_streaming_response.research( @@ -112,7 +112,7 @@ class TestAsyncAgent: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_automate(self, async_client: AsyncTabstack) -> None: agent_stream = await async_client.agent.automate( @@ -120,7 +120,7 @@ async def test_method_automate(self, async_client: AsyncTabstack) -> None: ) await agent_stream.response.aclose() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_automate_with_all_params(self, async_client: AsyncTabstack) -> None: agent_stream = await async_client.agent.automate( @@ -134,7 +134,7 @@ async def test_method_automate_with_all_params(self, async_client: AsyncTabstack ) await agent_stream.response.aclose() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_automate(self, async_client: AsyncTabstack) -> None: response = await async_client.agent.with_raw_response.automate( @@ -145,7 +145,7 @@ async def test_raw_response_automate(self, async_client: AsyncTabstack) -> None: stream = await response.parse() await stream.close() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_automate(self, async_client: AsyncTabstack) -> None: async with async_client.agent.with_streaming_response.automate( @@ -159,7 +159,7 @@ async def test_streaming_response_automate(self, async_client: AsyncTabstack) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_research(self, async_client: AsyncTabstack) -> None: agent_stream = await async_client.agent.research( @@ -167,7 +167,7 @@ async def test_method_research(self, async_client: AsyncTabstack) -> None: ) await agent_stream.response.aclose() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_research_with_all_params(self, async_client: AsyncTabstack) -> None: agent_stream = await async_client.agent.research( @@ -178,7 +178,7 @@ async def test_method_research_with_all_params(self, async_client: AsyncTabstack ) await agent_stream.response.aclose() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_research(self, async_client: AsyncTabstack) -> None: response = await async_client.agent.with_raw_response.research( @@ -189,7 +189,7 @@ async def test_raw_response_research(self, async_client: AsyncTabstack) -> None: stream = await response.parse() await stream.close() - @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_research(self, async_client: AsyncTabstack) -> None: async with async_client.agent.with_streaming_response.research( diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py index f5c7c99..262bac9 100644 --- a/tests/api_resources/test_extract.py +++ b/tests/api_resources/test_extract.py @@ -17,7 +17,7 @@ class TestExtract: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_json(self, client: Tabstack) -> None: extract = client.extract.json( @@ -50,7 +50,7 @@ def test_method_json(self, client: Tabstack) -> None: ) assert_matches_type(ExtractJsonResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_json_with_all_params(self, client: Tabstack) -> None: extract = client.extract.json( @@ -80,12 +80,13 @@ def test_method_json_with_all_params(self, client: Tabstack) -> None: "type": "object", }, url="https://news.ycombinator.com", + effort="standard", geo_target={"country": "US"}, nocache=False, ) assert_matches_type(ExtractJsonResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_json(self, client: Tabstack) -> None: response = client.extract.with_raw_response.json( @@ -122,7 +123,7 @@ def test_raw_response_json(self, client: Tabstack) -> None: extract = response.parse() assert_matches_type(ExtractJsonResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_json(self, client: Tabstack) -> None: with client.extract.with_streaming_response.json( @@ -161,7 +162,7 @@ def test_streaming_response_json(self, client: Tabstack) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_markdown(self, client: Tabstack) -> None: extract = client.extract.markdown( @@ -169,18 +170,19 @@ def test_method_markdown(self, client: Tabstack) -> None: ) assert_matches_type(ExtractMarkdownResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_markdown_with_all_params(self, client: Tabstack) -> None: extract = client.extract.markdown( url="https://example.com/blog/article", + effort="standard", geo_target={"country": "US"}, metadata=True, nocache=False, ) assert_matches_type(ExtractMarkdownResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_markdown(self, client: Tabstack) -> None: response = client.extract.with_raw_response.markdown( @@ -192,7 +194,7 @@ def test_raw_response_markdown(self, client: Tabstack) -> None: extract = response.parse() assert_matches_type(ExtractMarkdownResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_markdown(self, client: Tabstack) -> None: with client.extract.with_streaming_response.markdown( @@ -212,7 +214,7 @@ class TestAsyncExtract: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_json(self, async_client: AsyncTabstack) -> None: extract = await async_client.extract.json( @@ -245,7 +247,7 @@ async def test_method_json(self, async_client: AsyncTabstack) -> None: ) assert_matches_type(ExtractJsonResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_json_with_all_params(self, async_client: AsyncTabstack) -> None: extract = await async_client.extract.json( @@ -275,12 +277,13 @@ async def test_method_json_with_all_params(self, async_client: AsyncTabstack) -> "type": "object", }, url="https://news.ycombinator.com", + effort="standard", geo_target={"country": "US"}, nocache=False, ) assert_matches_type(ExtractJsonResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_json(self, async_client: AsyncTabstack) -> None: response = await async_client.extract.with_raw_response.json( @@ -317,7 +320,7 @@ async def test_raw_response_json(self, async_client: AsyncTabstack) -> None: extract = await response.parse() assert_matches_type(ExtractJsonResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_json(self, async_client: AsyncTabstack) -> None: async with async_client.extract.with_streaming_response.json( @@ -356,7 +359,7 @@ async def test_streaming_response_json(self, async_client: AsyncTabstack) -> Non assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_markdown(self, async_client: AsyncTabstack) -> None: extract = await async_client.extract.markdown( @@ -364,18 +367,19 @@ async def test_method_markdown(self, async_client: AsyncTabstack) -> None: ) assert_matches_type(ExtractMarkdownResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_markdown_with_all_params(self, async_client: AsyncTabstack) -> None: extract = await async_client.extract.markdown( url="https://example.com/blog/article", + effort="standard", geo_target={"country": "US"}, metadata=True, nocache=False, ) assert_matches_type(ExtractMarkdownResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_markdown(self, async_client: AsyncTabstack) -> None: response = await async_client.extract.with_raw_response.markdown( @@ -387,7 +391,7 @@ async def test_raw_response_markdown(self, async_client: AsyncTabstack) -> None: extract = await response.parse() assert_matches_type(ExtractMarkdownResponse, extract, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_markdown(self, async_client: AsyncTabstack) -> None: async with async_client.extract.with_streaming_response.markdown( diff --git a/tests/api_resources/test_generate.py b/tests/api_resources/test_generate.py index cc8e089..7d6e934 100644 --- a/tests/api_resources/test_generate.py +++ b/tests/api_resources/test_generate.py @@ -17,7 +17,7 @@ class TestGenerate: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_json(self, client: Tabstack) -> None: generate = client.generate.json( @@ -51,7 +51,7 @@ def test_method_json(self, client: Tabstack) -> None: ) assert_matches_type(GenerateJsonResponse, generate, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_json_with_all_params(self, client: Tabstack) -> None: generate = client.generate.json( @@ -82,12 +82,13 @@ def test_method_json_with_all_params(self, client: Tabstack) -> None: "type": "object", }, url="https://news.ycombinator.com", + effort="standard", geo_target={"country": "US"}, nocache=False, ) assert_matches_type(GenerateJsonResponse, generate, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_json(self, client: Tabstack) -> None: response = client.generate.with_raw_response.json( @@ -125,7 +126,7 @@ def test_raw_response_json(self, client: Tabstack) -> None: generate = response.parse() assert_matches_type(GenerateJsonResponse, generate, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_json(self, client: Tabstack) -> None: with client.generate.with_streaming_response.json( @@ -171,7 +172,7 @@ class TestAsyncGenerate: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_json(self, async_client: AsyncTabstack) -> None: generate = await async_client.generate.json( @@ -205,7 +206,7 @@ async def test_method_json(self, async_client: AsyncTabstack) -> None: ) assert_matches_type(GenerateJsonResponse, generate, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_json_with_all_params(self, async_client: AsyncTabstack) -> None: generate = await async_client.generate.json( @@ -236,12 +237,13 @@ async def test_method_json_with_all_params(self, async_client: AsyncTabstack) -> "type": "object", }, url="https://news.ycombinator.com", + effort="standard", geo_target={"country": "US"}, nocache=False, ) assert_matches_type(GenerateJsonResponse, generate, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_json(self, async_client: AsyncTabstack) -> None: response = await async_client.generate.with_raw_response.json( @@ -279,7 +281,7 @@ async def test_raw_response_json(self, async_client: AsyncTabstack) -> None: generate = await response.parse() assert_matches_type(GenerateJsonResponse, generate, path=["response"]) - @pytest.mark.skip(reason="Prism tests are disabled") + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_json(self, async_client: AsyncTabstack) -> None: async with async_client.generate.with_streaming_response.json( diff --git a/tests/test_client.py b/tests/test_client.py index cd51eee..f6e8193 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -959,6 +959,14 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly monkeypatch.setenv("HTTPS_PROXY", "https://example.org") + # Delete in case our environment has any proxy env vars set + monkeypatch.delenv("HTTP_PROXY", raising=False) + monkeypatch.delenv("ALL_PROXY", raising=False) + monkeypatch.delenv("NO_PROXY", raising=False) + monkeypatch.delenv("http_proxy", raising=False) + monkeypatch.delenv("https_proxy", raising=False) + monkeypatch.delenv("all_proxy", raising=False) + monkeypatch.delenv("no_proxy", raising=False) client = DefaultHttpxClient() @@ -1877,6 +1885,14 @@ async def test_get_platform(self) -> None: async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: # Test that the proxy environment variables are set correctly monkeypatch.setenv("HTTPS_PROXY", "https://example.org") + # Delete in case our environment has any proxy env vars set + monkeypatch.delenv("HTTP_PROXY", raising=False) + monkeypatch.delenv("ALL_PROXY", raising=False) + monkeypatch.delenv("NO_PROXY", raising=False) + monkeypatch.delenv("http_proxy", raising=False) + monkeypatch.delenv("https_proxy", raising=False) + monkeypatch.delenv("all_proxy", raising=False) + monkeypatch.delenv("no_proxy", raising=False) client = DefaultAsyncHttpxClient()