SilentWraith commited on
Commit
1c16d86
·
verified ·
1 Parent(s): efd4911

Update app/core/service/playwright/playwright_context.py

Browse files
app/core/service/playwright/playwright_context.py CHANGED
@@ -14,19 +14,22 @@ from .models import GetContentModel, PageModel, ScreenshotModel # noqa: TCH001
14
 
15
 
16
  class AsyncMixin:
17
- """experimental: making awaitable class."""
18
 
19
- async def ainit(self) -> None:
20
- pass
21
 
22
  def __await__(self) -> AsyncIterator[Awaitable]:
23
- return self.ainit().__await__()
 
24
 
25
 
26
  class PlaywrightInstance(AsyncMixin):
27
  """This class is designed to keep playwright browser instance open for reusability and scalability handling api requests.""" # noqa: E501
28
 
29
- HEADERS: str = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" # noqa: E501
 
 
30
 
31
  FIREFOX_USER_PREFS: ClassVar[dict[str, int | str]] = {
32
  "extensions.enabledScopes": 1,
@@ -37,11 +40,11 @@ class PlaywrightInstance(AsyncMixin):
37
  }
38
 
39
  def __init__(self) -> None:
40
- self.playwright: async_playwright = None
41
- self.browser: Browser = None
 
42
 
43
- async def ainit(self) -> PlaywrightInstance:
44
- """starts playwright and browser instance."""
45
  if not self.playwright:
46
  self.playwright = await async_playwright().start()
47
  self.browser = await self.playwright.firefox.launch(
@@ -54,7 +57,7 @@ class PlaywrightInstance(AsyncMixin):
54
  browser: Browser,
55
  screenshot_model: GetContentModel,
56
  page_model: PageModel,
57
- ) -> tuple[BrowserContext, Page]:
58
  """create a brwoser or new browser context page.
59
 
60
  Parameters:
@@ -73,11 +76,11 @@ class PlaywrightInstance(AsyncMixin):
73
  "java_script_enabled": page_model.java_script_enabled,
74
  "no_viewport": page_model.no_viewport,
75
  "proxy": page_model.proxy.model_dump() if page_model.proxy else None,
76
- "viewport": page_model.viewport.model_dump() if page_model.viewport else None,
77
  }
78
 
79
  if not screenshot_model.new_browser:
80
- return None, await self.browser.new_page(**params)
81
 
82
  new_context = await browser.new_context(**params)
83
  return new_context, await new_context.new_page()
@@ -87,24 +90,39 @@ class PlaywrightInstance(AsyncMixin):
87
  screenshot_model: ScreenshotModel,
88
  page_model: PageModel,
89
  ) -> bytes:
 
 
 
 
 
 
 
 
 
 
 
90
  context, page = await self.new_context_page(
91
- screenshot_model=screenshot_model, browser=self.browser, page_model=page_model,
 
 
92
  )
93
 
94
  await page.goto(str(screenshot_model.url))
95
-
96
  await page.wait_for_timeout(screenshot_model.ms_delay)
97
-
98
  screenshot_locator = (
99
  page.locator(screenshot_model.query_selector)
100
  if screenshot_model.query_selector
101
- else None
102
  )
103
 
104
  if screenshot_locator:
105
- screenshot_data: bytes = await screenshot_locator.screenshot()
 
 
106
  else:
107
- screenshot_data: bytes = await page.screenshot(full_page=screenshot_model.full_page)
 
 
108
 
109
  await page.close()
110
 
@@ -114,7 +132,7 @@ class PlaywrightInstance(AsyncMixin):
114
  return screenshot_data
115
 
116
  async def close_instance(self) -> None:
117
- """for manual closing of playwright if needed"""
118
  if self.playwright:
119
  await self.browser.close()
120
  await self.playwright.stop()
 
14
 
15
 
16
  class AsyncMixin:
17
+ """Experimental: making awaitable class."""
18
 
19
+ async def __ainit__(self) -> None:
20
+ """Initialize the class."""
21
 
22
  def __await__(self) -> AsyncIterator[Awaitable]:
23
+ """Make the class awaitable."""
24
+ return self.__ainit__().__await__()
25
 
26
 
27
  class PlaywrightInstance(AsyncMixin):
28
  """This class is designed to keep playwright browser instance open for reusability and scalability handling api requests.""" # noqa: E501
29
 
30
+ HEADERS: ClassVar[str] = (
31
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" # noqa: E501
32
+ )
33
 
34
  FIREFOX_USER_PREFS: ClassVar[dict[str, int | str]] = {
35
  "extensions.enabledScopes": 1,
 
40
  }
41
 
42
  def __init__(self) -> None:
43
+ """Initialize the class."""
44
+ self.playwright: async_playwright | None = None
45
+ self.browser: Browser | None = None
46
 
47
+ async def __ainit__(self) -> PlaywrightInstance:
 
48
  if not self.playwright:
49
  self.playwright = await async_playwright().start()
50
  self.browser = await self.playwright.firefox.launch(
 
57
  browser: Browser,
58
  screenshot_model: GetContentModel,
59
  page_model: PageModel,
60
+ ) -> tuple[BrowserContext | None, Page]:
61
  """create a brwoser or new browser context page.
62
 
63
  Parameters:
 
76
  "java_script_enabled": page_model.java_script_enabled,
77
  "no_viewport": page_model.no_viewport,
78
  "proxy": page_model.proxy.model_dump() if page_model.proxy else None,
79
+ "viewport": page_model.viewport,
80
  }
81
 
82
  if not screenshot_model.new_browser:
83
+ return None, await browser.new_page(**params)
84
 
85
  new_context = await browser.new_context(**params)
86
  return new_context, await new_context.new_page()
 
90
  screenshot_model: ScreenshotModel,
91
  page_model: PageModel,
92
  ) -> bytes:
93
+ """Take a screenshot of a webpage url.
94
+
95
+ Parameters:
96
+ screenshot_model (ScreenshotModel):
97
+ A pydantic BaseModel instance containing the configuration for the screenshot.
98
+ page_model (PageModel):
99
+ A pydantic BaseModel instance containing the configuration for the page.
100
+
101
+ Returns:
102
+ bytes: The screenshot data in bytes.
103
+ """
104
  context, page = await self.new_context_page(
105
+ screenshot_model=screenshot_model,
106
+ browser=self.browser,
107
+ page_model=page_model,
108
  )
109
 
110
  await page.goto(str(screenshot_model.url))
 
111
  await page.wait_for_timeout(screenshot_model.ms_delay)
 
112
  screenshot_locator = (
113
  page.locator(screenshot_model.query_selector)
114
  if screenshot_model.query_selector
115
+ else None,
116
  )
117
 
118
  if screenshot_locator:
119
+ screenshot_data: bytes = await screenshot_locator.screenshot(
120
+ type=screenshot_model.image_type
121
+ )
122
  else:
123
+ screenshot_data: bytes = await page.screenshot(
124
+ full_page=screenshot_model.full_page, type=screenshot_model.image_type
125
+ )
126
 
127
  await page.close()
128
 
 
132
  return screenshot_data
133
 
134
  async def close_instance(self) -> None:
135
+ """For manual closing of playwright if needed."""
136
  if self.playwright:
137
  await self.browser.close()
138
  await self.playwright.stop()