22from abc import ABC , abstractmethod
33from functools import partial
44from random import randint
5- from typing import Any , Callable , List , Optional , TypeVar
5+ from typing import Any , Callable , Optional , TypeVar
66
77from pydoll .browser .interfaces import BrowserOptionsManager
88from pydoll .browser .managers import (
2222from pydoll .constants import (
2323 AuthChallengeResponseValues ,
2424 DownloadBehavior ,
25+ NetworkErrorReason ,
2526 PermissionType ,
2627)
2728from pydoll .exceptions import BrowserNotRunning , FailedToStartBrowser , NoValidTabFound
3334)
3435from pydoll .protocol .browser .types import WindowBoundsDict
3536from pydoll .protocol .fetch .events import FetchEvent
37+ from pydoll .protocol .fetch .types import HeaderEntry
3638from pydoll .protocol .network .types import Cookie , CookieParam , RequestPausedEvent
3739from pydoll .protocol .storage .responses import GetCookiesResponse
3840from pydoll .protocol .target .responses import (
@@ -70,6 +72,7 @@ def __init__(
7072 Note:
7173 Call start() to actually launch the browser.
7274 """
75+ self ._validate_connection_port (connection_port )
7376 self .options = options_manager .initialize_options ()
7477 self ._proxy_manager = ProxyManager (self .options )
7578 self ._connection_port = connection_port if connection_port else randint (9223 , 9322 )
@@ -178,7 +181,7 @@ async def delete_browser_context(self, browser_context_id: str):
178181 TargetCommands .dispose_browser_context (browser_context_id )
179182 )
180183
181- async def get_browser_contexts (self ) -> List [str ]:
184+ async def get_browser_contexts (self ) -> list [str ]:
182185 """Get all browser context IDs including the default context."""
183186 response : GetBrowserContextsResponse = await self ._execute_command (
184187 TargetCommands .get_browser_contexts ()
@@ -205,7 +208,7 @@ async def new_tab(self, url: str = '', browser_context_id: Optional[str] = None)
205208 target_id = response ['result' ]['targetId' ]
206209 return Tab (self , self ._connection_port , target_id , browser_context_id )
207210
208- async def get_targets (self ) -> List [TargetInfo ]:
211+ async def get_targets (self ) -> list [TargetInfo ]:
209212 """
210213 Get all active targets/pages in browser.
211214
@@ -248,12 +251,12 @@ async def delete_all_cookies(self, browser_context_id: Optional[str] = None):
248251 return await self ._execute_command (StorageCommands .clear_cookies (browser_context_id ))
249252
250253 async def set_cookies (
251- self , cookies : List [CookieParam ], browser_context_id : Optional [str ] = None
254+ self , cookies : list [CookieParam ], browser_context_id : Optional [str ] = None
252255 ):
253256 """Set multiple cookies in browser or context."""
254257 return await self ._execute_command (StorageCommands .set_cookies (cookies , browser_context_id ))
255258
256- async def get_cookies (self , browser_context_id : Optional [str ] = None ) -> List [Cookie ]:
259+ async def get_cookies (self , browser_context_id : Optional [str ] = None ) -> list [Cookie ]:
257260 """Get all cookies from browser or context."""
258261 response : GetCookiesResponse = await self ._execute_command (
259262 StorageCommands .get_cookies (browser_context_id )
@@ -310,7 +313,7 @@ async def set_window_bounds(self, bounds: WindowBoundsDict):
310313
311314 async def grant_permissions (
312315 self ,
313- permissions : List [PermissionType ],
316+ permissions : list [PermissionType ],
314317 origin : Optional [str ] = None ,
315318 browser_context_id : Optional [str ] = None ,
316319 ):
@@ -401,6 +404,33 @@ async def continue_request(self, request_id: str):
401404 """
402405 return await self ._execute_command (FetchCommands .continue_request (request_id ))
403406
407+ async def fail_request (self , request_id : str , error_reason : NetworkErrorReason ):
408+ """Fail request with error code."""
409+ return await self ._execute_command (FetchCommands .fail_request (request_id , error_reason ))
410+
411+ async def fulfill_request (
412+ self ,
413+ request_id : str ,
414+ response_code : int ,
415+ response_headers : list [HeaderEntry ],
416+ response_body : dict [Any , Any ],
417+ ):
418+ """Fulfill request with response data."""
419+ return await self ._execute_command (
420+ FetchCommands .fulfill_request (
421+ request_id ,
422+ response_code ,
423+ response_headers ,
424+ response_body ,
425+ )
426+ )
427+
428+ @staticmethod
429+ def _validate_connection_port (connection_port : Optional [int ]):
430+ """Validate connection port."""
431+ if connection_port and connection_port < 0 :
432+ raise ValueError ('Connection port must be a positive integer' )
433+
404434 async def _continue_request_callback (self , event : RequestPausedEvent ):
405435 """Internal callback to continue paused requests."""
406436 request_id = event ['params' ]['requestId' ]
@@ -461,7 +491,7 @@ def _is_valid_tab(target: TargetInfo) -> bool:
461491 return target .get ('type' ) == 'page' and 'chrome-extension://' not in target .get ('url' , '' )
462492
463493 @staticmethod
464- async def _get_valid_tab_id (targets : List [TargetInfo ]) -> str :
494+ async def _get_valid_tab_id (targets : list [TargetInfo ]) -> str :
465495 """
466496 Find valid attached tab ID.
467497
0 commit comments