Repository navigation
Instances
In standard Selenium, when you call find_element, you receive a native WebElement object. This object is inherently synchronous and blocking. To support the Trio-based asynchronous architecture and provide Human-like interaction methods, osn-selenium wraps every native Selenium object into a specialized instance wrapper.
The primary goal of the instances package is to ensure that if you are using an asynchronous driver, every object returned by that driver is also asynchronous.
-
Consistency: A
WebElementfound by aTrioThreaddriver will always haveawait element.click(). -
Encapsulation: Raw Selenium objects are hidden inside the wrapper and accessed via the
.legacyproperty when necessary. - Extension: Wrappers allow the library to inject new functionality (like human-like movements) directly into standard objects.
Similar to the WebDrivers, Instance Wrappers follow a strict inheritance structure:
-
abstract/instances/: Defines the "Contract" (e.g.,AbstractWebElement). It specifies which methods must exist. -
instances/unified/: Implements the internal blocking logic (e.g.,_click_impl). This is the Single Source of Truth for how to interact with the underlying Selenium object. -
instances/[sync|trio_threads|trio_bidi]/: The public-facing classes.-
syncclasses call_implmethods directly. -
trio_threadsclasses wrap_implmethods in threads usingTrioThreadMixin. -
trio_bidiUsesTrioBiDiMixinfor synchronization and context management via BiDi Mapping.
-
The framework provides wrappers for almost every component of the WebDriver ecosystem:
| Object Class | Responsibility |
|---|---|
WebElement |
Standard interaction with HTML elements (click, send_keys, etc.). |
ShadowRoot |
Access and search within encapsulated Shadow DOM trees. |
Alert |
Management of JavaScript alert, confirm, and prompt dialogs. |
Browser |
Control over user contexts (profiles) and client windows. |
BrowsingContext |
High-level management of tabs and windows via BiDi protocol. |
Network |
Advanced network interception and authentication handling. |
Storage |
Cookie management with filter and partition support. |
Script |
Execution of JavaScript with preload and console monitoring features. |
Permissions |
Programmatic control over browser API permissions (camera, geo, etc.). |
WebExtension |
Dynamic installation and uninstallation of browser extensions. |
FedCM / Dialog |
Interface for Federated Credential Management interactions. |
Mobile |
Management of mobile-specific contexts and network connection types. |
SwitchTo |
Logic for switching focus between frames, windows, and alerts. |
WebDriverWait |
Explicit wait implementation aware of the chosen architecture. |
ActionChains |
Sequences of complex inputs (includes Human-like behaviors). |
Notice how the interaction changes depending on the wrapper type:
# --- Synchronous Driver ---
element = driver.find_element(By.ID, "submit")
# 'element' is an instances.sync.web_element.WebElement
element.click() # Standard blocking call
# --- Trio (Asynchronous) Driver ---
element = await driver.find_element(By.ID, "submit")
# 'element' is an instances.trio_threads.web_element.WebElement
await element.click() # Non-blocking async callThe osn_selenium/instances/convert.py module is the "glue" of the framework. It handles the transformation between raw Selenium objects and framework wrappers.
Returns the underlying Selenium object (legacy). If the input is already a legacy object or None, it is returned as-is. If it is an osn-selenium wrapper, it returns the .legacy property.
from osn_selenium.instances.convert import get_legacy_instance
# 'element' is an osn-selenium WebElement wrapper
raw_selenium_element = get_legacy_instance(element)
# Now you can use it with native Selenium features
print(type(raw_selenium_element))
# Output: <class 'selenium.webdriver.remote.webelement.WebElement'>The factory for the Synchronous architecture. It takes a raw Selenium object and wraps it in our specialized sync class.
from osn_selenium.instances.sync.web_element import WebElement
from osn_selenium.instances.convert import get_sync_instance_wrapper
# raw_el is a native selenium.webdriver.remote.webelement.WebElement
wrapped_el = get_sync_instance_wrapper(
wrapper_class=WebElement,
legacy_object=raw_el
)
wrapped_el.click() # Now has our framework's featuresThe factory for the Asynchronous architecture. In addition to the raw object, it requires Trio synchronization primitives (lock and limiter) to ensure thread-safe execution within the worker thread pool.
from osn_selenium.instances.trio_threads.web_element import WebElement
from osn_selenium.instances.convert import get_trio_thread_instance_wrapper
# Requires the lock and limiter from the parent driver
wrapped_el = get_trio_thread_instance_wrapper(
wrapper_class=WebElement,
legacy_object=raw_el,
lock=driver.lock,
limiter=driver.capacity_limiter
)
await wrapped_el.click() # Correct async executionYou don't have to worry about passing wrapped objects into other methods. The library handles it automatically:
# If you pass a wrapped element into a script
my_element = await driver.find_element(By.ID, "example")
# The 'execute_script' bridge will automatically call
# get_legacy_instance(my_element) before sending it to the browser.
await driver.execute_script("arguments[0].scrollIntoView();", my_element)