simplex 1.2.1__py3-none-any.whl → 1.2.3__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.

Potentially problematic release.


This version of simplex might be problematic. Click here for more details.

simplex/simplex.py CHANGED
@@ -26,12 +26,11 @@ class Simplex:
26
26
  self.driver = self.browser.new_page()
27
27
  else:
28
28
  self.playwright = None
29
- if len(self.browser.contexts) > 0 and len(self.browser.contexts[0].pages) > 0:
30
- self.driver = self.browser.contexts[0].pages[0]
31
- else:
32
- self.driver = self.browser.new_page()
29
+ self.driver = self.browser.contexts[0].pages[0]
30
+ self.driver.set_default_navigation_timeout(0)
31
+ self.driver.set_default_timeout(0)
33
32
 
34
- def find_element(self, element_description: str, state: Image.Image | None = None, annotate: bool = True) -> List[int]:
33
+ def extract_bbox(self, element_description: str, state: Image.Image | None = None, annotate: bool = True) -> List[int]:
35
34
  """
36
35
  Find an element in the screenshot using the element description
37
36
 
@@ -42,6 +41,7 @@ class Simplex:
42
41
  Returns:
43
42
  bounding_box (tuple): [x1, y1, x2, y2] bounding box of the found element
44
43
  """
44
+ print(f"[SIMPLEX] Finding element \"{element_description}\"...")
45
45
  if state is None:
46
46
  state = self.take_stable_screenshot()
47
47
 
@@ -58,7 +58,7 @@ class Simplex:
58
58
  'element_description': (None, element_description),
59
59
  'api_key': (None, self.api_key)
60
60
  }
61
-
61
+ print("[SIMPLEX] Sending screenshot to server...")
62
62
  # Make the request
63
63
  response = requests.post(
64
64
  endpoint,
@@ -67,7 +67,6 @@ class Simplex:
67
67
 
68
68
 
69
69
  # Print the results
70
- print(f"Status Code: {response.status_code}")
71
70
  if response.status_code == 200:
72
71
  res = response.json()
73
72
  bbox = [int(res['x1']), int(res['y1']), int(res['x2']), int(res['y2'])]
@@ -87,7 +86,7 @@ class Simplex:
87
86
  const overlay = document.createElement('div');
88
87
  overlay.id = 'simplex-bbox-overlay';
89
88
  overlay.style.position = 'fixed';
90
- overlay.style.border = '2px dashed rgba(74, 144, 226, 1)';
89
+ overlay.style.border = '2px dashed rgba(0, 255, 0, 1)';
91
90
  overlay.style.background = 'rgba(74, 144, 226, 0.1)';
92
91
  overlay.style.animation = 'marching-ants 0.5s linear infinite';
93
92
  overlay.style.left = bbox[0] + 'px';
@@ -124,7 +123,7 @@ class Simplex:
124
123
  self.driver.wait_for_selector('#simplex-bbox-overlay')
125
124
  return bbox
126
125
  else:
127
- print("Error:", response.text)
126
+ print("[SIMPLEX] Error:", response.text)
128
127
 
129
128
  def step_to_action(self, step_description: str, state: Image.Image | None = None) -> List[List[str]]:
130
129
  """
@@ -168,7 +167,7 @@ class Simplex:
168
167
  actions = [[action.strip() for action in action_pair] for action_pair in actions]
169
168
  return actions
170
169
  else:
171
- print(f"Error: {response.status_code}")
170
+ print(f"[SIMPLEX] Error: {response.status_code}")
172
171
  print(response.text)
173
172
  return []
174
173
 
@@ -182,8 +181,40 @@ class Simplex:
182
181
  """
183
182
  if new_tab:
184
183
  self.driver = self.browser.new_page()
184
+ self.driver.wait_for_load_state()
185
+ print(f"[SIMPLEX] Navigating to URL {url}...")
185
186
  self.driver.goto(url)
186
187
 
188
+ def click(self, element_description: str, annotate: bool = True) -> None:
189
+ """
190
+ Click on an element
191
+ """
192
+ self.execute_action(["CLICK", element_description], annotate=annotate)
193
+
194
+ def type(self, text: str) -> None:
195
+ """
196
+ Type text into an element
197
+ """
198
+ self.execute_action(["TYPE", text])
199
+
200
+ def press_enter(self, annotate: bool = True) -> None:
201
+ """
202
+ Press enter
203
+ """
204
+ self.execute_action(["ENTER", ""], annotate=annotate)
205
+
206
+ def scroll(self, scroll_amount: int, annotate: bool = True) -> None:
207
+ """
208
+ Scroll the page
209
+ """
210
+ self.execute_action(["SCROLL", scroll_amount], annotate=annotate)
211
+
212
+ def wait(self, wait_time: int, annotate: bool = True) -> None:
213
+ """
214
+ Wait for a given amount of time
215
+ """
216
+ self.execute_action(["WAIT", wait_time], annotate=annotate)
217
+
187
218
  def execute_action(self, action: List[List[str]], state: Image.Image | None = None, annotate: bool = True) -> None:
188
219
  """
189
220
  Execute an action with playwright driver
@@ -192,34 +223,30 @@ class Simplex:
192
223
  action (List[List[str]]): List of actions to perform
193
224
  """
194
225
  action_type, description = action
195
- if state is None:
196
- state = self.take_stable_screenshot()
197
-
198
226
  try:
199
227
  if action_type == "CLICK":
200
- bbox = self.find_element(description, state, annotate=annotate)
228
+ bbox = self.extract_bbox(description, state, annotate=annotate)
201
229
  center_x, center_y = center_bbox(bbox)
202
230
  self.driver.mouse.click(center_x, center_y)
203
-
204
- elif action_type == "HOVER":
205
- bbox = self.find_element(description, state, annotate=annotate)
206
- center_x, center_y = center_bbox(bbox)
207
- self.driver.mouse.move(center_x, center_y)
208
-
231
+ print(f"[SIMPLEX] Clicked on element \"{description}\"")
209
232
  elif action_type == "TYPE":
210
233
  self.driver.keyboard.type(description)
234
+ print(f"[SIMPLEX] Typed \"{description}\"")
211
235
 
212
236
  elif action_type == "ENTER":
213
237
  self.driver.keyboard.press("Enter")
238
+ print(f"[SIMPLEX] Pressed enter")
214
239
 
215
240
  elif action_type == "SCROLL":
216
241
  self.driver.mouse.wheel(0, int(description))
242
+ print(f"[SIMPLEX] Scrolled {description} pixels")
217
243
 
218
244
  elif action_type == "WAIT":
219
245
  self.driver.wait_for_timeout(int(description))
246
+ print(f"[SIMPLEX] Waited {description} seconds")
220
247
 
221
248
  except Exception as e:
222
- print(f"Error executing action: {e}")
249
+ print(f"[SIMPLEX] Error executing action: {e}")
223
250
  return None
224
251
 
225
252
  def do(self, step_description: str, annotate: bool = True) -> None:
@@ -230,6 +257,57 @@ class Simplex:
230
257
  actions = self.step_to_action(step_description, state)
231
258
  for action in actions:
232
259
  self.execute_action(action, annotate=annotate)
260
+
261
+ def extract_text(self, element_description: str, state: Image.Image | None = None) -> List[str] | None:
262
+ """
263
+ Extract an element text from the page
264
+ """
265
+ print(f"[SIMPLEX] Finding element \"{element_description}\"...")
266
+ if state is None:
267
+ state = self.take_stable_screenshot()
268
+
269
+ endpoint = f"{BASE_URL}/extract-text"
270
+
271
+ # Convert PIL Image to bytes
272
+ img_byte_arr = io.BytesIO()
273
+ state.save(img_byte_arr, format='PNG')
274
+ img_byte_arr = img_byte_arr.getvalue()
275
+
276
+ # Prepare multipart form data
277
+ files = {
278
+ 'image_data': ('screenshot.png', img_byte_arr, 'image/png'),
279
+ 'element_description': (None, element_description),
280
+ 'api_key': (None, self.api_key)
281
+ }
282
+ print("[SIMPLEX] Sending screenshot to server...")
283
+
284
+ # Make the request
285
+ response = requests.post(
286
+ endpoint,
287
+ files=files
288
+ )
289
+
290
+ # Print the results
291
+ if response.status_code == 200:
292
+ res = response.json()
293
+ text = res['text']
294
+ return text
295
+ else:
296
+ print("[SIMPLEX] Error:", response.text)
297
+ return None
298
+
299
+ def extract_image(self, element_description: str, state: Image.Image | None = None) -> Image.Image | None:
300
+ """
301
+ Extract an element image from the page
302
+ """
303
+ if state is None:
304
+ state = self.take_stable_screenshot()
305
+
306
+ bbox = self.extract_bbox(element_description, state)
307
+ cropped_state = state.crop((bbox[0], bbox[1], bbox[2], bbox[3]))
308
+ return cropped_state
309
+
310
+
233
311
 
234
312
  def take_stable_screenshot(self) -> Image.Image:
235
313
  """
@@ -238,6 +316,7 @@ class Simplex:
238
316
  Returns:
239
317
  PIL.Image.Image: Screenshot of the current page
240
318
  """
319
+ print("[SIMPLEX] Taking screenshot of the page...")
241
320
  self.driver.wait_for_load_state('networkidle')
242
321
  return screenshot_to_image(self.driver.screenshot())
243
322
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: simplex
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: Official Python SDK for Simplex API
5
5
  Home-page: https://github.com/shreyka/simplex-python
6
6
  Author: Simplex Labs, Inc.
@@ -0,0 +1,10 @@
1
+ simplex/__init__.py,sha256=1mbM4XUk0FNW161WOkM4ayC1s_QSsaBEls6PZ0iBScY,74
2
+ simplex/constants.py,sha256=nIXF2oVNNNknXweXAlmE-KBM9QjJtYw9osXVYjvloN0,59
3
+ simplex/simplex.py,sha256=c1kWt8KvOIu-vhVmQga1BH-sRNFHvmWBrfP9t-93iBE,12101
4
+ simplex/utils.py,sha256=UrD4Ena3yk0POmxxyiqMszzPbTscTCJpMP4xZFDAuOc,339
5
+ simplex-1.2.3.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
6
+ simplex-1.2.3.dist-info/METADATA,sha256=HM_H6qRoBXMEtKsO6Ish0NU5V62a7JnugRZmSvGYNMs,1114
7
+ simplex-1.2.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
8
+ simplex-1.2.3.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
9
+ simplex-1.2.3.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
10
+ simplex-1.2.3.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- simplex/__init__.py,sha256=1mbM4XUk0FNW161WOkM4ayC1s_QSsaBEls6PZ0iBScY,74
2
- simplex/constants.py,sha256=nIXF2oVNNNknXweXAlmE-KBM9QjJtYw9osXVYjvloN0,59
3
- simplex/simplex.py,sha256=8LTbvMJUbIWdyAqRKkius-R4PFHZBf4RW_bQZmwd5AY,9275
4
- simplex/utils.py,sha256=UrD4Ena3yk0POmxxyiqMszzPbTscTCJpMP4xZFDAuOc,339
5
- simplex-1.2.1.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
6
- simplex-1.2.1.dist-info/METADATA,sha256=u9gF-wpSwjx0DfsrE5XM-7aRrmFyO5X-6LQ1RagF0tc,1114
7
- simplex-1.2.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
8
- simplex-1.2.1.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
9
- simplex-1.2.1.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
10
- simplex-1.2.1.dist-info/RECORD,,