cmdop 0.1.21__py3-none-any.whl → 0.1.22__py3-none-any.whl
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.
- cmdop/__init__.py +1 -1
- cmdop/client.py +2 -8
- cmdop/services/browser/__init__.py +44 -31
- cmdop/services/browser/capabilities/__init__.py +15 -0
- cmdop/services/browser/capabilities/_base.py +28 -0
- cmdop/services/browser/capabilities/_helpers.py +16 -0
- cmdop/services/browser/capabilities/dom.py +76 -0
- cmdop/services/browser/capabilities/fetch.py +46 -0
- cmdop/services/browser/capabilities/input.py +49 -0
- cmdop/services/browser/capabilities/scroll.py +147 -0
- cmdop/services/browser/capabilities/timing.py +66 -0
- cmdop/services/browser/js/__init__.py +6 -4
- cmdop/services/browser/js/interaction.py +34 -0
- cmdop/services/browser/service/__init__.py +5 -0
- cmdop/services/browser/service/aio.py +30 -0
- cmdop/services/browser/{sync/service.py → service/sync.py} +2 -2
- cmdop/services/browser/session.py +166 -0
- {cmdop-0.1.21.dist-info → cmdop-0.1.22.dist-info}/METADATA +69 -60
- {cmdop-0.1.21.dist-info → cmdop-0.1.22.dist-info}/RECORD +22 -18
- cmdop/services/browser/aio/__init__.py +0 -6
- cmdop/services/browser/aio/service.py +0 -420
- cmdop/services/browser/aio/session.py +0 -407
- cmdop/services/browser/base/__init__.py +0 -6
- cmdop/services/browser/base/session.py +0 -124
- cmdop/services/browser/sync/__init__.py +0 -6
- cmdop/services/browser/sync/session.py +0 -644
- /cmdop/services/browser/{base/service.py → service/_helpers.py} +0 -0
- {cmdop-0.1.21.dist-info → cmdop-0.1.22.dist-info}/WHEEL +0 -0
- {cmdop-0.1.21.dist-info → cmdop-0.1.22.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Async browser service stub.
|
|
2
|
+
|
|
3
|
+
Async browser is not implemented yet. Use sync BrowserService instead.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import TYPE_CHECKING, NoReturn
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from cmdop.transport.base import BaseTransport
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AsyncBrowserService:
|
|
15
|
+
"""
|
|
16
|
+
Async browser service stub.
|
|
17
|
+
|
|
18
|
+
Not implemented yet. Use sync CMDOPClient.browser instead.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, transport: BaseTransport) -> None:
|
|
22
|
+
self._transport = transport
|
|
23
|
+
|
|
24
|
+
def _not_implemented(self) -> NoReturn:
|
|
25
|
+
raise NotImplementedError(
|
|
26
|
+
"Async browser is not implemented. Use sync CMDOPClient.browser instead."
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
async def create_session(self, *args, **kwargs) -> NoReturn:
|
|
30
|
+
self._not_implemented()
|
|
@@ -6,7 +6,7 @@ import json
|
|
|
6
6
|
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
from cmdop.services.base import BaseService
|
|
9
|
-
from cmdop.services.browser.
|
|
9
|
+
from cmdop.services.browser.service._helpers import BaseServiceMixin, cookie_to_pb, pb_to_cookie
|
|
10
10
|
from cmdop.services.browser.models import BrowserCookie, BrowserState, PageInfo, raise_browser_error
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
@@ -47,7 +47,7 @@ class BrowserService(BaseService, BaseServiceMixin):
|
|
|
47
47
|
height: int = 800,
|
|
48
48
|
) -> "BrowserSession":
|
|
49
49
|
from cmdop._generated.rpc_messages.browser_pb2 import BrowserCreateSessionRequest
|
|
50
|
-
from cmdop.services.browser.
|
|
50
|
+
from cmdop.services.browser.session import BrowserSession
|
|
51
51
|
|
|
52
52
|
request = BrowserCreateSessionRequest(
|
|
53
53
|
provider=provider,
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""Browser session with capability-based API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
from cmdop.services.browser.models import BrowserCookie, BrowserState, PageInfo
|
|
7
|
+
|
|
8
|
+
from .capabilities import (
|
|
9
|
+
ScrollCapability,
|
|
10
|
+
InputCapability,
|
|
11
|
+
TimingCapability,
|
|
12
|
+
DOMCapability,
|
|
13
|
+
FetchCapability,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from cmdop.services.browser.service.sync import BrowserService
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BrowserSession:
|
|
21
|
+
"""Browser session with grouped capabilities.
|
|
22
|
+
|
|
23
|
+
Core methods (on session directly):
|
|
24
|
+
session.navigate(url)
|
|
25
|
+
session.click(selector)
|
|
26
|
+
session.type(selector, text)
|
|
27
|
+
session.wait_for(selector)
|
|
28
|
+
session.execute_script(js)
|
|
29
|
+
|
|
30
|
+
Capabilities (grouped by function):
|
|
31
|
+
session.scroll.js("down", 500)
|
|
32
|
+
session.scroll.to_bottom()
|
|
33
|
+
session.input.click_js(selector)
|
|
34
|
+
session.input.key("Escape")
|
|
35
|
+
session.timing.wait(1000)
|
|
36
|
+
session.dom.soup()
|
|
37
|
+
session.fetch.json("/api/data")
|
|
38
|
+
|
|
39
|
+
Usage:
|
|
40
|
+
with service.create_session() as session:
|
|
41
|
+
session.navigate("https://example.com")
|
|
42
|
+
session.scroll.js("down", 500)
|
|
43
|
+
session.input.click_js(".button")
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
__slots__ = (
|
|
47
|
+
"_service",
|
|
48
|
+
"_session_id",
|
|
49
|
+
"_scroll",
|
|
50
|
+
"_input",
|
|
51
|
+
"_timing",
|
|
52
|
+
"_dom",
|
|
53
|
+
"_fetch",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def __init__(self, service: "BrowserService", session_id: str) -> None:
|
|
57
|
+
self._service = service
|
|
58
|
+
self._session_id = session_id
|
|
59
|
+
self._scroll: ScrollCapability | None = None
|
|
60
|
+
self._input: InputCapability | None = None
|
|
61
|
+
self._timing: TimingCapability | None = None
|
|
62
|
+
self._dom: DOMCapability | None = None
|
|
63
|
+
self._fetch: FetchCapability | None = None
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def session_id(self) -> str:
|
|
67
|
+
return self._session_id
|
|
68
|
+
|
|
69
|
+
# === Capabilities (lazy init) ===
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def scroll(self) -> ScrollCapability:
|
|
73
|
+
"""Scroll: js(), to_bottom(), to_element(), info(), native(), collect()"""
|
|
74
|
+
if self._scroll is None:
|
|
75
|
+
self._scroll = ScrollCapability(self)
|
|
76
|
+
return self._scroll
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def input(self) -> InputCapability:
|
|
80
|
+
"""Input: click_js(), key(), click_all(), hover(), hover_js()"""
|
|
81
|
+
if self._input is None:
|
|
82
|
+
self._input = InputCapability(self)
|
|
83
|
+
return self._input
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def timing(self) -> TimingCapability:
|
|
87
|
+
"""Timing: wait(), seconds(), random(), timeout()"""
|
|
88
|
+
if self._timing is None:
|
|
89
|
+
self._timing = TimingCapability(self)
|
|
90
|
+
return self._timing
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def dom(self) -> DOMCapability:
|
|
94
|
+
"""DOM: html(), text(), soup(), parse(), select(), close_modal(), extract()"""
|
|
95
|
+
if self._dom is None:
|
|
96
|
+
self._dom = DOMCapability(self)
|
|
97
|
+
return self._dom
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def fetch(self) -> FetchCapability:
|
|
101
|
+
"""Fetch: json(), all(), execute()"""
|
|
102
|
+
if self._fetch is None:
|
|
103
|
+
self._fetch = FetchCapability(self)
|
|
104
|
+
return self._fetch
|
|
105
|
+
|
|
106
|
+
# === Core Methods ===
|
|
107
|
+
|
|
108
|
+
def navigate(self, url: str, timeout_ms: int = 30000) -> str:
|
|
109
|
+
"""Navigate to URL. Returns final URL."""
|
|
110
|
+
return self._service.navigate(self._session_id, url, timeout_ms)
|
|
111
|
+
|
|
112
|
+
def click(self, selector: str, timeout_ms: int = 5000, move_cursor: bool = False) -> None:
|
|
113
|
+
"""Click element by CSS selector."""
|
|
114
|
+
self._service.click(self._session_id, selector, timeout_ms, move_cursor)
|
|
115
|
+
|
|
116
|
+
def type(self, selector: str, text: str, human_like: bool = False, clear_first: bool = True) -> None:
|
|
117
|
+
"""Type text into element."""
|
|
118
|
+
self._service.type(self._session_id, selector, text, human_like, clear_first)
|
|
119
|
+
|
|
120
|
+
def wait_for(self, selector: str, timeout_ms: int = 30000) -> bool:
|
|
121
|
+
"""Wait for element to appear."""
|
|
122
|
+
return self._service.wait_for(self._session_id, selector, timeout_ms)
|
|
123
|
+
|
|
124
|
+
def execute_script(self, script: str) -> str:
|
|
125
|
+
"""Execute raw JavaScript."""
|
|
126
|
+
return self._service.execute_script(self._session_id, script)
|
|
127
|
+
|
|
128
|
+
# === State ===
|
|
129
|
+
|
|
130
|
+
def screenshot(self, full_page: bool = False) -> bytes:
|
|
131
|
+
"""Take screenshot."""
|
|
132
|
+
return self._service.screenshot(self._session_id, full_page)
|
|
133
|
+
|
|
134
|
+
def get_state(self) -> BrowserState:
|
|
135
|
+
"""Get browser state."""
|
|
136
|
+
return self._service.get_state(self._session_id)
|
|
137
|
+
|
|
138
|
+
def get_cookies(self, domain: str = "") -> list[BrowserCookie]:
|
|
139
|
+
"""Get cookies."""
|
|
140
|
+
return self._service.get_cookies(self._session_id, domain)
|
|
141
|
+
|
|
142
|
+
def set_cookies(self, cookies: list[BrowserCookie | dict]) -> None:
|
|
143
|
+
"""Set cookies."""
|
|
144
|
+
self._service.set_cookies(self._session_id, cookies)
|
|
145
|
+
|
|
146
|
+
def get_page_info(self) -> PageInfo:
|
|
147
|
+
"""Get page info."""
|
|
148
|
+
return self._service.get_page_info(self._session_id)
|
|
149
|
+
|
|
150
|
+
# === Internal ===
|
|
151
|
+
|
|
152
|
+
def _call_service(self, method: str, *args: Any, **kwargs: Any) -> Any:
|
|
153
|
+
"""Call service method (used by capabilities)."""
|
|
154
|
+
return getattr(self._service, method)(self._session_id, *args, **kwargs)
|
|
155
|
+
|
|
156
|
+
# === Context Manager ===
|
|
157
|
+
|
|
158
|
+
def close(self) -> None:
|
|
159
|
+
"""Close session."""
|
|
160
|
+
self._service.close_session(self._session_id)
|
|
161
|
+
|
|
162
|
+
def __enter__(self) -> "BrowserSession":
|
|
163
|
+
return self
|
|
164
|
+
|
|
165
|
+
def __exit__(self, *args: Any) -> None:
|
|
166
|
+
self.close()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cmdop
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.22
|
|
4
4
|
Summary: Python SDK for CMDOP agent interaction
|
|
5
5
|
Project-URL: Homepage, https://cmdop.com
|
|
6
6
|
Project-URL: Documentation, https://cmdop.com
|
|
@@ -145,91 +145,100 @@ health: Health = result.output # Typed!
|
|
|
145
145
|
|
|
146
146
|
## Browser
|
|
147
147
|
|
|
148
|
+
Capability-based API for browser automation.
|
|
149
|
+
|
|
148
150
|
```python
|
|
149
|
-
with client.browser.create_session() as
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
with client.browser.create_session() as s:
|
|
152
|
+
s.navigate("https://shop.com/products")
|
|
153
|
+
s.dom.close_modal() # Close popups
|
|
152
154
|
|
|
153
155
|
# BeautifulSoup parsing
|
|
154
|
-
soup =
|
|
156
|
+
soup = s.dom.soup() # SoupWrapper with chainable API
|
|
155
157
|
for item in soup.select(".product"):
|
|
156
158
|
title = item.select_one("h2").text()
|
|
157
159
|
price = item.attr("data-price")
|
|
158
160
|
|
|
159
161
|
# Scrolling with random delays
|
|
160
162
|
for _ in range(10):
|
|
161
|
-
soup =
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
b.wait_random(0.8, 1.5) # Random delay
|
|
163
|
+
soup = s.dom.soup(".listings")
|
|
164
|
+
s.scroll.js("down", 700)
|
|
165
|
+
s.timing.random(0.8, 1.5)
|
|
165
166
|
|
|
166
|
-
# Click with cursor movement
|
|
167
|
-
|
|
167
|
+
# Click with cursor movement
|
|
168
|
+
s.click("button.buy", move_cursor=True)
|
|
168
169
|
|
|
169
170
|
# Click all "See more" buttons
|
|
170
|
-
|
|
171
|
+
s.input.click_all("See more")
|
|
171
172
|
|
|
172
|
-
#
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
# Mouse operations
|
|
174
|
+
s.input.mouse_move(500, 300)
|
|
175
|
+
s.input.hover(".tooltip-trigger")
|
|
175
176
|
|
|
176
177
|
# JS fetch (bypass CORS, inherit cookies)
|
|
177
|
-
data =
|
|
178
|
+
data = s.fetch.json("/api/items")
|
|
178
179
|
```
|
|
179
180
|
|
|
181
|
+
### Core Methods (on session)
|
|
182
|
+
|
|
180
183
|
| Method | Description |
|
|
181
184
|
|--------|-------------|
|
|
182
185
|
| `navigate(url)` | Go to URL |
|
|
183
|
-
| `click(selector, move_cursor)` | Click element
|
|
184
|
-
| `click_all_by_text(text, role)` | Click all matching elements |
|
|
186
|
+
| `click(selector, move_cursor)` | Click element |
|
|
185
187
|
| `type(selector, text)` | Type text |
|
|
186
|
-
| `wait_for(selector
|
|
187
|
-
| `
|
|
188
|
-
| `wait_random(min, max)` | Random sleep |
|
|
189
|
-
| `extract(selector, attr)` | Get text/attr |
|
|
190
|
-
| `get_html(selector)` | Get HTML |
|
|
191
|
-
| `soup(selector)` | → SoupWrapper |
|
|
192
|
-
| `parse_html(html)` | → BeautifulSoup |
|
|
193
|
-
| `fetch_json(url)` | JS fetch → dict |
|
|
194
|
-
| `fetch_all(urls)` | Parallel fetch |
|
|
195
|
-
| `execute_js(code)` | Run async JS |
|
|
188
|
+
| `wait_for(selector)` | Wait for element |
|
|
189
|
+
| `execute_script(js)` | Run JavaScript |
|
|
196
190
|
| `screenshot()` | PNG bytes |
|
|
197
|
-
| `
|
|
198
|
-
| `
|
|
199
|
-
| `get_scroll_info()` | Position + page size |
|
|
200
|
-
| `get_page_info()` | Comprehensive page info |
|
|
201
|
-
| `mouse_move(x, y, steps)` | Move cursor to coordinates |
|
|
202
|
-
| `hover(selector)` | Hover over element |
|
|
203
|
-
| `select(selector, value)` | Dropdown select |
|
|
204
|
-
| `close_modal()` | Close dialogs |
|
|
205
|
-
| `press_key(key, selector)` | Press keyboard key |
|
|
191
|
+
| `get_state()` | URL + title |
|
|
192
|
+
| `get_page_info()` | Full page info |
|
|
206
193
|
| `get/set_cookies()` | Cookie management |
|
|
207
|
-
| `with_timeout(fn, sec, cleanup)` | Run with timeout, skip if hangs |
|
|
208
194
|
|
|
209
|
-
|
|
210
|
-
```python
|
|
211
|
-
# Sync
|
|
212
|
-
result, ok = browser.with_timeout(
|
|
213
|
-
lambda: process_item(browser, item),
|
|
214
|
-
timeout_sec=60,
|
|
215
|
-
on_timeout=lambda: browser.press_key('Escape'),
|
|
216
|
-
)
|
|
217
|
-
if not ok:
|
|
218
|
-
print("Skipped - timed out")
|
|
195
|
+
### Capabilities
|
|
219
196
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
)
|
|
226
|
-
|
|
197
|
+
**`session.scroll`** - Scrolling
|
|
198
|
+
| Method | Description |
|
|
199
|
+
|--------|-------------|
|
|
200
|
+
| `js(dir, amount)` | JS scroll (works on complex sites) |
|
|
201
|
+
| `native(dir, amount)` | Browser API scroll |
|
|
202
|
+
| `to_bottom()` | Scroll to page bottom |
|
|
203
|
+
| `to_element(selector)` | Scroll element into view |
|
|
204
|
+
| `info()` | Get scroll position |
|
|
205
|
+
| `infinite(extract_fn)` | Smart infinite scroll with extraction |
|
|
206
|
+
|
|
207
|
+
**`session.input`** - Input operations
|
|
208
|
+
| Method | Description |
|
|
209
|
+
|--------|-------------|
|
|
210
|
+
| `click_js(selector)` | JS click (reliable) |
|
|
211
|
+
| `click_all(text, role)` | Click all matching elements |
|
|
212
|
+
| `key(key, selector)` | Press keyboard key |
|
|
213
|
+
| `hover(selector)` | Hover over element (native) |
|
|
214
|
+
| `hover_js(selector)` | Hover via JS |
|
|
215
|
+
| `mouse_move(x, y)` | Move cursor to coordinates |
|
|
216
|
+
|
|
217
|
+
**`session.timing`** - Delays
|
|
218
|
+
| Method | Description |
|
|
219
|
+
|--------|-------------|
|
|
220
|
+
| `wait(ms)` | Wait milliseconds |
|
|
221
|
+
| `seconds(n)` | Wait seconds |
|
|
222
|
+
| `random(min, max)` | Random delay |
|
|
223
|
+
| `timeout(fn, sec, cleanup)` | Run with timeout |
|
|
227
224
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
225
|
+
**`session.dom`** - DOM operations
|
|
226
|
+
| Method | Description |
|
|
227
|
+
|--------|-------------|
|
|
228
|
+
| `html(selector)` | Get HTML |
|
|
229
|
+
| `text(selector)` | Get text content |
|
|
230
|
+
| `soup(selector)` | → SoupWrapper |
|
|
231
|
+
| `parse(html)` | → BeautifulSoup |
|
|
232
|
+
| `extract(selector, attr)` | Get text/attr list |
|
|
233
|
+
| `select(selector, value)` | Dropdown select |
|
|
234
|
+
| `close_modal()` | Close dialogs |
|
|
235
|
+
|
|
236
|
+
**`session.fetch`** - HTTP from browser context
|
|
237
|
+
| Method | Description |
|
|
238
|
+
|--------|-------------|
|
|
239
|
+
| `json(url)` | Fetch JSON |
|
|
240
|
+
| `all(requests)` | Parallel fetch |
|
|
241
|
+
| `execute(method, url, ...)` | Custom request |
|
|
233
242
|
|
|
234
243
|
## SDKBaseModel
|
|
235
244
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
cmdop/__init__.py,sha256=
|
|
2
|
-
cmdop/client.py,sha256=
|
|
1
|
+
cmdop/__init__.py,sha256=te8zdIJesHnMNTru-7YrTOnoUObhAm972gTFbhoHW5g,5200
|
|
2
|
+
cmdop/client.py,sha256=nTotStZPBfYN3TrHH-OlEJMSVAXskYMQRkocsFmyaBY,14601
|
|
3
3
|
cmdop/config.py,sha256=vpw1aGCyS4NKlZyzVur81Lt06QmN3FnscZji0bypUi0,4398
|
|
4
4
|
cmdop/discovery.py,sha256=HNxSOa5tSuG7ppfFs21XdviW5ucjpRswVPguhX5j8Dg,7479
|
|
5
5
|
cmdop/exceptions.py,sha256=-ubepNXXpasXDmlKhl3k0MhWRsI6Oj46Ic_jH4VUw-g,10314
|
|
@@ -166,23 +166,27 @@ cmdop/services/base.py,sha256=BCYIUME5gfpDHAief30sQNVzrlAgHx6QGZ6AbLHQx5w,3087
|
|
|
166
166
|
cmdop/services/extract.py,sha256=zwzikEKH4T4OnrprmJg3wqBWQJr-DYsSZgJGK_2yIHU,11119
|
|
167
167
|
cmdop/services/files.py,sha256=RGhfo7tW6diuUWC_EQQ-Y9zO1btm6mBTji0SWWa0fdo,12548
|
|
168
168
|
cmdop/services/terminal.py,sha256=9SSWBexe2rWgMd-hGBEs9mcax3l7x_U84VHZpMC4xK8,17512
|
|
169
|
-
cmdop/services/browser/__init__.py,sha256=
|
|
169
|
+
cmdop/services/browser/__init__.py,sha256=31Ofu9RCYTAedPKLvnor8J7oGDgTjbqJ58OkxxHYwdk,1270
|
|
170
170
|
cmdop/services/browser/models.py,sha256=qJ3da8hPvQn7Vtiqg3xg49G-GioidQGPPuLk2c_IBC4,2656
|
|
171
171
|
cmdop/services/browser/parsing.py,sha256=0hQAy-0ZwJqtmhEqHO3EEdVB3iYmyhXRdouN_dCbig8,3820
|
|
172
|
-
cmdop/services/browser/
|
|
173
|
-
cmdop/services/browser/
|
|
174
|
-
cmdop/services/browser/
|
|
175
|
-
cmdop/services/browser/
|
|
176
|
-
cmdop/services/browser/
|
|
177
|
-
cmdop/services/browser/
|
|
178
|
-
cmdop/services/browser/
|
|
172
|
+
cmdop/services/browser/session.py,sha256=ZFZuzxEUEpwDenigBZdxr5aYePlo69LWre9YIK6LRSM,5363
|
|
173
|
+
cmdop/services/browser/capabilities/__init__.py,sha256=SvaRxAiB8pq671bWtTThVe5BgVg0G-4wAPcgOvu9ab4,334
|
|
174
|
+
cmdop/services/browser/capabilities/_base.py,sha256=mW0jKa2CyvK-8cjenv5JYvuCKiO3rpt5F7WtWFXBitA,749
|
|
175
|
+
cmdop/services/browser/capabilities/_helpers.py,sha256=jXqYbeDocAHec2GwF2_BNnJ78vTyUnHteQoS-RSG00k,488
|
|
176
|
+
cmdop/services/browser/capabilities/dom.py,sha256=DuXfildga23wGBNJWtNzx-t2Cq553HC48o9KAWAlyC0,2612
|
|
177
|
+
cmdop/services/browser/capabilities/fetch.py,sha256=GAjOjk9XkCrMgUzRUrdMmVgOmIClwBWPUnmfA_OqITY,1392
|
|
178
|
+
cmdop/services/browser/capabilities/input.py,sha256=uYmWGqturMDent44Us80oT_nk4kFNGyPJ0P5I35ulew,1749
|
|
179
|
+
cmdop/services/browser/capabilities/scroll.py,sha256=sh0VuOPOv81BZg80-n8TABOj5RpshJT12qJwm4F_OY0,4808
|
|
180
|
+
cmdop/services/browser/capabilities/timing.py,sha256=NH34G_4Kfukh6JCdhLRGoouA-uNTbx9ly7ybP9Kh558,1868
|
|
181
|
+
cmdop/services/browser/js/__init__.py,sha256=gTiZguikKfztDtggZTux2FqhT8YTjyHCzQR4TEnT7z4,1177
|
|
179
182
|
cmdop/services/browser/js/core.py,sha256=QXCCX_al5tMgz7aCwMqhIs1aRe_IdG8teOJniaumA5Q,995
|
|
180
183
|
cmdop/services/browser/js/fetch.py,sha256=WPy_H4LLkneSx06wpfnx4Sx_0Okf2ENXi6bveCd9ZCg,2188
|
|
181
|
-
cmdop/services/browser/js/interaction.py,sha256=
|
|
184
|
+
cmdop/services/browser/js/interaction.py,sha256=qNcs9XwjXZPJfbg8BPeqw5hXya_xTQsHv1T7VWdQ7qY,6620
|
|
182
185
|
cmdop/services/browser/js/scroll.py,sha256=yiOMAaR8ac8jCiWgNCVIt1pUGxdvktMUtzv-AVAE-2Q,7823
|
|
183
|
-
cmdop/services/browser/
|
|
184
|
-
cmdop/services/browser/
|
|
185
|
-
cmdop/services/browser/
|
|
186
|
+
cmdop/services/browser/service/__init__.py,sha256=AZH_r2FsxLfJGCVBaaAPw3dTGaUlgIFdlYd_RR8KxSg,100
|
|
187
|
+
cmdop/services/browser/service/_helpers.py,sha256=w8foDUGZcD4HyF5eyLZUFxbx_fctAFsYRovvsksi3l4,1584
|
|
188
|
+
cmdop/services/browser/service/aio.py,sha256=0E2D4igQb3YzAakdXsRMt8PEd0rFxI2gXfimwq_6nzk,767
|
|
189
|
+
cmdop/services/browser/service/sync.py,sha256=meSoRacS5WVBTABiXopWvTIItzvR7nUiyaxnDuUMoUQ,15466
|
|
186
190
|
cmdop/streaming/__init__.py,sha256=kG9UlJRqv8ndcwKMzWUddPlZT61pFO_Uf_c08A_8TxA,877
|
|
187
191
|
cmdop/streaming/base.py,sha256=r7Q2QlRxgULzs9vlSGcOC_fwAQ_cF3Z3M7WsPQtxG5I,2990
|
|
188
192
|
cmdop/streaming/handlers.py,sha256=FDEhADmCEFRbifvr9dU1X3C-K_96noz89Bl3tuDa_rQ,2616
|
|
@@ -193,7 +197,7 @@ cmdop/transport/base.py,sha256=2pkV8i9epgp_21dyReCfX47abRUrnALm0W5BXb-Fuz0,5571
|
|
|
193
197
|
cmdop/transport/discovery.py,sha256=rcGAuVrR1l6jwcP0dqZxVhX1NsFK7sRHygFMCLmmUbA,10673
|
|
194
198
|
cmdop/transport/local.py,sha256=ob6tWVxSdKwblHSMK8CkgjyuSdQoAeWgy5OAUd5ZNuE,7411
|
|
195
199
|
cmdop/transport/remote.py,sha256=FNVqus9wOv7LlxKarXjLmSyvJiHwhvPbNDOPv1IQkmE,4329
|
|
196
|
-
cmdop-0.1.
|
|
197
|
-
cmdop-0.1.
|
|
198
|
-
cmdop-0.1.
|
|
199
|
-
cmdop-0.1.
|
|
200
|
+
cmdop-0.1.22.dist-info/METADATA,sha256=OTt5H55-dBCDKBLpTJSiNtbsJAz5Wxy9jKTrIb7HTxE,7574
|
|
201
|
+
cmdop-0.1.22.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
202
|
+
cmdop-0.1.22.dist-info/licenses/LICENSE,sha256=6hyzbI1QVXW6B-XT7PaQ6UG9lns11Y_nnap8uUKGUqo,1062
|
|
203
|
+
cmdop-0.1.22.dist-info/RECORD,,
|