pydoll-python 1.3.0__tar.gz → 1.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/PKG-INFO +1 -1
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/browser/base.py +50 -6
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/browser/chrome.py +10 -5
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/browser/managers.py +7 -5
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/browser/page.py +2 -1
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/browser.py +19 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pyproject.toml +1 -1
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/LICENSE +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/README.md +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/__init__.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/browser/__init__.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/browser/options.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/__init__.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/dom.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/fetch.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/input.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/network.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/page.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/runtime.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/storage.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/commands/target.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/connection/__init__.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/connection/connection.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/connection/managers.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/constants.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/element.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/events/__init__.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/events/browser.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/events/dom.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/events/fetch.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/events/network.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/events/page.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/exceptions.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/mixins/__init__.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/mixins/find_elements.py +0 -0
- {pydoll_python-1.3.0 → pydoll_python-1.3.2}/pydoll/utils.py +0 -0
|
@@ -77,7 +77,9 @@ class Browser(ABC): # noqa: PLR0904
|
|
|
77
77
|
exc_val: The exception value, if raised.
|
|
78
78
|
exc_tb: The traceback, if an exception was raised.
|
|
79
79
|
"""
|
|
80
|
-
await self.
|
|
80
|
+
if await self._is_browser_running():
|
|
81
|
+
await self.stop()
|
|
82
|
+
|
|
81
83
|
await self._connection_handler.close()
|
|
82
84
|
|
|
83
85
|
async def start(self) -> None:
|
|
@@ -137,6 +139,7 @@ class Browser(ABC): # noqa: PLR0904
|
|
|
137
139
|
page_id = (
|
|
138
140
|
await self.new_page() if not self._pages else self._pages.pop()
|
|
139
141
|
)
|
|
142
|
+
|
|
140
143
|
return Page(self._connection_port, page_id)
|
|
141
144
|
|
|
142
145
|
async def delete_all_cookies(self):
|
|
@@ -243,10 +246,25 @@ class Browser(ABC): # noqa: PLR0904
|
|
|
243
246
|
Retrieves the ID of the current browser window.
|
|
244
247
|
|
|
245
248
|
Returns:
|
|
246
|
-
|
|
249
|
+
int: The ID of the current browser window.
|
|
250
|
+
|
|
251
|
+
Raises:
|
|
252
|
+
RuntimeError: If unable to retrieve the window ID.
|
|
247
253
|
"""
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
command = BrowserCommands.get_window_id()
|
|
255
|
+
response = await self._execute_command(command)
|
|
256
|
+
|
|
257
|
+
if response.get('error'):
|
|
258
|
+
pages = await self.get_targets()
|
|
259
|
+
target_id = await self._get_valid_target_id(pages)
|
|
260
|
+
response = await self._execute_command(
|
|
261
|
+
BrowserCommands.get_window_id_by_target(target_id)
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
if window_id := response.get('result', {}).get('windowId'):
|
|
265
|
+
return window_id
|
|
266
|
+
|
|
267
|
+
raise RuntimeError(response.get('error', {}))
|
|
250
268
|
|
|
251
269
|
async def set_window_bounds(self, bounds: dict):
|
|
252
270
|
"""
|
|
@@ -519,7 +537,7 @@ class Browser(ABC): # noqa: PLR0904
|
|
|
519
537
|
'url', ''
|
|
520
538
|
)
|
|
521
539
|
|
|
522
|
-
async def _get_valid_page(self, pages) -> str:
|
|
540
|
+
async def _get_valid_page(self, pages: list) -> str:
|
|
523
541
|
"""
|
|
524
542
|
Gets the ID of a valid page or creates a new one.
|
|
525
543
|
|
|
@@ -541,6 +559,31 @@ class Browser(ABC): # noqa: PLR0904
|
|
|
541
559
|
|
|
542
560
|
return await self.new_page()
|
|
543
561
|
|
|
562
|
+
@staticmethod
|
|
563
|
+
async def _get_valid_target_id(pages: list) -> str:
|
|
564
|
+
"""
|
|
565
|
+
Retrieves the target ID of a valid attached browser page.
|
|
566
|
+
|
|
567
|
+
Returns:
|
|
568
|
+
str: The target ID of a valid page.
|
|
569
|
+
|
|
570
|
+
"""
|
|
571
|
+
|
|
572
|
+
valid_page = next(
|
|
573
|
+
(page for page in pages
|
|
574
|
+
if page.get('type') == 'page' and page.get('attached')),
|
|
575
|
+
None
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
if not valid_page:
|
|
579
|
+
raise RuntimeError("No valid attached browser page found.")
|
|
580
|
+
|
|
581
|
+
target_id = valid_page.get('targetId')
|
|
582
|
+
if not target_id:
|
|
583
|
+
raise RuntimeError("Valid page found but missing 'targetId'.")
|
|
584
|
+
|
|
585
|
+
return target_id
|
|
586
|
+
|
|
544
587
|
async def _is_browser_running(self, timeout: int = 10) -> bool:
|
|
545
588
|
"""
|
|
546
589
|
Checks if the browser process is currently running.
|
|
@@ -553,9 +596,10 @@ class Browser(ABC): # noqa: PLR0904
|
|
|
553
596
|
if await self._connection_handler.ping():
|
|
554
597
|
return True
|
|
555
598
|
await asyncio.sleep(1)
|
|
599
|
+
|
|
556
600
|
return False
|
|
557
601
|
|
|
558
|
-
async def _execute_command(self, command:
|
|
602
|
+
async def _execute_command(self, command: dict):
|
|
559
603
|
"""
|
|
560
604
|
Executes a command through the connection handler.
|
|
561
605
|
|
|
@@ -46,13 +46,18 @@ class Chrome(Browser):
|
|
|
46
46
|
the browser executable is not found at the default location.
|
|
47
47
|
"""
|
|
48
48
|
os_name = platform.system()
|
|
49
|
+
|
|
49
50
|
browser_paths = {
|
|
50
|
-
'Windows':
|
|
51
|
+
'Windows': [
|
|
51
52
|
r'C:\Program Files\Google\Chrome\Application\chrome.exe',
|
|
52
|
-
|
|
53
|
+
r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe',
|
|
54
|
+
],
|
|
55
|
+
'Linux': [
|
|
53
56
|
'/usr/bin/google-chrome',
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
],
|
|
58
|
+
'Darwin': [
|
|
59
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
60
|
+
]
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
browser_path = browser_paths.get(os_name)
|
|
@@ -60,6 +65,6 @@ class Chrome(Browser):
|
|
|
60
65
|
if not browser_path:
|
|
61
66
|
raise ValueError('Unsupported OS')
|
|
62
67
|
|
|
63
|
-
return BrowserOptionsManager.
|
|
68
|
+
return BrowserOptionsManager.validate_browser_paths(
|
|
64
69
|
browser_path
|
|
65
70
|
)
|
|
@@ -275,7 +275,7 @@ class BrowserOptionsManager:
|
|
|
275
275
|
options.arguments.append('--no-default-browser-check')
|
|
276
276
|
|
|
277
277
|
@staticmethod
|
|
278
|
-
def
|
|
278
|
+
def validate_browser_paths(paths: list[str]) -> str:
|
|
279
279
|
"""
|
|
280
280
|
Validates the provided browser executable path.
|
|
281
281
|
|
|
@@ -283,7 +283,8 @@ class BrowserOptionsManager:
|
|
|
283
283
|
the specified path.
|
|
284
284
|
|
|
285
285
|
Args:
|
|
286
|
-
|
|
286
|
+
paths (list[str]): Lista de caminhos possíveis do navegador.
|
|
287
|
+
|
|
287
288
|
|
|
288
289
|
Returns:
|
|
289
290
|
str: The validated browser path if it exists.
|
|
@@ -291,6 +292,7 @@ class BrowserOptionsManager:
|
|
|
291
292
|
Raises:
|
|
292
293
|
ValueError: If the browser executable is not found at the path.
|
|
293
294
|
"""
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
for path in paths:
|
|
296
|
+
if os.path.exists(path) and os.access(path, os.X_OK):
|
|
297
|
+
return path
|
|
298
|
+
raise ValueError(f"No valid browser path found in: {paths}")
|
|
@@ -157,6 +157,7 @@ class Page(FindElementsMixin): # noqa: PLR0904
|
|
|
157
157
|
"""
|
|
158
158
|
if self._connection_handler.dialog:
|
|
159
159
|
return True
|
|
160
|
+
|
|
160
161
|
return False
|
|
161
162
|
|
|
162
163
|
async def get_dialog_message(self) -> str:
|
|
@@ -256,7 +257,7 @@ class Page(FindElementsMixin): # noqa: PLR0904
|
|
|
256
257
|
# TODO: remove the duplicated logic
|
|
257
258
|
"""
|
|
258
259
|
response = await self._execute_command(PageCommands.screenshot())
|
|
259
|
-
return response['result']['data']
|
|
260
|
+
return response['result']['data']
|
|
260
261
|
|
|
261
262
|
async def set_download_path(self, path: str):
|
|
262
263
|
"""
|
|
@@ -17,6 +17,10 @@ class BrowserCommands:
|
|
|
17
17
|
|
|
18
18
|
CLOSE = {'method': 'Browser.close'}
|
|
19
19
|
GET_WINDOW_ID = {'method': 'Browser.WindowID'}
|
|
20
|
+
GET_WINDOW_ID_BY_TARGET = {
|
|
21
|
+
'method': 'Browser.getWindowForTarget',
|
|
22
|
+
'params': {},
|
|
23
|
+
}
|
|
20
24
|
SET_WINDOW_BOUNDS_TEMPLATE = {
|
|
21
25
|
'method': 'Browser.setWindowBounds',
|
|
22
26
|
'params': {},
|
|
@@ -62,6 +66,21 @@ class BrowserCommands:
|
|
|
62
66
|
"""
|
|
63
67
|
return cls.GET_WINDOW_ID
|
|
64
68
|
|
|
69
|
+
@classmethod
|
|
70
|
+
def get_window_id_by_target(cls, target_id: str) -> dict:
|
|
71
|
+
"""
|
|
72
|
+
Generates the command to get the ID of the current window.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
target_id (str): The target_id to set for the window.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
dict: The command to be sent to the browser.
|
|
79
|
+
"""
|
|
80
|
+
command = cls.GET_WINDOW_ID_BY_TARGET.copy()
|
|
81
|
+
command['params']['targetId'] = target_id
|
|
82
|
+
return command
|
|
83
|
+
|
|
65
84
|
@classmethod
|
|
66
85
|
def set_window_bounds(cls, window_id: int, bounds: dict) -> dict:
|
|
67
86
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|