Skip to content

Commit

Permalink
Type hinting and documentation improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Xewdy444 committed Nov 27, 2023
1 parent 56725bb commit 894a0bd
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 33 deletions.
26 changes: 14 additions & 12 deletions playwright_recaptcha/recaptchav2/async_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
from concurrent.futures import ThreadPoolExecutor
from io import BytesIO
from json import JSONDecodeError
from typing import Any, BinaryIO, Dict, Iterable, Optional, Union
from typing import Any, BinaryIO, Dict, Iterable, List, Optional, Union

import speech_recognition
from playwright.async_api import APIResponse, Page, Response
from playwright.async_api import APIResponse, Locator, Page, Response
from pydub import AudioSegment
from tenacity import (
AsyncRetrying,
Expand All @@ -36,31 +36,33 @@ class AsyncAudioFile(speech_recognition.AudioFile):
Parameters
----------
file : BinaryIO
The audio file.
file : Union[BinaryIO, str]
The audio file handle or file path.
executor : Optional[ThreadPoolExecutor], optional
The thread pool executor to use, by default None.
"""

def __init__(
self, file: BinaryIO, *, executor: Optional[ThreadPoolExecutor] = None
self,
file: Union[BinaryIO, str],
*,
executor: Optional[ThreadPoolExecutor] = None,
) -> None:
super().__init__(file)
self._loop = asyncio.get_event_loop()
self._executor = executor

async def __aenter__(self) -> AsyncAudioFile:
loop = asyncio.get_event_loop()
await loop.run_in_executor(self._executor, super().__enter__)
await self._loop.run_in_executor(self._executor, super().__enter__)
return self

async def __aexit__(self, *args: Any) -> None:
loop = asyncio.get_event_loop()
await loop.run_in_executor(self._executor, super().__exit__, *args)
await self._loop.run_in_executor(self._executor, super().__exit__, *args)


class AsyncSolver:
"""
A class used to solve reCAPTCHA v2 asynchronously.
A class for solving reCAPTCHA v2 asynchronously with Playwright.
Parameters
----------
Expand Down Expand Up @@ -94,7 +96,7 @@ def __repr__(self) -> str:
async def __aenter__(self) -> AsyncSolver:
return self

async def __aexit__(self, *args: Any) -> None:
async def __aexit__(self, *_: Any) -> None:
self.close()

@staticmethod
Expand Down Expand Up @@ -258,7 +260,7 @@ async def _solve_tiles(
CapSolverError
If the CapSolver API returned an error.
"""
changing_tiles = []
changing_tiles: List[Locator] = []

for index in indexes:
tile = recaptcha_box.tile_selector.nth(index)
Expand Down
6 changes: 4 additions & 2 deletions playwright_recaptcha/recaptchav2/recaptcha_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ def _get_recaptcha_frame_pairs(
frame_id = anchor_frame.name[2:]

for bframe_frame in bframe_frames:
if frame_id in bframe_frame.name:
frame_pairs.append((anchor_frame, bframe_frame))
if frame_id not in bframe_frame.name:
continue

frame_pairs.append((anchor_frame, bframe_frame))

if not frame_pairs:
raise RecaptchaNotFoundError
Expand Down
10 changes: 5 additions & 5 deletions playwright_recaptcha/recaptchav2/sync_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import re
from io import BytesIO
from json import JSONDecodeError
from typing import Any, Dict, Iterable, Optional, Union
from typing import Any, Dict, Iterable, List, Optional, Union

import speech_recognition
from playwright.sync_api import APIResponse, Page, Response
from playwright.sync_api import APIResponse, Locator, Page, Response
from pydub import AudioSegment
from tenacity import Retrying, retry_if_exception_type, stop_after_delay, wait_fixed

Expand All @@ -24,7 +24,7 @@

class SyncSolver:
"""
A class used to solve reCAPTCHA v2 synchronously.
A class for solving reCAPTCHA v2 synchronously with Playwright.
Parameters
----------
Expand Down Expand Up @@ -58,7 +58,7 @@ def __repr__(self) -> str:
def __enter__(self) -> SyncSolver:
return self

def __exit__(self, *args: Any) -> None:
def __exit__(self, *_: Any) -> None:
self.close()

@staticmethod
Expand Down Expand Up @@ -222,7 +222,7 @@ def _solve_tiles(
CapSolverError
If the CapSolver API returned an error.
"""
changing_tiles = []
changing_tiles: List[Locator] = []

for index in indexes:
tile = recaptcha_box.tile_selector.nth(index)
Expand Down
14 changes: 7 additions & 7 deletions playwright_recaptcha/recaptchav3/async_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

class AsyncSolver:
"""
A class used to solve reCAPTCHA v3 asynchronously.
A class for solving reCAPTCHA v3 asynchronously with Playwright.
Parameters
----------
Expand All @@ -26,25 +26,25 @@ def __init__(self, page: Page, timeout: int = 30) -> None:
self._timeout = timeout

self._token: Optional[str] = None
self._page.on("response", self._extract_token)
self._page.on("response", self._response_callback)

def __repr__(self) -> str:
return f"AsyncSolver(page={self._page!r}, timeout={self._timeout!r})"

async def __aenter__(self) -> AsyncSolver:
return self

async def __aexit__(self, *args: Any) -> None:
async def __aexit__(self, *_: Any) -> None:
self.close()

async def _extract_token(self, response: Response) -> None:
async def _response_callback(self, response: Response) -> None:
"""
Extract the `g-recaptcha-response` token from the reload response.
The callback for intercepting reload responses.
Parameters
----------
response : Response
The response to extract the `g-recaptcha-response` token from.
The response.
"""
if re.search("/recaptcha/(api2|enterprise)/reload", response.url) is None:
return
Expand All @@ -57,7 +57,7 @@ async def _extract_token(self, response: Response) -> None:
def close(self) -> None:
"""Remove the reload response listener."""
try:
self._page.remove_listener("response", self._extract_token)
self._page.remove_listener("response", self._response_callback)
except KeyError:
pass

Expand Down
14 changes: 7 additions & 7 deletions playwright_recaptcha/recaptchav3/sync_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

class SyncSolver:
"""
A class used to solve reCAPTCHA v3 synchronously.
A class for solving reCAPTCHA v3 synchronously with Playwright.
Parameters
----------
Expand All @@ -26,25 +26,25 @@ def __init__(self, page: Page, timeout: int = 30) -> None:
self._timeout = timeout

self._token: Optional[str] = None
self._page.on("response", self._extract_token)
self._page.on("response", self._response_callback)

def __repr__(self) -> str:
return f"SyncSolver(page={self._page!r}, timeout={self._timeout!r})"

def __enter__(self) -> SyncSolver:
return self

def __exit__(self, *args: Any) -> None:
def __exit__(self, *_: Any) -> None:
self.close()

def _extract_token(self, response: Response) -> None:
def _response_callback(self, response: Response) -> None:
"""
Extract the `g-recaptcha-response` token from the reload response.
The callback for intercepting reload responses.
Parameters
----------
response : Response
The response to extract the `g-recaptcha-response` token from.
The response.
"""
if re.search("/recaptcha/(api2|enterprise)/reload", response.url) is None:
return
Expand All @@ -57,7 +57,7 @@ def _extract_token(self, response: Response) -> None:
def close(self) -> None:
"""Remove the reload response listener."""
try:
self._page.remove_listener("response", self._extract_token)
self._page.remove_listener("response", self._response_callback)
except KeyError:
pass

Expand Down

0 comments on commit 894a0bd

Please sign in to comment.