Skip to content

Commit 2794a3b

Browse files
authored
api(video): support video accessor from 1.5.1 (microsoft#238)
1 parent 6a649d8 commit 2794a3b

File tree

12 files changed

+193
-3
lines changed

12 files changed

+193
-3
lines changed

api.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

build_package.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
from playwright.path_utils import get_file_dirname
2424

25-
driver_version = "0.150.0"
25+
driver_version = "0.151.0"
2626

2727
if not os.path.exists("driver"):
2828
os.makedirs("driver")

playwright/async_api.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
from playwright.page import Worker as WorkerImpl
6565
from playwright.playwright import Playwright as PlaywrightImpl
6666
from playwright.selectors import Selectors as SelectorsImpl
67+
from playwright.video import Video as VideoImpl
6768

6869
NoneType = type(None)
6970

@@ -3127,6 +3128,25 @@ async def saveAs(self, path: typing.Union[str, pathlib.Path]) -> NoneType:
31273128
mapping.register(DownloadImpl, Download)
31283129

31293130

3131+
class Video(AsyncBase):
3132+
def __init__(self, obj: VideoImpl):
3133+
super().__init__(obj)
3134+
3135+
async def path(self) -> str:
3136+
"""Video.path
3137+
3138+
Returns the file system path this video will be recorded to. The video is guaranteed to be written to the filesystem upon closing the browser context.
3139+
3140+
Returns
3141+
-------
3142+
str
3143+
"""
3144+
return mapping.from_maybe_impl(await self._impl_obj.path())
3145+
3146+
3147+
mapping.register(VideoImpl, Video)
3148+
3149+
31303150
class BindingCall(AsyncBase):
31313151
def __init__(self, obj: BindingCallImpl):
31323152
super().__init__(obj)
@@ -3235,6 +3255,18 @@ def workers(self) -> typing.List["Worker"]:
32353255
"""
32363256
return mapping.from_impl_list(self._impl_obj.workers)
32373257

3258+
@property
3259+
def video(self) -> typing.Union["Video", NoneType]:
3260+
"""Page.video
3261+
3262+
Video object associated with this page.
3263+
3264+
Returns
3265+
-------
3266+
Optional[Video]
3267+
"""
3268+
return mapping.from_impl_nullable(self._impl_obj.video)
3269+
32383270
def remove_listener(self, event: str, f: typing.Any) -> NoneType:
32393271
return mapping.from_maybe_impl(
32403272
self._impl_obj.remove_listener(event=event, f=mapping.to_impl(f))

playwright/browser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ async def newContext(
103103
context = from_channel(channel)
104104
self._contexts.append(context)
105105
context._browser = self
106+
context._options = params
106107
return context
107108

108109
async def newPage(

playwright/browser_context.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def __init__(
5858
self._browser: Optional["Browser"] = None
5959
self._owner_page: Optional[Page] = None
6060
self._is_closed_or_closing = False
61+
self._options: Dict[str, Any] = {}
6162

6263
self._channel.on(
6364
"bindingCall",

playwright/browser_type.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ async def launchPersistentContext(
115115
params["extraHTTPHeaders"] = serialize_headers(extraHTTPHeaders)
116116
normalize_launch_params(params)
117117
try:
118-
return from_channel(
118+
context = from_channel(
119119
await self._channel.send("launchPersistentContext", params)
120120
)
121+
context._options = params
122+
return context
121123
except Exception as e:
122124
if f"{self.name}-" in str(e):
123125
raise not_installed_error(f'"{self.name}" browser was not found.')

playwright/page.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
serialize_argument,
6060
)
6161
from playwright.network import Request, Response, Route, serialize_headers
62+
from playwright.video import Video
6263
from playwright.wait_helper import WaitHelper
6364

6465
if sys.version_info >= (3, 8): # pragma: no cover
@@ -115,6 +116,7 @@ def __init__(
115116
self._routes: List[RouteHandlerEntry] = []
116117
self._owned_context: Optional["BrowserContext"] = None
117118
self._timeout_settings: TimeoutSettings = TimeoutSettings(None)
119+
self._video: Optional[Video] = None
118120

119121
self._channel.on(
120122
"bindingCall",
@@ -201,6 +203,12 @@ def __init__(
201203
from_channel(params["route"]), from_channel(params["request"])
202204
),
203205
)
206+
self._channel.on(
207+
"video",
208+
lambda params: cast(Video, self.video)._set_relative_path(
209+
params["relativePath"]
210+
),
211+
)
204212
self._channel.on(
205213
"worker", lambda params: self._on_worker(from_channel(params["worker"]))
206214
)
@@ -775,6 +783,16 @@ async def pdf(
775783
fd.write(decoded_binary)
776784
return decoded_binary
777785

786+
@property
787+
def video(
788+
self,
789+
) -> Optional[Video]:
790+
if not self._browser_context._options.get("videosPath"):
791+
return None
792+
if not self._video:
793+
self._video = Video(self)
794+
return self._video
795+
778796
def expect_event(
779797
self,
780798
event: str,

playwright/sync_api.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
from playwright.playwright import Playwright as PlaywrightImpl
6565
from playwright.selectors import Selectors as SelectorsImpl
6666
from playwright.sync_base import EventContextManager, SyncBase, mapping
67+
from playwright.video import Video as VideoImpl
6768

6869
NoneType = type(None)
6970

@@ -3255,6 +3256,25 @@ def saveAs(self, path: typing.Union[str, pathlib.Path]) -> NoneType:
32553256
mapping.register(DownloadImpl, Download)
32563257

32573258

3259+
class Video(SyncBase):
3260+
def __init__(self, obj: VideoImpl):
3261+
super().__init__(obj)
3262+
3263+
def path(self) -> str:
3264+
"""Video.path
3265+
3266+
Returns the file system path this video will be recorded to. The video is guaranteed to be written to the filesystem upon closing the browser context.
3267+
3268+
Returns
3269+
-------
3270+
str
3271+
"""
3272+
return mapping.from_maybe_impl(self._sync(self._impl_obj.path()))
3273+
3274+
3275+
mapping.register(VideoImpl, Video)
3276+
3277+
32583278
class BindingCall(SyncBase):
32593279
def __init__(self, obj: BindingCallImpl):
32603280
super().__init__(obj)
@@ -3363,6 +3383,18 @@ def workers(self) -> typing.List["Worker"]:
33633383
"""
33643384
return mapping.from_impl_list(self._impl_obj.workers)
33653385

3386+
@property
3387+
def video(self) -> typing.Union["Video", NoneType]:
3388+
"""Page.video
3389+
3390+
Video object associated with this page.
3391+
3392+
Returns
3393+
-------
3394+
Optional[Video]
3395+
"""
3396+
return mapping.from_impl_nullable(self._impl_obj.video)
3397+
33663398
def remove_listener(self, event: str, f: typing.Any) -> NoneType:
33673399
return mapping.from_maybe_impl(
33683400
self._impl_obj.remove_listener(event=event, f=mapping.to_impl(f))

playwright/video.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Copyright (c) Microsoft Corporation.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
from typing import TYPE_CHECKING, cast
17+
18+
if TYPE_CHECKING: # pragma: no cover
19+
from playwright.page import Page
20+
21+
22+
class Video:
23+
def __init__(self, page: "Page") -> None:
24+
self._loop = page._loop
25+
self._page = page
26+
self._path_future = page._loop.create_future()
27+
28+
async def path(self) -> str:
29+
return await self._path_future
30+
31+
def _set_relative_path(self, relative_path: str) -> None:
32+
self._path_future.set_result(
33+
os.path.join(
34+
cast(str, self._page._browser_context._options.get("videosPath")),
35+
relative_path,
36+
)
37+
)

scripts/generate_api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from playwright.page import BindingCall, Page, Worker
4444
from playwright.playwright import Playwright
4545
from playwright.selectors import Selectors
46+
from playwright.video import Video
4647

4748

4849
def process_type(value: Any, param: bool = False) -> str:
@@ -169,6 +170,7 @@ def return_value(value: Any) -> List[str]:
169170
from playwright.page import BindingCall as BindingCallImpl, Page as PageImpl, Worker as WorkerImpl
170171
from playwright.playwright import Playwright as PlaywrightImpl
171172
from playwright.selectors import Selectors as SelectorsImpl
173+
from playwright.video import Video as VideoImpl
172174
"""
173175

174176
all_types = [
@@ -187,6 +189,7 @@ def return_value(value: Any) -> List[str]:
187189
ConsoleMessage,
188190
Dialog,
189191
Download,
192+
Video,
190193
BindingCall,
191194
Page,
192195
BrowserContext,

tests/async/test_video.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright (c) Microsoft Corporation.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
17+
18+
async def test_should_expose_video_path(browser, tmpdir, server):
19+
page = await browser.newPage(videosPath=str(tmpdir))
20+
await page.goto(server.PREFIX + "/grid.html")
21+
path = await page.video.path()
22+
assert str(tmpdir) in path
23+
await page.context.close()
24+
25+
26+
async def test_short_video_should_exist(browser, tmpdir, server):
27+
page = await browser.newPage(videosPath=str(tmpdir))
28+
await page.goto(server.PREFIX + "/grid.html")
29+
path = await page.video.path()
30+
assert str(tmpdir) in path
31+
await page.context.close()
32+
assert os.path.exists(path)

tests/sync/test_video.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright (c) Microsoft Corporation.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
17+
18+
def test_should_expose_video_path(browser, tmpdir, server):
19+
page = browser.newPage(videosPath=str(tmpdir))
20+
page.goto(server.PREFIX + "/grid.html")
21+
path = page.video.path()
22+
assert str(tmpdir) in path
23+
page.context.close()
24+
25+
26+
def test_video_should_exist(browser, tmpdir, server):
27+
page = browser.newPage(videosPath=str(tmpdir))
28+
page.goto(server.PREFIX + "/grid.html")
29+
path = page.video.path()
30+
assert str(tmpdir) in path
31+
page.context.close()
32+
assert os.path.exists(path)

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