pydoll-python 2.9.2__tar.gz → 2.10.0__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.
Files changed (88) hide show
  1. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/PKG-INFO +24 -7
  2. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/README.md +23 -6
  3. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/chromium/base.py +42 -27
  4. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/chromium/chrome.py +6 -2
  5. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/chromium/edge.py +6 -2
  6. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/managers/browser_options_manager.py +7 -2
  7. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/managers/proxy_manager.py +5 -2
  8. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/requests/request.py +19 -17
  9. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/requests/response.py +8 -11
  10. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/tab.py +74 -34
  11. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/browser_commands.py +42 -34
  12. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/dom_commands.py +69 -58
  13. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/fetch_commands.py +30 -24
  14. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/input_commands.py +33 -27
  15. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/network_commands.py +47 -41
  16. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/page_commands.py +65 -57
  17. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/runtime_commands.py +26 -20
  18. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/storage_commands.py +46 -42
  19. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/target_commands.py +23 -17
  20. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/connection/connection_handler.py +11 -12
  21. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/connection/managers/commands_manager.py +5 -1
  22. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/connection/managers/events_manager.py +12 -8
  23. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/constants.py +88 -0
  24. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/elements/mixins/find_elements_mixin.py +37 -29
  25. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/elements/web_element.py +80 -25
  26. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/exceptions.py +12 -0
  27. pydoll_python-2.10.0/pydoll/interactions/__init__.py +3 -0
  28. pydoll_python-2.10.0/pydoll/interactions/scroll.py +121 -0
  29. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pyproject.toml +1 -1
  30. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/LICENSE +0 -0
  31. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/__init__.py +0 -0
  32. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/__init__.py +0 -0
  33. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/chromium/__init__.py +0 -0
  34. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/interfaces.py +0 -0
  35. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/managers/__init__.py +0 -0
  36. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/managers/browser_process_manager.py +0 -0
  37. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/managers/temp_dir_manager.py +0 -0
  38. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/options.py +0 -0
  39. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/browser/requests/__init__.py +0 -0
  40. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/commands/__init__.py +0 -0
  41. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/connection/__init__.py +0 -0
  42. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/connection/managers/__init__.py +0 -0
  43. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/elements/__init__.py +0 -0
  44. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/elements/mixins/__init__.py +0 -0
  45. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/__init__.py +0 -0
  46. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/base.py +0 -0
  47. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/browser/__init__.py +0 -0
  48. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/browser/events.py +0 -0
  49. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/browser/methods.py +0 -0
  50. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/browser/types.py +0 -0
  51. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/debugger/types.py +0 -0
  52. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/dom/__init__.py +0 -0
  53. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/dom/events.py +0 -0
  54. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/dom/methods.py +0 -0
  55. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/dom/types.py +0 -0
  56. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/emulation/types.py +0 -0
  57. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/fetch/__init__.py +0 -0
  58. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/fetch/events.py +0 -0
  59. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/fetch/methods.py +0 -0
  60. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/fetch/types.py +0 -0
  61. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/input/__init__.py +0 -0
  62. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/input/events.py +0 -0
  63. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/input/methods.py +0 -0
  64. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/input/types.py +0 -0
  65. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/io/types.py +0 -0
  66. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/network/__init__.py +0 -0
  67. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/network/events.py +0 -0
  68. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/network/methods.py +0 -0
  69. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/network/types.py +0 -0
  70. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/page/__init__.py +0 -0
  71. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/page/events.py +0 -0
  72. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/page/methods.py +0 -0
  73. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/page/types.py +0 -0
  74. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/runtime/__init__.py +0 -0
  75. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/runtime/events.py +0 -0
  76. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/runtime/methods.py +0 -0
  77. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/runtime/types.py +0 -0
  78. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/security/types.py +0 -0
  79. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/storage/__init__.py +0 -0
  80. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/storage/events.py +0 -0
  81. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/storage/methods.py +0 -0
  82. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/storage/types.py +0 -0
  83. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/target/__init__.py +0 -0
  84. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/target/events.py +0 -0
  85. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/target/methods.py +0 -0
  86. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/protocol/target/types.py +0 -0
  87. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/py.typed +0 -0
  88. {pydoll_python-2.9.2 → pydoll_python-2.10.0}/pydoll/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydoll-python
3
- Version: 2.9.2
3
+ Version: 2.10.0
4
4
  Summary: Pydoll is a library for automating chromium-based browsers without a WebDriver, offering realistic interactions.
5
5
  License-File: LICENSE
6
6
  Author: Thalison Fernandes
@@ -19,7 +19,7 @@ Requires-Dist: websockets (>=14,<15)
19
19
  Description-Content-Type: text/markdown
20
20
 
21
21
  <p align="center">
22
- <img src="https://github.com/user-attachments/assets/219f2dbc-37ed-4aea-a289-ba39cdbb335d" alt="Pydoll Logo" /> <br>
22
+ <img src="https://github.com/user-attachments/assets/2c380638-b04a-4b04-b1c8-2958e4237a94" alt="Pydoll Logo" /> <br>
23
23
  </p>
24
24
  <h1 align="center">Pydoll: scraping, the easier way</h1>
25
25
 
@@ -52,11 +52,6 @@ Built from scratch with a different philosophy, Pydoll connects directly to the
52
52
 
53
53
  We believe that powerful automation shouldn't require you to become an expert in configuration or constantly fight with bot protection systems. With Pydoll, you can focus on what really matters: your automation logic, not the underlying complexity or protection systems.
54
54
 
55
- <div>
56
- <h4>Be a good human. Give it a star ⭐</h4>
57
- No stars, no bugs fixed. Just kidding (maybe)
58
- </div>
59
-
60
55
  ## 🌟 What makes Pydoll special?
61
56
 
62
57
  - **Zero Webdrivers**: Say goodbye to webdriver compatibility issues
@@ -65,6 +60,28 @@ We believe that powerful automation shouldn't require you to become an expert in
65
60
  - **Humanized Interactions**: Mimic real user behavior
66
61
  - **Simplicity**: With Pydoll, you install and you're ready to automate.
67
62
 
63
+ ## 🆕 What's New
64
+
65
+ ### Human-Like Page Scrolling: Scroll Like a Real User!
66
+
67
+ Now you can control page scrolling with smooth animations and automatic completion waiting:
68
+
69
+ ```python
70
+ from pydoll.constants import ScrollPosition
71
+
72
+ # Scroll down with smooth animation (waits for completion)
73
+ await tab.scroll.by(ScrollPosition.DOWN, 500, smooth=True)
74
+
75
+ # Navigate to specific positions
76
+ await tab.scroll.to_bottom(smooth=True)
77
+ await tab.scroll.to_top(smooth=True)
78
+
79
+ # Instant scroll for speed when realism isn't critical
80
+ await tab.scroll.by(ScrollPosition.UP, 300, smooth=False)
81
+ ```
82
+
83
+ Unlike `execute_script("window.scrollBy(...)")` which returns immediately, the scroll API uses CDP's `awaitPromise` to wait for the browser's `scrollend` event, ensuring your next actions only execute after scrolling completely finishes. Perfect for taking screenshots, loading lazy content, or creating realistic reading patterns.
84
+
68
85
  ## 📦 Installation
69
86
 
70
87
  ```bash
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://github.com/user-attachments/assets/219f2dbc-37ed-4aea-a289-ba39cdbb335d" alt="Pydoll Logo" /> <br>
2
+ <img src="https://github.com/user-attachments/assets/2c380638-b04a-4b04-b1c8-2958e4237a94" alt="Pydoll Logo" /> <br>
3
3
  </p>
4
4
  <h1 align="center">Pydoll: scraping, the easier way</h1>
5
5
 
@@ -32,11 +32,6 @@ Built from scratch with a different philosophy, Pydoll connects directly to the
32
32
 
33
33
  We believe that powerful automation shouldn't require you to become an expert in configuration or constantly fight with bot protection systems. With Pydoll, you can focus on what really matters: your automation logic, not the underlying complexity or protection systems.
34
34
 
35
- <div>
36
- <h4>Be a good human. Give it a star ⭐</h4>
37
- No stars, no bugs fixed. Just kidding (maybe)
38
- </div>
39
-
40
35
  ## 🌟 What makes Pydoll special?
41
36
 
42
37
  - **Zero Webdrivers**: Say goodbye to webdriver compatibility issues
@@ -45,6 +40,28 @@ We believe that powerful automation shouldn't require you to become an expert in
45
40
  - **Humanized Interactions**: Mimic real user behavior
46
41
  - **Simplicity**: With Pydoll, you install and you're ready to automate.
47
42
 
43
+ ## 🆕 What's New
44
+
45
+ ### Human-Like Page Scrolling: Scroll Like a Real User!
46
+
47
+ Now you can control page scrolling with smooth animations and automatic completion waiting:
48
+
49
+ ```python
50
+ from pydoll.constants import ScrollPosition
51
+
52
+ # Scroll down with smooth animation (waits for completion)
53
+ await tab.scroll.by(ScrollPosition.DOWN, 500, smooth=True)
54
+
55
+ # Navigate to specific positions
56
+ await tab.scroll.to_bottom(smooth=True)
57
+ await tab.scroll.to_top(smooth=True)
58
+
59
+ # Instant scroll for speed when realism isn't critical
60
+ await tab.scroll.by(ScrollPosition.UP, 300, smooth=False)
61
+ ```
62
+
63
+ Unlike `execute_script("window.scrollBy(...)")` which returns immediately, the scroll API uses CDP's `awaitPromise` to wait for the browser's `scrollend` event, ensuring your next actions only execute after scrolling completely finishes. Perfect for taking screenshots, loading lazy content, or creating realistic reading patterns.
64
+
48
65
  ## 📦 Installation
49
66
 
50
67
  ```bash
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import json
3
5
  import logging
@@ -8,11 +10,9 @@ from abc import ABC, abstractmethod
8
10
  from contextlib import suppress
9
11
  from functools import partial
10
12
  from random import randint
11
- from tempfile import TemporaryDirectory
12
- from typing import Any, Awaitable, Callable, Optional, overload
13
+ from typing import TYPE_CHECKING, Any, Awaitable, Callable, Optional, overload
13
14
  from urllib.parse import urlsplit, urlunsplit
14
15
 
15
- from pydoll.browser.interfaces import BrowserOptionsManager
16
16
  from pydoll.browser.managers import (
17
17
  BrowserProcessManager,
18
18
  ProxyManager,
@@ -35,30 +35,38 @@ from pydoll.exceptions import (
35
35
  MissingTargetOrWebSocket,
36
36
  NoValidTabFound,
37
37
  )
38
- from pydoll.protocol.base import Command, Response, T_CommandParams, T_CommandResponse
39
- from pydoll.protocol.browser.methods import (
40
- GetVersionResponse,
41
- GetVersionResult,
42
- GetWindowForTargetResponse,
43
- )
44
- from pydoll.protocol.browser.types import Bounds, DownloadBehavior, PermissionType
45
- from pydoll.protocol.fetch.events import FetchEvent, RequestPausedEvent
46
- from pydoll.protocol.fetch.types import AuthChallengeResponseType, HeaderEntry
47
- from pydoll.protocol.network.types import (
48
- Cookie,
49
- CookieParam,
50
- ErrorReason,
51
- RequestMethod,
52
- ResourceType,
53
- )
54
- from pydoll.protocol.storage.methods import GetCookiesResponse
55
- from pydoll.protocol.target.methods import (
56
- CreateBrowserContextResponse,
57
- CreateTargetResponse,
58
- GetBrowserContextsResponse,
59
- GetTargetsResponse,
60
- )
61
- from pydoll.protocol.target.types import TargetInfo
38
+ from pydoll.protocol.browser.types import DownloadBehavior
39
+ from pydoll.protocol.fetch.events import FetchEvent
40
+ from pydoll.protocol.fetch.types import AuthChallengeResponseType
41
+
42
+ if TYPE_CHECKING:
43
+ from tempfile import TemporaryDirectory
44
+
45
+ from pydoll.browser.interfaces import BrowserOptionsManager
46
+ from pydoll.protocol.base import Command, Response, T_CommandParams, T_CommandResponse
47
+ from pydoll.protocol.browser.methods import (
48
+ GetVersionResponse,
49
+ GetVersionResult,
50
+ GetWindowForTargetResponse,
51
+ )
52
+ from pydoll.protocol.browser.types import Bounds, PermissionType
53
+ from pydoll.protocol.fetch.events import RequestPausedEvent
54
+ from pydoll.protocol.fetch.types import HeaderEntry
55
+ from pydoll.protocol.network.types import (
56
+ Cookie,
57
+ CookieParam,
58
+ ErrorReason,
59
+ RequestMethod,
60
+ ResourceType,
61
+ )
62
+ from pydoll.protocol.storage.methods import GetCookiesResponse
63
+ from pydoll.protocol.target.methods import (
64
+ CreateBrowserContextResponse,
65
+ CreateTargetResponse,
66
+ GetBrowserContextsResponse,
67
+ GetTargetsResponse,
68
+ )
69
+ from pydoll.protocol.target.types import TargetInfo
62
70
 
63
71
  logger = logging.getLogger(__name__)
64
72
 
@@ -209,6 +217,13 @@ class Browser(ABC): # noqa: PLR0904
209
217
  await self._connection_handler.close()
210
218
  logger.info('Browser process stopped and resources cleaned up')
211
219
 
220
+ async def close(self):
221
+ """
222
+ Closes the WebSocket connection and releases resources.
223
+ """
224
+ logger.info('Closing browser WebSocket connection')
225
+ await self._connection_handler.close()
226
+
212
227
  async def create_browser_context(
213
228
  self, proxy_server: Optional[str] = None, proxy_bypass_list: Optional[str] = None
214
229
  ) -> str:
@@ -1,13 +1,17 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  import platform
3
- from typing import Optional
5
+ from typing import TYPE_CHECKING, Optional
4
6
 
5
7
  from pydoll.browser.chromium.base import Browser
6
8
  from pydoll.browser.managers import ChromiumOptionsManager
7
- from pydoll.browser.options import ChromiumOptions
8
9
  from pydoll.exceptions import UnsupportedOS
9
10
  from pydoll.utils import validate_browser_paths
10
11
 
12
+ if TYPE_CHECKING:
13
+ from pydoll.browser.options import ChromiumOptions
14
+
11
15
  logger = logging.getLogger(__name__)
12
16
 
13
17
 
@@ -1,13 +1,17 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  import platform
3
- from typing import Optional
5
+ from typing import TYPE_CHECKING, Optional
4
6
 
5
7
  from pydoll.browser.chromium.base import Browser
6
8
  from pydoll.browser.managers import ChromiumOptionsManager
7
- from pydoll.browser.options import Options
8
9
  from pydoll.exceptions import UnsupportedOS
9
10
  from pydoll.utils import validate_browser_paths
10
11
 
12
+ if TYPE_CHECKING:
13
+ from pydoll.browser.options import Options
14
+
11
15
  logger = logging.getLogger(__name__)
12
16
 
13
17
 
@@ -1,10 +1,15 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
- from typing import Optional
4
+ from typing import TYPE_CHECKING, Optional
3
5
 
4
- from pydoll.browser.interfaces import BrowserOptionsManager, Options
6
+ from pydoll.browser.interfaces import BrowserOptionsManager
5
7
  from pydoll.browser.options import ChromiumOptions
6
8
  from pydoll.exceptions import InvalidOptionsObject
7
9
 
10
+ if TYPE_CHECKING:
11
+ from pydoll.browser.options import Options
12
+
8
13
  logger = logging.getLogger(__name__)
9
14
 
10
15
 
@@ -1,7 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
- from typing import Optional
4
+ from typing import TYPE_CHECKING, Optional
3
5
 
4
- from pydoll.browser.options import Options
6
+ if TYPE_CHECKING:
7
+ from pydoll.browser.options import Options
5
8
 
6
9
  logger = logging.getLogger(__name__)
7
10
 
@@ -3,16 +3,19 @@ This module provides a Request class that mimics the behavior of requests.
3
3
  It allows making HTTP requests using the browser's fetch API.
4
4
  """
5
5
 
6
+ from __future__ import annotations
7
+
6
8
  import json as jsonlib
7
9
  import logging
8
10
  from typing import TYPE_CHECKING, Any, Callable, Optional, Union, cast
9
11
  from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
10
12
 
11
- from pydoll.browser.requests.response import HTTPError, Response
13
+ from pydoll.browser.requests.response import Response
12
14
  from pydoll.commands.runtime_commands import RuntimeCommands
13
15
  from pydoll.constants import Scripts
16
+ from pydoll.exceptions import HTTPError
14
17
  from pydoll.protocol.fetch.types import HeaderEntry
15
- from pydoll.protocol.network.events import NetworkEvent
18
+ from pydoll.protocol.network.events import NetworkEvent, ResponseReceivedExtraInfoEventParams
16
19
  from pydoll.protocol.network.types import CookieParam
17
20
 
18
21
  logger = logging.getLogger(__name__)
@@ -27,7 +30,6 @@ if TYPE_CHECKING:
27
30
  ResponseReceivedEvent,
28
31
  ResponseReceivedEventParams,
29
32
  ResponseReceivedExtraInfoEvent,
30
- ResponseReceivedExtraInfoEventParams,
31
33
  )
32
34
  from pydoll.protocol.runtime.methods import EvaluateResponse
33
35
 
@@ -71,7 +73,7 @@ class Request:
71
73
  - Cookies are managed automatically by the browser
72
74
  """
73
75
 
74
- def __init__(self, tab: 'Tab'):
76
+ def __init__(self, tab: Tab):
75
77
  """Initialize a new Request instance bound to a browser tab.
76
78
 
77
79
  Args:
@@ -81,8 +83,8 @@ class Request:
81
83
  """
82
84
  self.tab = tab
83
85
  self._network_events_enabled = False
84
- self._requests_sent: list['RequestSentEvent'] = []
85
- self._requests_received: list['RequestReceivedEvent'] = []
86
+ self._requests_sent: list[RequestSentEvent] = []
87
+ self._requests_received: list[RequestReceivedEvent] = []
86
88
  logger.debug('Request helper initialized for tab')
87
89
 
88
90
  async def request(
@@ -334,7 +336,7 @@ class Request:
334
336
  options['body'] = data
335
337
  logger.debug('Request data set as raw payload')
336
338
 
337
- async def _execute_fetch_request(self, url: str, options: dict[str, Any]) -> 'EvaluateResponse':
339
+ async def _execute_fetch_request(self, url: str, options: dict[str, Any]) -> EvaluateResponse:
338
340
  """Execute the fetch request using browser's runtime."""
339
341
  script = Scripts.MAKE_REQUEST.format(url=jsonlib.dumps(url), options=jsonlib.dumps(options))
340
342
  await self._register_callbacks()
@@ -350,7 +352,7 @@ class Request:
350
352
 
351
353
  @staticmethod
352
354
  def _build_response(
353
- result: 'EvaluateResponse',
355
+ result: EvaluateResponse,
354
356
  response_headers: list[HeaderEntry],
355
357
  request_headers: list[HeaderEntry],
356
358
  cookies: list[CookieParam],
@@ -385,11 +387,11 @@ class Request:
385
387
  logger.debug('Network events enabled on tab for request capture')
386
388
 
387
389
  def append_received_request(event: dict) -> None:
388
- self._requests_received.append(cast('RequestReceivedEvent', event))
390
+ self._requests_received.append(cast(RequestReceivedEvent, event))
389
391
  logger.debug(f'Appended received request: event={event}')
390
392
 
391
393
  def append_sent_request(event: dict) -> None:
392
- self._requests_sent.append(cast('RequestSentEvent', event))
394
+ self._requests_sent.append(cast(RequestSentEvent, event))
393
395
  logger.debug(f'Appended sent request: event={event}')
394
396
 
395
397
  await self.tab.on(
@@ -450,7 +452,7 @@ class Request:
450
452
 
451
453
  @staticmethod
452
454
  def _extract_headers_from_events(
453
- events: Union[list['RequestSentEvent'], list['RequestReceivedEvent']],
455
+ events: Union[list[RequestSentEvent], list[RequestReceivedEvent]],
454
456
  event_extractors: dict[str, Callable[[Any], list[HeaderEntry]]],
455
457
  ) -> list[HeaderEntry]:
456
458
  """Extract headers from network events using appropriate extractors.
@@ -488,7 +490,7 @@ class Request:
488
490
  return headers
489
491
 
490
492
  def _extract_request_sent_headers(
491
- self, params: 'RequestWillBeSentEventParams'
493
+ self, params: RequestWillBeSentEventParams
492
494
  ) -> list[HeaderEntry]:
493
495
  """Extract headers from main request event.
494
496
 
@@ -503,7 +505,7 @@ class Request:
503
505
  return self._convert_dict_to_header_entries(request.get('headers', {}))
504
506
 
505
507
  def _extract_request_sent_extra_info_headers(
506
- self, params: 'RequestWillBeSentExtraInfoEventParams'
508
+ self, params: RequestWillBeSentExtraInfoEventParams
507
509
  ) -> list[HeaderEntry]:
508
510
  """Extract headers from extra request info event.
509
511
 
@@ -520,7 +522,7 @@ class Request:
520
522
  return self._convert_dict_to_header_entries(params.get('headers', {}))
521
523
 
522
524
  def _extract_response_received_headers(
523
- self, params: 'ResponseReceivedEventParams'
525
+ self, params: ResponseReceivedEventParams
524
526
  ) -> list[HeaderEntry]:
525
527
  """Extract headers from main response event.
526
528
 
@@ -535,7 +537,7 @@ class Request:
535
537
  return self._convert_dict_to_header_entries(response.get('headers', {}))
536
538
 
537
539
  def _extract_response_received_extra_info_headers(
538
- self, params: 'ResponseReceivedExtraInfoEventParams'
540
+ self, params: ResponseReceivedExtraInfoEventParams
539
541
  ) -> list[HeaderEntry]:
540
542
  """Extract headers from extra response info event.
541
543
 
@@ -583,7 +585,7 @@ class Request:
583
585
  f'response_extra_info_events={response_extra_info_events}'
584
586
  )
585
587
  for event in response_extra_info_events:
586
- params = cast('ResponseReceivedExtraInfoEventParams', event['params'])
588
+ params = cast(ResponseReceivedExtraInfoEventParams, event['params'])
587
589
  headers = self._convert_dict_to_header_entries(params['headers'])
588
590
  logger.debug(f'Converting dictionary to header entries: headers={headers}')
589
591
  set_cookie_headers = [
@@ -598,7 +600,7 @@ class Request:
598
600
  logger.debug(f'Set cookies extracted: cookies={cookies}')
599
601
  return cookies
600
602
 
601
- def _filter_response_extra_info_events(self) -> list['RequestReceivedEvent']:
603
+ def _filter_response_extra_info_events(self) -> list[RequestReceivedEvent]:
602
604
  """Filter network events to find those containing Set-Cookie information.
603
605
 
604
606
  Returns:
@@ -1,9 +1,14 @@
1
+ from __future__ import annotations
2
+
1
3
  import json as jsonlib
2
4
  import logging
3
- from typing import Any, Optional, Union
5
+ from typing import TYPE_CHECKING, Any, Optional, Union
6
+
7
+ from pydoll.exceptions import HTTPError
4
8
 
5
- from pydoll.protocol.fetch.types import HeaderEntry
6
- from pydoll.protocol.network.types import CookieParam
9
+ if TYPE_CHECKING:
10
+ from pydoll.protocol.fetch.types import HeaderEntry
11
+ from pydoll.protocol.network.types import CookieParam
7
12
 
8
13
  logger = logging.getLogger(__name__)
9
14
 
@@ -221,11 +226,3 @@ class Response:
221
226
  f'HTTP error status encountered: status={self.status_code}, url={self._url}'
222
227
  )
223
228
  raise HTTPError(f'{self.status_code} Client Error: for url {self._url}')
224
-
225
-
226
- class HTTPError(Exception):
227
- """
228
- Exception raised for HTTP error responses (4xx and 5xx status codes).
229
- """
230
-
231
- pass