Skip to content

Commit 47d3d13

Browse files
chore(types): change optional parameter type from NotGiven to Omit
1 parent b3b9856 commit 47d3d13

14 files changed

Lines changed: 235 additions & 218 deletions

File tree

src/steel/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import typing as _t
44

55
from . import types
6-
from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes
6+
from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given
77
from ._utils import file_from_path
88
from ._client import Steel, Client, Stream, Timeout, Transport, AsyncSteel, AsyncClient, AsyncStream, RequestOptions
99
from ._models import BaseModel
@@ -38,7 +38,9 @@
3838
"ProxiesTypes",
3939
"NotGiven",
4040
"NOT_GIVEN",
41+
"not_given",
4142
"Omit",
43+
"omit",
4244
"SteelError",
4345
"APIError",
4446
"APIStatusError",

src/steel/_base_client.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
from ._qs import Querystring
4343
from ._files import to_httpx_files, async_to_httpx_files
4444
from ._types import (
45-
NOT_GIVEN,
4645
Body,
4746
Omit,
4847
Query,
@@ -57,6 +56,7 @@
5756
RequestOptions,
5857
HttpxRequestFiles,
5958
ModelBuilderProtocol,
59+
not_given,
6060
)
6161
from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping
6262
from ._compat import PYDANTIC_V1, model_copy, model_dump
@@ -145,9 +145,9 @@ def __init__(
145145
def __init__(
146146
self,
147147
*,
148-
url: URL | NotGiven = NOT_GIVEN,
149-
json: Body | NotGiven = NOT_GIVEN,
150-
params: Query | NotGiven = NOT_GIVEN,
148+
url: URL | NotGiven = not_given,
149+
json: Body | NotGiven = not_given,
150+
params: Query | NotGiven = not_given,
151151
) -> None:
152152
self.url = url
153153
self.json = json
@@ -595,7 +595,7 @@ def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalReques
595595
# we internally support defining a temporary header to override the
596596
# default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response`
597597
# see _response.py for implementation details
598-
override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, NOT_GIVEN)
598+
override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, not_given)
599599
if is_given(override_cast_to):
600600
options.headers = headers
601601
return cast(Type[ResponseT], override_cast_to)
@@ -825,7 +825,7 @@ def __init__(
825825
version: str,
826826
base_url: str | URL,
827827
max_retries: int = DEFAULT_MAX_RETRIES,
828-
timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
828+
timeout: float | Timeout | None | NotGiven = not_given,
829829
http_client: httpx.Client | None = None,
830830
custom_headers: Mapping[str, str] | None = None,
831831
custom_query: Mapping[str, object] | None = None,
@@ -1356,7 +1356,7 @@ def __init__(
13561356
base_url: str | URL,
13571357
_strict_response_validation: bool,
13581358
max_retries: int = DEFAULT_MAX_RETRIES,
1359-
timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
1359+
timeout: float | Timeout | None | NotGiven = not_given,
13601360
http_client: httpx.AsyncClient | None = None,
13611361
custom_headers: Mapping[str, str] | None = None,
13621362
custom_query: Mapping[str, object] | None = None,
@@ -1818,8 +1818,8 @@ def make_request_options(
18181818
extra_query: Query | None = None,
18191819
extra_body: Body | None = None,
18201820
idempotency_key: str | None = None,
1821-
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
1822-
post_parser: PostParser | NotGiven = NOT_GIVEN,
1821+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
1822+
post_parser: PostParser | NotGiven = not_given,
18231823
) -> RequestOptions:
18241824
"""Create a dict of type RequestOptions without keys of NotGiven values."""
18251825
options: RequestOptions = {}

src/steel/_client.py

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from __future__ import annotations
44

55
import os
6-
from typing import Any, List, Union, Mapping
6+
from typing import Any, List, Mapping
77
from typing_extensions import Self, Literal, override
88

99
import httpx
@@ -12,7 +12,6 @@
1212
from ._qs import Querystring
1313
from .types import client_pdf_params, client_scrape_params, client_screenshot_params
1414
from ._types import (
15-
NOT_GIVEN,
1615
Body,
1716
Omit,
1817
Query,
@@ -22,6 +21,8 @@
2221
Transport,
2322
ProxiesTypes,
2423
RequestOptions,
24+
omit,
25+
not_given,
2526
)
2627
from ._utils import (
2728
is_given,
@@ -69,7 +70,7 @@ def __init__(
6970
*,
7071
steel_api_key: str | None = None,
7172
base_url: str | httpx.URL | None = None,
72-
timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN,
73+
timeout: float | Timeout | None | NotGiven = not_given,
7374
max_retries: int = DEFAULT_MAX_RETRIES,
7475
default_headers: Mapping[str, str] | None = None,
7576
default_query: Mapping[str, object] | None = None,
@@ -145,9 +146,9 @@ def copy(
145146
*,
146147
steel_api_key: str | None = None,
147148
base_url: str | httpx.URL | None = None,
148-
timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
149+
timeout: float | Timeout | None | NotGiven = not_given,
149150
http_client: httpx.Client | None = None,
150-
max_retries: int | NotGiven = NOT_GIVEN,
151+
max_retries: int | NotGiven = not_given,
151152
default_headers: Mapping[str, str] | None = None,
152153
set_default_headers: Mapping[str, str] | None = None,
153154
default_query: Mapping[str, object] | None = None,
@@ -195,15 +196,15 @@ def pdf(
195196
self,
196197
*,
197198
url: str,
198-
delay: float | NotGiven = NOT_GIVEN,
199-
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | NotGiven = NOT_GIVEN,
200-
use_proxy: bool | NotGiven = NOT_GIVEN,
199+
delay: float | Omit = omit,
200+
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | Omit = omit,
201+
use_proxy: bool | Omit = omit,
201202
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
202203
# The extra values given here take precedence over values defined on the client or passed to this method.
203204
extra_headers: Headers | None = None,
204205
extra_query: Query | None = None,
205206
extra_body: Body | None = None,
206-
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
207+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
207208
) -> PdfResponse:
208209
"""
209210
Generates a PDF from a specified webpage.
@@ -246,18 +247,18 @@ def scrape(
246247
self,
247248
*,
248249
url: str,
249-
delay: float | NotGiven = NOT_GIVEN,
250-
format: List[Literal["html", "readability", "cleaned_html", "markdown"]] | NotGiven = NOT_GIVEN,
251-
pdf: bool | NotGiven = NOT_GIVEN,
252-
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | NotGiven = NOT_GIVEN,
253-
screenshot: bool | NotGiven = NOT_GIVEN,
254-
use_proxy: bool | NotGiven = NOT_GIVEN,
250+
delay: float | Omit = omit,
251+
format: List[Literal["html", "readability", "cleaned_html", "markdown"]] | Omit = omit,
252+
pdf: bool | Omit = omit,
253+
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | Omit = omit,
254+
screenshot: bool | Omit = omit,
255+
use_proxy: bool | Omit = omit,
255256
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
256257
# The extra values given here take precedence over values defined on the client or passed to this method.
257258
extra_headers: Headers | None = None,
258259
extra_query: Query | None = None,
259260
extra_body: Body | None = None,
260-
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
261+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
261262
) -> ScrapeResponse:
262263
"""
263264
Extracts content from a specified URL.
@@ -309,16 +310,16 @@ def screenshot(
309310
self,
310311
*,
311312
url: str,
312-
delay: float | NotGiven = NOT_GIVEN,
313-
full_page: bool | NotGiven = NOT_GIVEN,
314-
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | NotGiven = NOT_GIVEN,
315-
use_proxy: bool | NotGiven = NOT_GIVEN,
313+
delay: float | Omit = omit,
314+
full_page: bool | Omit = omit,
315+
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | Omit = omit,
316+
use_proxy: bool | Omit = omit,
316317
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
317318
# The extra values given here take precedence over values defined on the client or passed to this method.
318319
extra_headers: Headers | None = None,
319320
extra_query: Query | None = None,
320321
extra_body: Body | None = None,
321-
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
322+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
322323
) -> ScreenshotResponse:
323324
"""
324325
Captures a screenshot of a specified webpage.
@@ -410,7 +411,7 @@ def __init__(
410411
*,
411412
steel_api_key: str | None = None,
412413
base_url: str | httpx.URL | None = None,
413-
timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN,
414+
timeout: float | Timeout | None | NotGiven = not_given,
414415
max_retries: int = DEFAULT_MAX_RETRIES,
415416
default_headers: Mapping[str, str] | None = None,
416417
default_query: Mapping[str, object] | None = None,
@@ -486,9 +487,9 @@ def copy(
486487
*,
487488
steel_api_key: str | None = None,
488489
base_url: str | httpx.URL | None = None,
489-
timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
490+
timeout: float | Timeout | None | NotGiven = not_given,
490491
http_client: httpx.AsyncClient | None = None,
491-
max_retries: int | NotGiven = NOT_GIVEN,
492+
max_retries: int | NotGiven = not_given,
492493
default_headers: Mapping[str, str] | None = None,
493494
set_default_headers: Mapping[str, str] | None = None,
494495
default_query: Mapping[str, object] | None = None,
@@ -536,15 +537,15 @@ async def pdf(
536537
self,
537538
*,
538539
url: str,
539-
delay: float | NotGiven = NOT_GIVEN,
540-
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | NotGiven = NOT_GIVEN,
541-
use_proxy: bool | NotGiven = NOT_GIVEN,
540+
delay: float | Omit = omit,
541+
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | Omit = omit,
542+
use_proxy: bool | Omit = omit,
542543
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
543544
# The extra values given here take precedence over values defined on the client or passed to this method.
544545
extra_headers: Headers | None = None,
545546
extra_query: Query | None = None,
546547
extra_body: Body | None = None,
547-
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
548+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
548549
) -> PdfResponse:
549550
"""
550551
Generates a PDF from a specified webpage.
@@ -587,18 +588,18 @@ async def scrape(
587588
self,
588589
*,
589590
url: str,
590-
delay: float | NotGiven = NOT_GIVEN,
591-
format: List[Literal["html", "readability", "cleaned_html", "markdown"]] | NotGiven = NOT_GIVEN,
592-
pdf: bool | NotGiven = NOT_GIVEN,
593-
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | NotGiven = NOT_GIVEN,
594-
screenshot: bool | NotGiven = NOT_GIVEN,
595-
use_proxy: bool | NotGiven = NOT_GIVEN,
591+
delay: float | Omit = omit,
592+
format: List[Literal["html", "readability", "cleaned_html", "markdown"]] | Omit = omit,
593+
pdf: bool | Omit = omit,
594+
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | Omit = omit,
595+
screenshot: bool | Omit = omit,
596+
use_proxy: bool | Omit = omit,
596597
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
597598
# The extra values given here take precedence over values defined on the client or passed to this method.
598599
extra_headers: Headers | None = None,
599600
extra_query: Query | None = None,
600601
extra_body: Body | None = None,
601-
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
602+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
602603
) -> ScrapeResponse:
603604
"""
604605
Extracts content from a specified URL.
@@ -650,16 +651,16 @@ async def screenshot(
650651
self,
651652
*,
652653
url: str,
653-
delay: float | NotGiven = NOT_GIVEN,
654-
full_page: bool | NotGiven = NOT_GIVEN,
655-
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | NotGiven = NOT_GIVEN,
656-
use_proxy: bool | NotGiven = NOT_GIVEN,
654+
delay: float | Omit = omit,
655+
full_page: bool | Omit = omit,
656+
region: Literal["lax", "ord", "iad", "bom", "scl", "fra", "hkg"] | Omit = omit,
657+
use_proxy: bool | Omit = omit,
657658
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
658659
# The extra values given here take precedence over values defined on the client or passed to this method.
659660
extra_headers: Headers | None = None,
660661
extra_query: Query | None = None,
661662
extra_body: Body | None = None,
662-
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
663+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
663664
) -> ScreenshotResponse:
664665
"""
665666
Captures a screenshot of a specified webpage.

src/steel/_qs.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from urllib.parse import parse_qs, urlencode
55
from typing_extensions import Literal, get_args
66

7-
from ._types import NOT_GIVEN, NotGiven, NotGivenOr
7+
from ._types import NotGiven, not_given
88
from ._utils import flatten
99

1010
_T = TypeVar("_T")
@@ -41,8 +41,8 @@ def stringify(
4141
self,
4242
params: Params,
4343
*,
44-
array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN,
45-
nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN,
44+
array_format: ArrayFormat | NotGiven = not_given,
45+
nested_format: NestedFormat | NotGiven = not_given,
4646
) -> str:
4747
return urlencode(
4848
self.stringify_items(
@@ -56,8 +56,8 @@ def stringify_items(
5656
self,
5757
params: Params,
5858
*,
59-
array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN,
60-
nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN,
59+
array_format: ArrayFormat | NotGiven = not_given,
60+
nested_format: NestedFormat | NotGiven = not_given,
6161
) -> list[tuple[str, str]]:
6262
opts = Options(
6363
qs=self,
@@ -143,8 +143,8 @@ def __init__(
143143
self,
144144
qs: Querystring = _qs,
145145
*,
146-
array_format: NotGivenOr[ArrayFormat] = NOT_GIVEN,
147-
nested_format: NotGivenOr[NestedFormat] = NOT_GIVEN,
146+
array_format: ArrayFormat | NotGiven = not_given,
147+
nested_format: NestedFormat | NotGiven = not_given,
148148
) -> None:
149149
self.array_format = qs.array_format if isinstance(array_format, NotGiven) else array_format
150150
self.nested_format = qs.nested_format if isinstance(nested_format, NotGiven) else nested_format

src/steel/_types.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,21 @@ class RequestOptions(TypedDict, total=False):
117117
# Sentinel class used until PEP 0661 is accepted
118118
class NotGiven:
119119
"""
120-
A sentinel singleton class used to distinguish omitted keyword arguments
121-
from those passed in with the value None (which may have different behavior).
120+
For parameters with a meaningful None value, we need to distinguish between
121+
the user explicitly passing None, and the user not passing the parameter at
122+
all.
123+
124+
User code shouldn't need to use not_given directly.
122125
123126
For example:
124127
125128
```py
126-
def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: ...
129+
def create(timeout: Timeout | None | NotGiven = not_given): ...
127130
128131
129-
get(timeout=1) # 1s timeout
130-
get(timeout=None) # No timeout
131-
get() # Default timeout behavior, which may not be statically known at the method definition.
132+
create(timeout=1) # 1s timeout
133+
create(timeout=None) # No timeout
134+
create() # Default timeout behavior
132135
```
133136
"""
134137

@@ -140,13 +143,14 @@ def __repr__(self) -> str:
140143
return "NOT_GIVEN"
141144

142145

143-
NotGivenOr = Union[_T, NotGiven]
146+
not_given = NotGiven()
147+
# for backwards compatibility:
144148
NOT_GIVEN = NotGiven()
145149

146150

147151
class Omit:
148-
"""In certain situations you need to be able to represent a case where a default value has
149-
to be explicitly removed and `None` is not an appropriate substitute, for example:
152+
"""
153+
To explicitly omit something from being sent in a request, use `omit`.
150154
151155
```py
152156
# as the default `Content-Type` header is `application/json` that will be sent
@@ -156,15 +160,18 @@ class Omit:
156160
# to look something like: 'multipart/form-data; boundary=0d8382fcf5f8c3be01ca2e11002d2983'
157161
client.post(..., headers={"Content-Type": "multipart/form-data"})
158162
159-
# instead you can remove the default `application/json` header by passing Omit
160-
client.post(..., headers={"Content-Type": Omit()})
163+
# instead you can remove the default `application/json` header by passing omit
164+
client.post(..., headers={"Content-Type": omit})
161165
```
162166
"""
163167

164168
def __bool__(self) -> Literal[False]:
165169
return False
166170

167171

172+
omit = Omit()
173+
174+
168175
@runtime_checkable
169176
class ModelBuilderProtocol(Protocol):
170177
@classmethod

0 commit comments

Comments
 (0)