adspower 2.0.2__tar.gz → 2.0.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 (55) hide show
  1. {adspower-2.0.2 → adspower-2.0.3}/PKG-INFO +9 -2
  2. {adspower-2.0.2 → adspower-2.0.3}/README.md +8 -1
  3. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/__pycache__/_base_profile.cpython-311.pyc +0 -0
  4. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/__pycache__/profile_api.cpython-311.pyc +0 -0
  5. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/_base_profile.py +0 -1
  6. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/playwright/__pycache__/profile.cpython-311.pyc +0 -0
  7. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/playwright/profile.py +1 -3
  8. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/profile_api.py +57 -12
  9. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/selenium/__pycache__/profile.cpython-311.pyc +0 -0
  10. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/selenium/profile.py +5 -3
  11. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/_base_profile.py +1 -2
  12. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/playwright/profile.py +0 -2
  13. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/profile_api.py +19 -2
  14. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/selenium/profile.py +5 -2
  15. adspower-2.0.3/adspower/utils.py +69 -0
  16. {adspower-2.0.2 → adspower-2.0.3}/pyproject.toml +1 -1
  17. adspower-2.0.2/adspower/utils.py +0 -36
  18. {adspower-2.0.2 → adspower-2.0.3}/LICENSE +0 -0
  19. {adspower-2.0.2 → adspower-2.0.3}/adspower/.DS_Store +0 -0
  20. {adspower-2.0.2 → adspower-2.0.3}/adspower/__init__.py +0 -0
  21. {adspower-2.0.2 → adspower-2.0.3}/adspower/_api_entity.py +0 -0
  22. {adspower-2.0.2 → adspower-2.0.3}/adspower/_base_category.py +0 -0
  23. {adspower-2.0.2 → adspower-2.0.3}/adspower/_base_group.py +0 -0
  24. {adspower-2.0.2 → adspower-2.0.3}/adspower/_base_http_client.py +0 -0
  25. {adspower-2.0.2 → adspower-2.0.3}/adspower/_base_profile_api.py +0 -0
  26. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/__init__.py +0 -0
  27. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/__pycache__/__init__.cpython-311.pyc +0 -0
  28. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/__pycache__/category.cpython-311.pyc +0 -0
  29. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/__pycache__/group.cpython-311.pyc +0 -0
  30. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/__pycache__/http_client.cpython-311.pyc +0 -0
  31. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/category.py +0 -0
  32. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/group.py +0 -0
  33. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/http_client.py +0 -0
  34. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/playwright/__init__.py +0 -0
  35. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/playwright/__pycache__/__init__.cpython-311.pyc +0 -0
  36. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/selenium/__init__.py +0 -0
  37. {adspower-2.0.2 → adspower-2.0.3}/adspower/async_api/selenium/__pycache__/__init__.cpython-311.pyc +0 -0
  38. {adspower-2.0.2 → adspower-2.0.3}/adspower/exceptions.py +0 -0
  39. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/__init__.py +0 -0
  40. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/__pycache__/__init__.cpython-311.pyc +0 -0
  41. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/__pycache__/_base_profile.cpython-311.pyc +0 -0
  42. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/__pycache__/category.cpython-311.pyc +0 -0
  43. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/__pycache__/group.cpython-311.pyc +0 -0
  44. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/__pycache__/http_client.cpython-311.pyc +0 -0
  45. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/__pycache__/profile_api.cpython-311.pyc +0 -0
  46. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/category.py +0 -0
  47. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/group.py +0 -0
  48. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/http_client.py +0 -0
  49. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/playwright/__init__.py +0 -0
  50. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/playwright/__pycache__/__init__.cpython-311.pyc +0 -0
  51. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/playwright/__pycache__/profile.cpython-311.pyc +0 -0
  52. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/selenium/__init__.py +0 -0
  53. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/selenium/__pycache__/__init__.cpython-311.pyc +0 -0
  54. {adspower-2.0.2 → adspower-2.0.3}/adspower/sync_api/selenium/__pycache__/profile.cpython-311.pyc +0 -0
  55. {adspower-2.0.2 → adspower-2.0.3}/adspower/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: adspower
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: The package for interacting with API of anti-detect browser AdsPower.
5
5
  Home-page: https://github.com/blnkoff/adspower
6
6
  License: MIT
@@ -27,7 +27,14 @@ Description-Content-Type: text/markdown
27
27
 
28
28
  # adspower
29
29
 
30
- [![Croco Logo](https://i.ibb.co/G5Pjt6M/logo.png)](https://t.me/crocofactory)<a href="https://www.adspower.com"><img height="35" src="https://www.adspower.com/dist/logo_global.png"></a>
30
+ [![Croco Logo](https://i.ibb.co/G5Pjt6M/logo.png)](https://t.me/crocofactory) <a href="https://www.adspower.com"><img height="35" src="https://www.adspower.com/dist/logo_global.png"></a>
31
+
32
+ [![PyPi Version](https://img.shields.io/pypi/v/adspower)](https://pypi.org/project/adspower/)
33
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/adspower?label=downloads)](https://pypi.org/project/adspower/)
34
+ [![License](https://img.shields.io/github/license/blnkoff/adspower.svg)](https://pypi.org/project/adspower/)
35
+ [![Last Commit](https://img.shields.io/github/last-commit/blnkoff/adspower.svg)](https://pypi.org/project/adspower/)
36
+ [![Development Status](https://img.shields.io/pypi/status/adspower)](https://pypi.org/project/adspower/)
37
+
31
38
 
32
39
  The package for interacting with API of anti-detect browser [AdsPower](https://www.adspower.com).
33
40
 
@@ -1,6 +1,13 @@
1
1
  # adspower
2
2
 
3
- [![Croco Logo](https://i.ibb.co/G5Pjt6M/logo.png)](https://t.me/crocofactory)<a href="https://www.adspower.com"><img height="35" src="https://www.adspower.com/dist/logo_global.png"></a>
3
+ [![Croco Logo](https://i.ibb.co/G5Pjt6M/logo.png)](https://t.me/crocofactory) <a href="https://www.adspower.com"><img height="35" src="https://www.adspower.com/dist/logo_global.png"></a>
4
+
5
+ [![PyPi Version](https://img.shields.io/pypi/v/adspower)](https://pypi.org/project/adspower/)
6
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/adspower?label=downloads)](https://pypi.org/project/adspower/)
7
+ [![License](https://img.shields.io/github/license/blnkoff/adspower.svg)](https://pypi.org/project/adspower/)
8
+ [![Last Commit](https://img.shields.io/github/last-commit/blnkoff/adspower.svg)](https://pypi.org/project/adspower/)
9
+ [![Development Status](https://img.shields.io/pypi/status/adspower)](https://pypi.org/project/adspower/)
10
+
4
11
 
5
12
  The package for interacting with API of anti-detect browser [AdsPower](https://www.adspower.com).
6
13
 
@@ -38,7 +38,6 @@ class _BaseProfile(ProfileAPI, ABC):
38
38
  clear_cache_after_closing: bool = False,
39
39
  enable_password_saving: bool = False,
40
40
  close_tabs: bool = True,
41
- start_maximized: bool = True
42
41
  ):
43
42
  pass
44
43
 
@@ -88,8 +88,7 @@ class Profile(_BaseProfile):
88
88
  disable_password_filling: bool = False,
89
89
  clear_cache_after_closing: bool = False,
90
90
  enable_password_saving: bool = False,
91
- close_tabs: bool = True,
92
- start_maximized: bool = True
91
+ close_tabs: bool = True
93
92
  ) -> BrowserContext:
94
93
  """
95
94
  Get a BrowserContext connected to the profile
@@ -102,7 +101,6 @@ class Profile(_BaseProfile):
102
101
  :param clear_cache_after_closing: Whether to delete the cache after closing the browser
103
102
  :param enable_password_saving: Whether to allow password saving
104
103
  :param close_tabs: Whether to close all startup tabs
105
- :param start_maximized: Whether to enable maximized window size at start
106
104
  :return: BrowserContext instance
107
105
  """
108
106
  response = await self._get_browser(
@@ -144,13 +144,27 @@ class ProfileAPI(_BaseProfileAPI, ABC):
144
144
  :return: A Profile instance
145
145
  """
146
146
  http_client = cls._client
147
- args, handler = cls._create(group,
148
- name,
149
- domain_name,
150
- open_urls,
151
- repeat_config,
152
- username,
153
- password)
147
+ args, handler = cls._create(
148
+ group,
149
+ name,
150
+ domain_name,
151
+ open_urls,
152
+ repeat_config,
153
+ username,
154
+ password,
155
+ fakey,
156
+ cookies,
157
+ ignore_cookie_error,
158
+ ip,
159
+ ip_country,
160
+ region,
161
+ city,
162
+ remark,
163
+ ip_checker,
164
+ category,
165
+ proxy_config,
166
+ fingerprint_config
167
+ )
154
168
 
155
169
  async with http_client() as client:
156
170
  response = (await client.post(**args)).json()['data']
@@ -182,7 +196,15 @@ class ProfileAPI(_BaseProfileAPI, ABC):
182
196
  :return: List of profiles
183
197
  """
184
198
  http_client = cls._client
185
- args, handler = cls._query(group, id_, name, serial_number, user_sort, page, page_size)
199
+ args, handler = cls._query(
200
+ group,
201
+ id_,
202
+ name,
203
+ serial_number,
204
+ user_sort,
205
+ page,
206
+ page_size
207
+ )
186
208
 
187
209
  async with http_client() as client:
188
210
  response = (await client.get(**args)).json()['data']
@@ -213,7 +235,15 @@ class ProfileAPI(_BaseProfileAPI, ABC):
213
235
  ) -> BrowserResponse:
214
236
  http_client = self._client
215
237
 
216
- args, handler = super()._get_browser(ip_tab, new_first_tab, launch_args)
238
+ args, handler = super()._get_browser(
239
+ ip_tab,
240
+ new_first_tab,
241
+ launch_args,
242
+ headless,
243
+ disable_password_filling,
244
+ clear_cache_after_closing,
245
+ enable_password_saving
246
+ )
217
247
  async with http_client() as client:
218
248
  response = (await client.get(**args)).json()['data']
219
249
 
@@ -262,9 +292,24 @@ class ProfileAPI(_BaseProfileAPI, ABC):
262
292
  :param fingerprint_config: Dictionary containing fingerprint info
263
293
  """
264
294
  http_client = self._client
265
- args, handler = self._update(name, domain_name, open_urls, username, password, fakey, cookies,
266
- ignore_cookie_error, ip, ip_country, region, city, remark, category,
267
- proxy_config, fingerprint_config)
295
+ args, handler = self._update(
296
+ name,
297
+ domain_name,
298
+ open_urls,
299
+ username,
300
+ password,
301
+ fakey,
302
+ cookies,
303
+ ignore_cookie_error,
304
+ ip,
305
+ ip_country,
306
+ region,
307
+ city,
308
+ remark,
309
+ category,
310
+ proxy_config,
311
+ fingerprint_config
312
+ )
268
313
 
269
314
  async with http_client() as client:
270
315
  (await client.post(**args))
@@ -122,14 +122,16 @@ class Profile(_BaseProfile):
122
122
 
123
123
  options.add_experimental_option('debuggerAddress', debugger_address)
124
124
  options.page_load_strategy = 'none'
125
- options.add_argument('--headless=new')
126
125
 
127
- if start_maximized:
128
- options.add_argument("--start-maximized")
126
+ if not headless:
127
+ options.add_argument('--headless=new')
129
128
 
130
129
  service = Service(executable_path=chrome_driver)
131
130
  browser = self._browser = WebDriver(service=service, options=options)
132
131
 
132
+ if start_maximized:
133
+ browser.maximize_window()
134
+
133
135
  if close_tabs:
134
136
  self.close_tabs()
135
137
 
@@ -37,8 +37,7 @@ class _BaseProfile(ProfileAPI, ABC):
37
37
  disable_password_filling: bool = False,
38
38
  clear_cache_after_closing: bool = False,
39
39
  enable_password_saving: bool = False,
40
- close_tabs: bool = True,
41
- start_maximized: bool = True
40
+ close_tabs: bool = True
42
41
  ):
43
42
  pass
44
43
 
@@ -89,7 +89,6 @@ class Profile(_BaseProfile):
89
89
  clear_cache_after_closing: bool = False,
90
90
  enable_password_saving: bool = False,
91
91
  close_tabs: bool = True,
92
- start_maximized: bool = True
93
92
  ) -> BrowserContext:
94
93
  """
95
94
  Get a BrowserContext connected to the profile
@@ -102,7 +101,6 @@ class Profile(_BaseProfile):
102
101
  :param clear_cache_after_closing: Whether to delete the cache after closing the browser
103
102
  :param enable_password_saving: Whether to allow password saving
104
103
  :param close_tabs: Whether to close all startup tabs
105
- :param start_maximized: Whether to enable maximized window size at start
106
104
  :return: BrowserContext instance
107
105
  """
108
106
  response = self._get_browser(
@@ -196,7 +196,15 @@ class ProfileAPI(_BaseProfileAPI):
196
196
  :return: List of profiles
197
197
  """
198
198
  http_client = cls._client
199
- args, handler = cls._query(group, id_, name, serial_number, user_sort, page, page_size)
199
+ args, handler = cls._query(
200
+ group,
201
+ id_,
202
+ name,
203
+ serial_number,
204
+ user_sort,
205
+ page,
206
+ page_size
207
+ )
200
208
 
201
209
  with http_client() as client:
202
210
  response = client.get(**args).json()['data']
@@ -227,7 +235,16 @@ class ProfileAPI(_BaseProfileAPI):
227
235
  ) -> BrowserResponse:
228
236
  http_client = self._client
229
237
 
230
- args, handler = super()._get_browser(ip_tab, new_first_tab, launch_args)
238
+ args, handler = super()._get_browser(
239
+ ip_tab,
240
+ new_first_tab,
241
+ launch_args,
242
+ headless,
243
+ disable_password_filling,
244
+ clear_cache_after_closing,
245
+ enable_password_saving
246
+ )
247
+
231
248
  with http_client() as client:
232
249
  response = client.get(**args).json()['data']
233
250
 
@@ -124,12 +124,15 @@ class Profile(_BaseProfile):
124
124
  options.page_load_strategy = 'none'
125
125
  options.add_argument('--headless=new')
126
126
 
127
- if start_maximized:
128
- options.add_argument("--start-maximized")
127
+ if not headless:
128
+ options.add_argument('--headless=new')
129
129
 
130
130
  service = Service(executable_path=chrome_driver)
131
131
  browser = self._browser = WebDriver(service=service, options=options)
132
132
 
133
+ if start_maximized:
134
+ browser.maximize_window()
135
+
133
136
  if close_tabs:
134
137
  self.close_tabs()
135
138
 
@@ -0,0 +1,69 @@
1
+ import ctypes
2
+ import platform
3
+ import subprocess
4
+ from typing import TypeVar
5
+
6
+ _KT = TypeVar('_KT')
7
+ _VT = TypeVar('_VT')
8
+
9
+
10
+ def _convert_json(data: dict[_KT, _VT]) -> dict[_KT, _VT]:
11
+ """
12
+ Convert string representations of numbers to actual numeric types within a dictionary and convert
13
+ empty strings to None.
14
+
15
+ :param data: A dictionary containing various key-value pairs.
16
+ :return: A dictionary with string representations of numbers converted to their actual numeric types.
17
+ """
18
+ for key, value in data.items():
19
+ if isinstance(value, str) and value.isdigit():
20
+ data[key] = int(value)
21
+ elif isinstance(value, str) and _is_float(value):
22
+ data[key] = float(value)
23
+ elif isinstance(value, str) and not len(value):
24
+ data[key] = None
25
+ return data
26
+
27
+
28
+ def _is_float(__str: str) -> bool:
29
+ """
30
+ Check if a string represents a floating-point number.
31
+
32
+ :param __str: A string to check.
33
+ :return: True if the string represents a floating-point number, False otherwise.
34
+ """
35
+ try:
36
+ float(__str)
37
+ return True
38
+ except ValueError:
39
+ return False
40
+
41
+
42
+ def _get_screen_size() -> tuple[int, int]:
43
+ os_name = platform.system()
44
+ if os_name == "Windows":
45
+ h = ctypes.windll.user32.GetDC(0)
46
+ width = ctypes.windll.gdi32.GetDeviceCaps(h, 118)
47
+ height = ctypes.windll.gdi32.GetDeviceCaps(h, 117)
48
+ ctypes.windll.user32.ReleaseDC(0, h)
49
+ return width, height
50
+
51
+ elif os_name == "Darwin":
52
+ output = subprocess.run(['system_profiler', 'SPDisplaysDataType'], capture_output=True, text=True).stdout
53
+ for line in output.split('\n'):
54
+ if 'Resolution' in line:
55
+ parts = line.split()
56
+ width = int(parts[1])
57
+ height = int(parts[3])
58
+ return width, height
59
+
60
+ elif os_name == "Linux":
61
+ output = subprocess.run(['xrandr'], capture_output=True, text=True).stdout
62
+ for line in output.split('\n'):
63
+ if '*' in line:
64
+ resolution = line.split()[0]
65
+ width, height = map(int, resolution.split('x'))
66
+ return width, height
67
+
68
+ else:
69
+ raise NotImplementedError(f"OS {os_name} not supported")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = 'adspower'
3
- version = '2.0.2'
3
+ version = '2.0.3'
4
4
  description = 'The package for interacting with API of anti-detect browser AdsPower.'
5
5
  authors = ['Alexey <axbelenkov@gmail.com>']
6
6
  license = 'MIT'
@@ -1,36 +0,0 @@
1
- from typing import TypeVar
2
-
3
- _KT = TypeVar('_KT')
4
- _VT = TypeVar('_VT')
5
-
6
-
7
- def _convert_json(data: dict[_KT, _VT]) -> dict[_KT, _VT]:
8
- """
9
- Convert string representations of numbers to actual numeric types within a dictionary and convert
10
- empty strings to None.
11
-
12
- :param data: A dictionary containing various key-value pairs.
13
- :return: A dictionary with string representations of numbers converted to their actual numeric types.
14
- """
15
- for key, value in data.items():
16
- if isinstance(value, str) and value.isdigit():
17
- data[key] = int(value)
18
- elif isinstance(value, str) and _is_float(value):
19
- data[key] = float(value)
20
- elif isinstance(value, str) and not len(value):
21
- data[key] = None
22
- return data
23
-
24
-
25
- def _is_float(__str: str) -> bool:
26
- """
27
- Check if a string represents a floating-point number.
28
-
29
- :param __str: A string to check.
30
- :return: True if the string represents a floating-point number, False otherwise.
31
- """
32
- try:
33
- float(__str)
34
- return True
35
- except ValueError:
36
- return False
File without changes
File without changes
File without changes
File without changes