Skip to content

Commit 062cc15

Browse files
authored
feat(api): api review nits (microsoft#381)
1 parent f347dd4 commit 062cc15

30 files changed

+441
-469
lines changed

playwright/__init__.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,8 @@
2828
FilePayload = api_types.FilePayload
2929
FloatRect = api_types.FloatRect
3030
Geolocation = api_types.Geolocation
31-
HttpCredentials = api_types.HttpCredentials
3231
PdfMargins = api_types.PdfMargins
3332
ProxySettings = api_types.ProxySettings
34-
RecordHarOptions = api_types.RecordHarOptions
35-
RecordVideoOptions = api_types.RecordVideoOptions
36-
RequestFailure = api_types.RequestFailure
37-
OptionSelector = api_types.OptionSelector
3833
SourceLocation = api_types.SourceLocation
3934
TimeoutError = api_types.TimeoutError
4035

@@ -55,19 +50,14 @@ def sync_playwright() -> SyncPlaywrightContextManager:
5550
"async_playwright",
5651
"sync_playwright",
5752
"Cookie",
58-
"HttpCredentials",
5953
"DeviceDescriptor",
6054
"Error",
6155
"FilePayload",
6256
"FloatRect",
6357
"Geolocation",
6458
"PdfMargins",
6559
"ProxySettings",
66-
"RecordHarOptions",
67-
"RecordVideoOptions",
68-
"RequestFailure",
6960
"ResourceTiming",
70-
"OptionSelector",
7161
"SourceLocation",
7262
"StorageState",
7363
"TimeoutError",

playwright/_api_types.py

Lines changed: 7 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from pathlib import Path
15+
import sys
1616
from typing import Any, Dict, Optional, Tuple, Union
1717

18+
if sys.version_info >= (3, 8): # pragma: no cover
19+
from typing import TypedDict
20+
else: # pragma: no cover
21+
from typing_extensions import TypedDict
22+
1823

1924
class Error(Exception):
2025
def __init__(self, message: str, stack: str = None) -> None:
@@ -68,37 +73,13 @@ def __init__(self, x: float, y: float, width: float, height: float):
6873
self.height = height
6974

7075

71-
class DeviceDescriptor(ApiType):
76+
class DeviceDescriptor(TypedDict):
7277
user_agent: Optional[str]
7378
viewport: Optional[Tuple[int, int]]
7479
device_scale_factor: Optional[int]
7580
is_mobile: Optional[bool]
7681
has_touch: Optional[bool]
7782

78-
@classmethod
79-
def _parse(cls, dict: Dict) -> "DeviceDescriptor":
80-
return DeviceDescriptor(
81-
dict["userAgent"],
82-
dict["viewport"],
83-
dict["deviceScaleFactor"],
84-
dict["isMobile"],
85-
dict["hasTouch"],
86-
)
87-
88-
def __init__(
89-
self,
90-
user_agent: str = None,
91-
viewport: Tuple[int, int] = None,
92-
device_scale_factor: int = None,
93-
is_mobile: bool = None,
94-
has_touch: bool = None,
95-
):
96-
self.user_agent = user_agent
97-
self.viewport = viewport
98-
self.device_scale_factor = device_scale_factor
99-
self.is_mobile = is_mobile
100-
self.has_touch = has_touch
101-
10283

10384
class Geolocation(ApiType):
10485
latitude: float
@@ -111,15 +92,6 @@ def __init__(self, latitude: float, longitude: float, accuracy: float = None):
11192
self.accuracy = accuracy
11293

11394

114-
class HttpCredentials(ApiType):
115-
username: str
116-
password: str
117-
118-
def __init__(self, username: str, password: str):
119-
self.username = username
120-
self.password = password
121-
122-
12395
class PdfMargins(ApiType):
12496
top: Optional[Union[str, int]]
12597
right: Optional[Union[str, int]]
@@ -158,52 +130,6 @@ def __init__(
158130
self.password = password
159131

160132

161-
class RequestFailure(ApiType):
162-
error_text: str
163-
164-
@classmethod
165-
def _parse(cls, dict: Optional[Dict]) -> Optional["RequestFailure"]:
166-
if not dict:
167-
return None
168-
return RequestFailure(dict["errorText"])
169-
170-
def __init__(self, error_text: str):
171-
self.error_text = error_text
172-
173-
174-
class RecordHarOptions(ApiType):
175-
omit_content: Optional[bool]
176-
path: Union[Path, str]
177-
178-
def __init__(self, path: Union[str, Path], omit_content: bool = None):
179-
self.path = path
180-
self.omit_content = omit_content
181-
182-
def _to_json(self) -> Dict:
183-
return filter_out_none(
184-
{"omitContent": self.omit_content, "path": str(self.path)}
185-
)
186-
187-
188-
class RecordVideoOptions(ApiType):
189-
dir: Union[Path, str]
190-
size: Optional[Tuple[int, int]]
191-
192-
def __init__(self, dir: Union[str, Path], size: Tuple[int, int] = None):
193-
self.dir = dir
194-
self.size = size
195-
196-
def _to_json(self) -> Dict:
197-
return filter_out_none(
198-
{
199-
"dir": str(self.dir),
200-
"size": {"width": self.size[0], "height": self.size[1]}
201-
if self.size
202-
else None,
203-
}
204-
)
205-
206-
207133
class SourceLocation(ApiType):
208134
url: str
209135
line: int
@@ -215,17 +141,6 @@ def __init__(self, url: str, line: int, column: int):
215141
self.column = column
216142

217143

218-
class OptionSelector(ApiType):
219-
value: Optional[str]
220-
label: Optional[str]
221-
index: Optional[int]
222-
223-
def __init__(self, value: str = None, label: str = None, index: int = None):
224-
self.value = value
225-
self.label = label
226-
self.index = index
227-
228-
229144
def filter_out_none(args: Dict) -> Any:
230145
copy = {}
231146
for key in args:

playwright/_browser.py

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,7 @@
1919
from typing import TYPE_CHECKING, Dict, List, Tuple, Union
2020

2121
from playwright._api_structures import StorageState
22-
from playwright._api_types import (
23-
Geolocation,
24-
HttpCredentials,
25-
ProxySettings,
26-
RecordHarOptions,
27-
RecordVideoOptions,
28-
)
22+
from playwright._api_types import Geolocation, ProxySettings
2923
from playwright._browser_context import BrowserContext
3024
from playwright._connection import ChannelOwner, from_channel
3125
from playwright._helper import ColorScheme, is_safe_close_error, locals_to_params
@@ -83,32 +77,22 @@ async def newContext(
8377
permissions: List[str] = None,
8478
extraHTTPHeaders: Dict[str, str] = None,
8579
offline: bool = None,
86-
httpCredentials: HttpCredentials = None,
80+
httpCredentials: Tuple[str, str] = None,
8781
deviceScaleFactor: int = None,
8882
isMobile: bool = None,
8983
hasTouch: bool = None,
9084
colorScheme: ColorScheme = None,
9185
acceptDownloads: bool = None,
9286
defaultBrowserType: str = None,
9387
proxy: ProxySettings = None,
94-
recordHar: RecordHarOptions = None,
95-
recordVideo: RecordVideoOptions = None,
88+
recordHarPath: Union[Path, str] = None,
89+
recordHarOmitContent: bool = None,
90+
recordVideoDir: Union[Path, str] = None,
91+
recordVideoSize: Tuple[int, int] = None,
9692
storageState: Union[StorageState, str, Path] = None,
9793
) -> BrowserContext:
9894
params = locals_to_params(locals())
99-
# Python is strict in which variables gets passed to methods. We get this
100-
# value from the device descriptors, thats why we have to strip it out.
101-
if defaultBrowserType in params:
102-
del params["defaultBrowserType"]
103-
if storageState:
104-
if not isinstance(storageState, dict):
105-
with open(storageState, "r") as f:
106-
params["storageState"] = json.load(f)
107-
if viewport == 0:
108-
del params["viewport"]
109-
params["noDefaultViewport"] = True
110-
if extraHTTPHeaders:
111-
params["extraHTTPHeaders"] = serialize_headers(extraHTTPHeaders)
95+
normalize_context_params(params)
11296

11397
channel = await self._channel.send("newContext", params)
11498
context = from_channel(channel)
@@ -130,27 +114,21 @@ async def newPage(
130114
permissions: List[str] = None,
131115
extraHTTPHeaders: Dict[str, str] = None,
132116
offline: bool = None,
133-
httpCredentials: HttpCredentials = None,
117+
httpCredentials: Tuple[str, str] = None,
134118
deviceScaleFactor: int = None,
135119
isMobile: bool = None,
136120
hasTouch: bool = None,
137121
colorScheme: ColorScheme = None,
138122
acceptDownloads: bool = None,
139123
defaultBrowserType: str = None,
140124
proxy: ProxySettings = None,
141-
recordHar: RecordHarOptions = None,
142-
recordVideo: RecordVideoOptions = None,
125+
recordHarPath: Union[Path, str] = None,
126+
recordHarOmitContent: bool = None,
127+
recordVideoDir: Union[Path, str] = None,
128+
recordVideoSize: Tuple[int, int] = None,
143129
storageState: Union[StorageState, str, Path] = None,
144130
) -> Page:
145131
params = locals_to_params(locals())
146-
# Python is strict in which variables gets passed to methods. We get this
147-
# value from the device descriptors, thats why we have to strip it out.
148-
if defaultBrowserType:
149-
del params["defaultBrowserType"]
150-
if storageState:
151-
if not isinstance(storageState, dict):
152-
with open(storageState, "r") as f:
153-
params["storageState"] = json.load(f)
154132
context = await self.newContext(**params)
155133
page = await context.newPage()
156134
page._owned_context = context
@@ -170,3 +148,33 @@ async def close(self) -> None:
170148
@property
171149
def version(self) -> str:
172150
return self._initializer["version"]
151+
152+
153+
def normalize_context_params(params: Dict) -> None:
154+
if "viewport" in params and params["viewport"] == 0:
155+
del params["viewport"]
156+
params["noDefaultViewport"] = True
157+
if "defaultBrowserType" in params:
158+
del params["defaultBrowserType"]
159+
if "extraHTTPHeaders" in params:
160+
params["extraHTTPHeaders"] = serialize_headers(params["extraHTTPHeaders"])
161+
if "recordHarPath" in params:
162+
params["recordHar"] = {"path": str(params["recordHarPath"])}
163+
if "recordHarOmitContent" in params:
164+
params["recordHar"]["omitContent"] = True
165+
del params["recordHarOmitContent"]
166+
del params["recordHarPath"]
167+
if "recordVideoDir" in params:
168+
params["recordVideo"] = {"dir": str(params["recordVideoDir"])}
169+
if "recordVideoSize" in params:
170+
params["recordVideo"]["size"] = {
171+
"width": params["recordVideoSize"][0],
172+
"height": params["recordVideoSize"][1],
173+
}
174+
del params["recordVideoSize"]
175+
del params["recordVideoDir"]
176+
if "storageState" in params:
177+
storageState = params["storageState"]
178+
if not isinstance(storageState, dict):
179+
with open(storageState, "r") as f:
180+
params["storageState"] = json.load(f)

playwright/_browser_context.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union, cast
2121

2222
from playwright._api_structures import Cookie, StorageState
23-
from playwright._api_types import Error, Geolocation
23+
from playwright._api_types import Error
2424
from playwright._connection import ChannelOwner, from_channel
2525
from playwright._event_context_manager import EventContextManagerImpl
2626
from playwright._helper import (
@@ -141,8 +141,15 @@ async def grantPermissions(
141141
async def clearPermissions(self) -> None:
142142
await self._channel.send("clearPermissions")
143143

144-
async def setGeolocation(self, geolocation: Optional[Geolocation]) -> None:
145-
await self._channel.send("setGeolocation", locals_to_params(locals()))
144+
async def setGeolocation(
145+
self, latitude: float, longitude: float, accuracy: Optional[float]
146+
) -> None:
147+
await self._channel.send(
148+
"setGeolocation", {"geolocation": locals_to_params(locals())}
149+
)
150+
151+
async def resetGeolocation(self) -> None:
152+
await self._channel.send("setGeolocation", {})
146153

147154
async def setExtraHTTPHeaders(self, headers: Dict[str, str]) -> None:
148155
await self._channel.send(

playwright/_browser_type.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,11 @@
1616
from pathlib import Path
1717
from typing import Dict, List, Tuple, Union
1818

19-
from playwright._api_types import (
20-
Geolocation,
21-
HttpCredentials,
22-
ProxySettings,
23-
RecordHarOptions,
24-
RecordVideoOptions,
25-
)
26-
from playwright._browser import Browser
19+
from playwright._api_types import Geolocation, ProxySettings
20+
from playwright._browser import Browser, normalize_context_params
2721
from playwright._browser_context import BrowserContext
2822
from playwright._connection import ChannelOwner, from_channel
2923
from playwright._helper import ColorScheme, Env, locals_to_params, not_installed_error
30-
from playwright._network import serialize_headers
3124

3225
if sys.version_info >= (3, 8): # pragma: no cover
3326
from typing import Literal
@@ -103,23 +96,21 @@ async def launchPersistentContext(
10396
permissions: List[str] = None,
10497
extraHTTPHeaders: Dict[str, str] = None,
10598
offline: bool = None,
106-
httpCredentials: HttpCredentials = None,
99+
httpCredentials: Tuple[str, str] = None,
107100
deviceScaleFactor: int = None,
108101
isMobile: bool = None,
109102
hasTouch: bool = None,
110103
colorScheme: ColorScheme = None,
111104
acceptDownloads: bool = None,
112105
chromiumSandbox: bool = None,
113-
recordHar: RecordHarOptions = None,
114-
recordVideo: RecordVideoOptions = None,
106+
recordHarPath: Union[Path, str] = None,
107+
recordHarOmitContent: bool = None,
108+
recordVideoDir: Union[Path, str] = None,
109+
recordVideoSize: Tuple[int, int] = None,
115110
) -> BrowserContext:
116111
userDataDir = str(Path(userDataDir))
117112
params = locals_to_params(locals())
118-
if viewport == 0:
119-
del params["viewport"]
120-
params["noDefaultViewport"] = True
121-
if extraHTTPHeaders:
122-
params["extraHTTPHeaders"] = serialize_headers(extraHTTPHeaders)
113+
normalize_context_params(params)
123114
normalize_launch_params(params)
124115
try:
125116
context = from_channel(

playwright/_connection.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ def _replace_channels_with_guids(self, payload: Any, param_name: str) -> Any:
237237
return {"x": payload[0], "y": payload[1]}
238238
if param_name == "size" or param_name == "viewport":
239239
return {"width": payload[0], "height": payload[1]}
240+
if param_name == "httpCredentials":
241+
return {"username": payload[0], "password": payload[1]}
240242
if isinstance(payload, Path):
241243
return str(payload)
242244
if isinstance(payload, ApiType):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy