[py] generate the internal BiDi protocol layer from the shared binding-neutral schema - #17761
[py] generate the internal BiDi protocol layer from the shared binding-neutral schema#17761titusfortner wants to merge 4 commits into
Conversation
PR Summary by Qodo[py] Generate internal BiDi protocol layer from the shared binding-neutral schema
AI Description
Diagram
High-Level Assessment
Files changed (41)
|
There was a problem hiding this comment.
Pull request overview
This PR adds a new internal Python WebDriver BiDi protocol layer under selenium.webdriver._bidi, generated from the shared binding-neutral BiDi schema, plus a small handwritten runtime (serialization + transport seam) and Bazel/CI wiring to keep checked-in generated files in sync.
Changes:
- Introduces the generated internal
_bidiprotocol package (domains, types, commands/events metadata) and a handwritten runtime (serialization.py,transport.py). - Wires
RemoteWebDriverto create a per-session_bidi_transportlazily when BiDi is started. - Adds unit + end-to-end tests, plus a
verify-bidi-protocolBazel target and CI step to detect drift/hand-edits.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
py/verify_bidi_protocol.py |
Verifies checked-in _bidi files match generator output. |
py/test/unit/selenium/webdriver/common/bidi_transport_tests.py |
Unit coverage for the handwritten transport/domain seam. |
py/test/unit/selenium/webdriver/common/bidi_serialization_tests.py |
Unit coverage for strict (de)serialization runtime rules. |
py/test/unit/selenium/webdriver/common/bidi_protocol_command_tests.py |
Exercises generated command surfaces over a stand-in transport. |
py/test/selenium/webdriver/common/bidi_protocol_tests.py |
Browser-level sanity checks that generated types round-trip against a real BiDi session. |
py/selenium/webdriver/remote/webdriver.py |
Adds _bidi_transport lifecycle + lazy import/creation in _start_bidi(). |
py/selenium/webdriver/_bidi/__init__.py |
Generated package initializer exporting domain classes. |
py/selenium/webdriver/_bidi/serialization.py |
Handwritten serialization runtime used by generated records/unions (plus registry). |
py/selenium/webdriver/_bidi/transport.py |
Handwritten websocket seam (Transport) and base domain (Domain). |
py/selenium/webdriver/_bidi/browsing_context.py |
Generated browsingContext domain (types + commands + event metadata). |
py/selenium/webdriver/_bidi/bluetooth.py |
Generated bluetooth domain (types + commands + event metadata). |
py/selenium/webdriver/_bidi/browser.py |
Generated browser domain (types + commands). |
py/selenium/webdriver/_bidi/emulation.py |
Generated emulation domain (types + commands). |
py/selenium/webdriver/_bidi/input.py |
Generated input domain (types + commands + event metadata). |
py/selenium/webdriver/_bidi/log.py |
Generated log domain (types + event metadata). |
py/selenium/webdriver/_bidi/network.py |
Generated network domain (types + commands + event metadata). |
py/selenium/webdriver/_bidi/permissions.py |
Generated permissions domain (types + commands). |
py/selenium/webdriver/_bidi/script.py |
Generated script domain (types + commands + event metadata). |
py/selenium/webdriver/_bidi/session.py |
Generated session domain (types + commands). |
py/selenium/webdriver/_bidi/speculation.py |
Generated speculation domain (types + event metadata). |
py/selenium/webdriver/_bidi/storage.py |
Generated storage domain (types + commands). |
py/selenium/webdriver/_bidi/user_agent_client_hints.py |
Generated userAgentClientHints domain (types + commands). |
py/selenium/webdriver/_bidi/web_extension.py |
Generated webExtension domain (types + commands). |
py/BUILD.bazel |
Adds generator target, _bidi library, and verify test; packages _bidi. |
.github/workflows/ci-python.yml |
Runs //py:verify-bidi-protocol in CI alongside unit tests. |
Code Review by Qodo
1.
|
|
The direction of this looks ok so far but need to see how this will be used as that code isn't here |
0760b9a to
ae297f2
Compare
|
PR has a lot of unnecessary files in it now in case you're not aware |
|
@AutomatedTester yes, to work with the latest schema it pulled in #17784 which should merge soon |
6057552 to
a227d86
Compare
@AutomatedTester to clarify, the intention is that our users will write this code if they need it. The usage in selenium will be limited to re-implementing current API and whatever additional facades we agree to, so I can't give examples for any of that yet, bu to give a better view of what usage looks like, I ported all the existing integration tests to use this code. py/test/selenium/webdriver/common/_bidi/. (instantiates A few concrete comparisons
# convenience method — dict in, raw dicts out
nodes = driver.browsing_context.locate_nodes(context=cid, locator={"type": "css", "value": "div.content"})
name = nodes[0]["value"]["localName"]
# generated classes — typed locator in, typed nodes out
nodes = BrowsingContext(driver).locate_nodes(context=cid, locator=CssLocator(value="div.content")).nodes
name = nodes[0].value.local_name
# convenience method — flat bool + folder
driver.browser.set_download_behavior(allowed=True, destination_folder=folder)
# generated classes — pass the typed variant
Browser(driver).set_download_behavior(DownloadBehaviorAllowed(destination_folder=folder)) |
5899a33 to
2b06fe9
Compare
Code Review by Qodo
1.
|
2b06fe9 to
52abe0c
Compare
|
Code review by qodo was updated up to the latest commit 52abe0c |
52abe0c to
dc4cb10
Compare
|
Code review by qodo was updated up to the latest commit dc4cb10 |
|
Code review by qodo was updated up to the latest commit c73c938 |
🔗 Related Issues
objectOnly/preserveExtras/scalarsignals from [rb] add objectOnly/preserveExtras/scalar-primitive BiDi schema signals #17784 (now on trunk).💥 What does this PR do?
selenium.webdriver.common._bidipackage, generated at build time from the shared binding-neutral schema (projected once from the CDDL). The domain modules are not checked in.Domainbase, and the package__init__. These four are the only tracked files in the package; the domain modules are generated and gitignored.✅ Compliance with the behavioral contract (#17786)
This branch meets every behavior in the ADR's conformance table for
py 17761. The two thesnapshot had it failing are now closed by consuming #17784's derived signals, each backed by an
executed test that feeds malformed input and asserts the raise/round-trip (the ADR is
runtime-not-declaration):
(
Union._OBJECT_ONLY, from the schema'sobjectOnly), while a union with a real scalar arm(
input.Origin) still passes scalars through. Map[key, value]entries keep round-trippingbecause the
scalarsignal lets a bare-string key through, checked against its primitive.preserveExtras(extensible ∩ re-sendable), so a received-only type (network.Cookie,session.NewResultCapabilities,storage.PartitionKey) drops unknowns while a re-sendable type(
storage.PartialCookie, proxy configs, …) stores and echoes them.The other ten behaviors were already met and are unchanged.
🔧 Implementation Notes
common/bidicode and its CDDL generator are left untouched — retiring or migrating that is out of scope.common/_bidi/; onlyserialization.py,transport.py,domain.py, and__init__.pyare hand-written and tracked. Regenerate the checked-out tree for local development withbazel run //py:generate-bidi-protocol.common/alongside the existing generatedcommon/bidiandcommon/devtoolspackages, matching the established structure.Transport; the driver owns only the sharedWebSocketConnection(where the id counter and callbacks live). Nothing on the driver imports the generated package, so non-BiDi sessions never load it.Domainbase (the class each generated domain subclasses) lives in its owncommon/_bidi/domain.pymodule.🤖 AI assistance
💡 Additional Considerations
🔄 Types of changes