pydoll-python 2.2.1__tar.gz → 2.2.3__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 (95) hide show
  1. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/PKG-INFO +2 -5
  2. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/chromium/base.py +5 -4
  3. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/tab.py +10 -4
  4. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/elements/mixins/find_elements_mixin.py +6 -6
  5. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/elements/web_element.py +5 -4
  6. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/dom/types.py +11 -0
  7. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/utils.py +91 -0
  8. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pyproject.toml +2 -4
  9. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/LICENSE +0 -0
  10. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/README.md +0 -0
  11. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/__init__.py +0 -0
  12. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/__init__.py +0 -0
  13. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/chromium/__init__.py +0 -0
  14. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/chromium/chrome.py +0 -0
  15. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/chromium/edge.py +0 -0
  16. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/interfaces.py +0 -0
  17. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/managers/__init__.py +0 -0
  18. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/managers/browser_options_manager.py +0 -0
  19. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/managers/browser_process_manager.py +0 -0
  20. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/managers/proxy_manager.py +0 -0
  21. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/managers/temp_dir_manager.py +0 -0
  22. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/browser/options.py +0 -0
  23. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/__init__.py +0 -0
  24. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/browser_commands.py +0 -0
  25. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/dom_commands.py +0 -0
  26. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/fetch_commands.py +0 -0
  27. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/input_commands.py +0 -0
  28. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/network_commands.py +0 -0
  29. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/page_commands.py +0 -0
  30. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/runtime_commands.py +0 -0
  31. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/storage_commands.py +0 -0
  32. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/commands/target_commands.py +0 -0
  33. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/connection/__init__.py +0 -0
  34. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/connection/connection_handler.py +0 -0
  35. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/connection/managers/__init__.py +0 -0
  36. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/connection/managers/commands_manager.py +0 -0
  37. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/connection/managers/events_manager.py +0 -0
  38. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/constants.py +0 -0
  39. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/elements/__init__.py +0 -0
  40. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/elements/mixins/__init__.py +0 -0
  41. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/exceptions.py +0 -0
  42. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/__init__.py +0 -0
  43. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/base.py +0 -0
  44. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/browser/__init__.py +0 -0
  45. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/browser/events.py +0 -0
  46. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/browser/methods.py +0 -0
  47. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/browser/params.py +0 -0
  48. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/browser/responses.py +0 -0
  49. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/browser/types.py +0 -0
  50. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/dom/__init__.py +0 -0
  51. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/dom/events.py +0 -0
  52. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/dom/methods.py +0 -0
  53. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/dom/params.py +0 -0
  54. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/dom/responses.py +0 -0
  55. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/fetch/__init__.py +0 -0
  56. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/fetch/events.py +0 -0
  57. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/fetch/methods.py +0 -0
  58. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/fetch/params.py +0 -0
  59. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/fetch/responses.py +0 -0
  60. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/fetch/types.py +0 -0
  61. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/input/__init__.py +0 -0
  62. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/input/events.py +0 -0
  63. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/input/methods.py +0 -0
  64. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/input/params.py +0 -0
  65. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/input/types.py +0 -0
  66. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/network/__init__.py +0 -0
  67. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/network/events.py +0 -0
  68. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/network/methods.py +0 -0
  69. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/network/params.py +0 -0
  70. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/network/responses.py +0 -0
  71. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/network/types.py +0 -0
  72. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/page/__init__.py +0 -0
  73. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/page/events.py +0 -0
  74. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/page/methods.py +0 -0
  75. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/page/params.py +0 -0
  76. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/page/responses.py +0 -0
  77. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/page/types.py +0 -0
  78. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/runtime/__init__.py +0 -0
  79. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/runtime/events.py +0 -0
  80. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/runtime/methods.py +0 -0
  81. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/runtime/params.py +0 -0
  82. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/runtime/responses.py +0 -0
  83. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/runtime/types.py +0 -0
  84. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/storage/__init__.py +0 -0
  85. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/storage/events.py +0 -0
  86. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/storage/methods.py +0 -0
  87. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/storage/params.py +0 -0
  88. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/storage/responses.py +0 -0
  89. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/storage/types.py +0 -0
  90. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/target/__init__.py +0 -0
  91. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/target/events.py +0 -0
  92. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/target/methods.py +0 -0
  93. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/target/params.py +0 -0
  94. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/target/responses.py +0 -0
  95. {pydoll_python-2.2.1 → pydoll_python-2.2.3}/pydoll/protocol/target/types.py +0 -0
@@ -1,19 +1,16 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pydoll-python
3
- Version: 2.2.1
3
+ Version: 2.2.3
4
4
  Summary:
5
5
  Author: Thalison Fernandes
6
6
  Author-email: thalissfernandes99@gmail.com
7
- Requires-Python: >=3.10,<4.0
7
+ Requires-Python: >=3.11,<4.0
8
8
  Classifier: Programming Language :: Python :: 3
9
- Classifier: Programming Language :: Python :: 3.10
10
9
  Classifier: Programming Language :: Python :: 3.11
11
10
  Classifier: Programming Language :: Python :: 3.12
12
11
  Classifier: Programming Language :: Python :: 3.13
13
12
  Requires-Dist: aiofiles (>=23.2.1,<24.0.0)
14
13
  Requires-Dist: aiohttp (>=3.9.5,<4.0.0)
15
- Requires-Dist: beautifulsoup4 (>=4.12.3,<5.0.0)
16
- Requires-Dist: mkdocstrings (>=0.29.1,<0.30.0)
17
14
  Requires-Dist: websockets (>=13.1,<14.0)
18
15
  Description-Content-Type: text/markdown
19
16
 
@@ -231,12 +231,13 @@ class Browser(ABC): # noqa: PLR0904
231
231
  """
232
232
  targets = await self.get_targets()
233
233
  valid_tab_targets = [
234
- target for target in targets if target['type'] == 'page'
235
- and 'extension' not in target['url']
234
+ target
235
+ for target in targets
236
+ if target['type'] == 'page' and 'extension' not in target['url']
236
237
  ]
237
238
  return [
238
- Tab(self, self._connection_port, target['targetId']) for target
239
- in reversed(valid_tab_targets)
239
+ Tab(self, self._connection_port, target['targetId'])
240
+ for target in reversed(valid_tab_targets)
240
241
  ]
241
242
 
242
243
  async def set_download_path(self, path: str, browser_context_id: Optional[str] = None):
@@ -41,6 +41,7 @@ from pydoll.exceptions import (
41
41
  WaitElementTimeout,
42
42
  )
43
43
  from pydoll.protocol.base import Response
44
+ from pydoll.protocol.dom.types import EventFileChooserOpened
44
45
  from pydoll.protocol.network.responses import GetResponseBodyResponse
45
46
  from pydoll.protocol.network.types import Cookie, CookieParam, NetworkLog
46
47
  from pydoll.protocol.page.events import PageEvent
@@ -678,10 +679,11 @@ class Tab(FindElementsMixin): # noqa: PLR0904
678
679
  files: File path(s) for upload.
679
680
  """
680
681
 
681
- async def event_handler(event):
682
+ async def event_handler(event: EventFileChooserOpened):
683
+ file_list = [str(file) for file in files] if isinstance(files, list) else [str(files)]
682
684
  await self._execute_command(
683
- DomCommands.upload_files(
684
- files=files,
685
+ DomCommands.set_file_input_files(
686
+ files=file_list,
685
687
  backend_node_id=event['params']['backendNodeId'],
686
688
  )
687
689
  )
@@ -695,7 +697,11 @@ class Tab(FindElementsMixin): # noqa: PLR0904
695
697
  if self.intercept_file_chooser_dialog_enabled is False:
696
698
  await self.enable_intercept_file_chooser_dialog()
697
699
 
698
- await self.on(PageEvent.FILE_CHOOSER_OPENED, event_handler, temporary=True)
700
+ await self.on(
701
+ PageEvent.FILE_CHOOSER_OPENED,
702
+ cast(Callable[[dict], Any], event_handler),
703
+ temporary=True,
704
+ )
699
705
 
700
706
  yield
701
707
 
@@ -403,8 +403,8 @@ class FindElementsMixin:
403
403
  if object_id and not by == By.XPATH:
404
404
  script = Scripts.RELATIVE_QUERY_SELECTOR.replace('{selector}', selector)
405
405
  command = RuntimeCommands.call_function_on(
406
- object_id,
407
- script,
406
+ function_declaration=script,
407
+ object_id=object_id,
408
408
  return_by_value=False,
409
409
  )
410
410
  elif by == By.XPATH:
@@ -437,8 +437,8 @@ class FindElementsMixin:
437
437
  if object_id and not by == By.XPATH:
438
438
  script = Scripts.RELATIVE_QUERY_SELECTOR_ALL.replace('{selector}', escaped_value)
439
439
  command = RuntimeCommands.call_function_on(
440
- object_id,
441
- script,
440
+ function_declaration=script,
441
+ object_id=object_id,
442
442
  return_by_value=False,
443
443
  )
444
444
  elif by == By.XPATH:
@@ -461,8 +461,8 @@ class FindElementsMixin:
461
461
  escaped_value = self._ensure_relative_xpath(escaped_value)
462
462
  script = Scripts.FIND_RELATIVE_XPATH_ELEMENT.replace('{escaped_value}', escaped_value)
463
463
  command = RuntimeCommands.call_function_on(
464
- object_id,
465
- script,
464
+ function_declaration=script,
465
+ object_id=object_id,
466
466
  return_by_value=False,
467
467
  )
468
468
  else:
@@ -3,7 +3,6 @@ import json
3
3
  from typing import Optional
4
4
 
5
5
  import aiofiles
6
- from bs4 import BeautifulSoup
7
6
 
8
7
  from pydoll.commands import (
9
8
  DomCommands,
@@ -34,7 +33,10 @@ from pydoll.protocol.dom.responses import (
34
33
  from pydoll.protocol.dom.types import Quad
35
34
  from pydoll.protocol.page.responses import CaptureScreenshotResponse
36
35
  from pydoll.protocol.page.types import Viewport
37
- from pydoll.utils import decode_base64_to_bytes
36
+ from pydoll.utils import (
37
+ decode_base64_to_bytes,
38
+ extract_text_from_html,
39
+ )
38
40
 
39
41
 
40
42
  class WebElement(FindElementsMixin): # noqa: PLR0904
@@ -99,8 +101,7 @@ class WebElement(FindElementsMixin): # noqa: PLR0904
99
101
  async def text(self) -> str:
100
102
  """Visible text content of the element."""
101
103
  outer_html = await self.inner_html
102
- soup = BeautifulSoup(outer_html, 'html.parser')
103
- return soup.get_text(strip=True)
104
+ return extract_text_from_html(outer_html, strip=True)
104
105
 
105
106
  @property
106
107
  async def bounds(self) -> Quad:
@@ -79,3 +79,14 @@ class BoxModel(TypedDict):
79
79
  width: int
80
80
  height: int
81
81
  shapeOutside: NotRequired[ShapeOutsideInfo]
82
+
83
+
84
+ class EventFileChooserOpenedParams(TypedDict):
85
+ frameId: str
86
+ mode: str
87
+ backendNodeId: int
88
+
89
+
90
+ class EventFileChooserOpened(TypedDict):
91
+ method: str
92
+ params: EventFileChooserOpenedParams
@@ -2,6 +2,8 @@ import base64
2
2
  import logging
3
3
  import os
4
4
  import re
5
+ from html import unescape
6
+ from html.parser import HTMLParser
5
7
 
6
8
  import aiohttp
7
9
 
@@ -10,6 +12,95 @@ from pydoll.exceptions import InvalidBrowserPath, InvalidResponse, NetworkError
10
12
  logger = logging.getLogger(__name__)
11
13
 
12
14
 
15
+ class TextExtractor(HTMLParser):
16
+ """
17
+ HTML parser for text extraction.
18
+
19
+ Extracts visible text content from an HTML string, excluding the contents of
20
+ tags specified in _skip_tags.
21
+ """
22
+
23
+ def __init__(self):
24
+ super().__init__()
25
+ self._parts = []
26
+ self._skip = False
27
+ self._skip_tags = {'script', 'style', 'template'}
28
+
29
+ def handle_starttag(self, tag, attrs):
30
+ """
31
+ Marks the parser to skip content inside tags specified in _skip_tags.
32
+
33
+ Args:
34
+ tag (str): The tag name.
35
+ attrs (list): A list of (attribute, value) pairs.
36
+ """
37
+ if tag in self._skip_tags:
38
+ self._skip = True
39
+
40
+ def handle_endtag(self, tag):
41
+ """
42
+ Marks the parser the end of skip tags.
43
+
44
+ Args:
45
+ tag (str): The tag name.
46
+ """
47
+ if tag in self._skip_tags:
48
+ self._skip = False
49
+
50
+ def handle_data(self, data):
51
+ """
52
+ Handles text nodes. Adds them to the result unless they are within a skip tag.
53
+
54
+ Args:
55
+ data (str): The text data.
56
+ """
57
+ if not self._skip:
58
+ self._parts.append(unescape(data))
59
+
60
+ def get_strings(self, strip: bool):
61
+ """
62
+ Yields all collected visible text fragments.
63
+
64
+ Args:
65
+ strip (bool): Whether to strip leading/trailing whitespace from each fragment.
66
+
67
+ Yields:
68
+ str: Visible text fragments.
69
+ """
70
+ for text in self._parts:
71
+ yield text.strip() if strip else text
72
+
73
+ def get_text(self, separator: str, strip: bool) -> str:
74
+ """
75
+ Returns all visible text.
76
+
77
+ Args:
78
+ separator (str): String inserted between extracted text fragments.
79
+ strip (bool): Whether to strip whitespace from each fragment.
80
+
81
+ Returns:
82
+ str: The visible text.
83
+ """
84
+ return separator.join(self.get_strings(strip=strip))
85
+
86
+
87
+ def extract_text_from_html(html: str, separator: str = '', strip: bool = False) -> str:
88
+ """
89
+ Extracts visible text content from an HTML string.
90
+
91
+ Args:
92
+ html (str): The HTML string to extract text from.
93
+ separator (str, optional): String inserted between extracted text fragments. Defaults to ''.
94
+ strip (bool, optional): Whether to strip whitespace from text fragments. Defaults to False.
95
+
96
+ Returns:
97
+ str: The extracted visible text.
98
+ """
99
+ parser = TextExtractor()
100
+ parser.feed(html)
101
+ return parser.get_text(separator=separator, strip=strip)
102
+
103
+
13
104
  def decode_base64_to_bytes(image: str) -> bytes:
14
105
  """
15
106
  Decodes a base64 image string to bytes.
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pydoll-python"
3
- version = "2.2.1"
3
+ version = "2.2.3"
4
4
  description = ""
5
5
  authors = ["Thalison Fernandes <thalissfernandes99@gmail.com>"]
6
6
  readme = "README.md"
@@ -9,12 +9,10 @@ packages = [
9
9
  ]
10
10
 
11
11
  [tool.poetry.dependencies]
12
- python = "^3.10"
12
+ python = "^3.11"
13
13
  websockets = "^13.1"
14
14
  aiohttp = "^3.9.5"
15
15
  aiofiles = "^23.2.1"
16
- beautifulsoup4 = "^4.12.3"
17
- mkdocstrings = "^0.29.1"
18
16
 
19
17
 
20
18
  [tool.poetry.group.dev.dependencies]
File without changes
File without changes