Skip to content

[py] hold generated BiDi numbers to their declared ranges - #18230

Merged
AutomatedTester merged 2 commits into
trunkfrom
claude/jolly-einstein-hijyeq
Oct 23, 2026
Merged

AutomatedTester merged 2 commits into
trunkfrom
claude/jolly-einstein-hijyeq

Conversation

@AutomatedTester

@AutomatedTester AutomatedTester commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

The generator now combines a field's own min/max/exclusiveMin/exclusiveMax
with those of the alias chain it follows (so maxNodeCount: js-uint .ge 1
is 1..2**53-1) and emits them as field metadata. The serialization runtime
rejects an out-of-range value before sending and on receipt.

Python part of #18195.

@selenium-ci

Copy link
Copy Markdown
Member

/agentic_describe

@selenium-ci

Copy link
Copy Markdown
Member

/agentic_review

@selenium-ci selenium-ci added the C-py Python Bindings label Oct 23, 2026
@CLAassistant

CLAassistant commented Oct 23, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Enforce declared numeric ranges in Python BiDi serialization

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Combine field and alias-chain numeric bounds when generating BiDi field metadata.
• Reject out-of-range numbers before sending commands and when parsing responses.
• Cover inclusive, exclusive, aliased, and list-element bounds in unit tests.
Diagram

graph TD
  Schema["BiDi schema"] --> Generator["Python generator"] --> Metadata["Field metadata"] --> Outbound["Outbound validation"] --> Transport["BiDi transport"] --> Inbound["Inbound validation"]
  Metadata --> Inbound
Loading
High-Level Assessment

Emitting narrowed bounds as field metadata fits the existing generated-code architecture and lets both serialization directions share validation. Loading the schema at runtime would add a dependency without a clear benefit.

Files changed (4) +206 / -2

Bug fix (2) +77 / -1
generate_bidi_protocol.pyEmit narrowed numeric bounds for generated fields +47/-1

Emit narrowed numeric bounds for generated fields

• Collects numeric limits from a field and its alias chain, retaining the tighter limit and exclusive endpoint at a tie. Emits the resulting bounds as field metadata, including for list elements.

py/generate_bidi_protocol.py

serialization.pyValidate numeric bounds in both serialization directions +30/-0

Validate numeric bounds in both serialization directions

• Extends field metadata with inclusive and exclusive limits. Rejects out-of-range numeric values during outbound validation and inbound parsing with field-specific errors.

py/selenium/webdriver/common/_bidi/serialization.py

Tests (2) +129 / -1
bidi_protocol_command_tests.pyTest range enforcement through generated BiDi types +58/-1

Test range enforcement through generated BiDi types

• Exercises alias and field-bound narrowing, exclusive endpoints, pre-send rejection, and rejection of an invalid received response using generated protocol classes.

py/test/unit/selenium/webdriver/common/bidi_protocol_command_tests.py

bidi_serialization_tests.pyTest inclusive, exclusive, and list-element bounds +71/-0

Test inclusive, exclusive, and list-element bounds

• Adds a bounded test record and checks accepted endpoints, rejected values, list elements, and inbound and outbound behavior.

py/test/unit/selenium/webdriver/common/bidi_serialization_tests.py

@qodo-code-review

qodo-code-review Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Bindings accept different numeric values 📘 Rule violation ≡ Correctness
Description
Python now rejects max_node_count=0 and heading=360 through _out_of_bounds, while equivalent
Java and .NET APIs continue accepting those values. Calls using the same BiDi fields therefore
succeed in some Selenium bindings but fail before transmission in Python.
Code

py/selenium/webdriver/common/_bidi/serialization.py[R457-459]

+        bound = _out_of_bounds(w, raw)
+        if bound:
+            raise BiDiSerializationError(f"{cls.__name__}.{name}: {raw!r} is out of range (must be {bound})")
Evidence
The new Python inbound and outbound checks reject values outside generated numeric bounds.
Repository evidence shows Ruby already enforces comparable bounds, while Java accepts
maxNodeCount=0 and .NET does not reject heading=360, so equivalent user inputs have different
outcomes across bindings.

AGENTS.md: Maintain Cross-Binding Consistency for User-Visible Behavior
py/selenium/webdriver/common/_bidi/serialization.py[457-459]
py/selenium/webdriver/common/_bidi/serialization.py[540-542]
py/test/unit/selenium/webdriver/common/bidi_protocol_command_tests.py[189-214]
java/test/org/openqa/selenium/bidi/protocol/input/JsIntRangeTest.java[74-86]
dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs[104-121]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Python runtime now rejects schema-defined out-of-range numeric values, but equivalent Java and .NET bindings still accept some of those values, creating inconsistent user-visible behavior across Selenium bindings.

## Fix Focus Areas
- py/selenium/webdriver/common/_bidi/serialization.py[457-459]
- py/selenium/webdriver/common/_bidi/serialization.py[540-542]
- java/src/org/openqa/selenium/bidi/BiDiGenerator.java[1402-1432]
- dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs[104-121]

## Recommended Fix
Coordinate the numeric-bound behavior across affected language bindings so equivalent BiDi fields enforce the same inclusive and exclusive ranges, or explicitly defer the Python behavior until the other bindings are updated. Add matching focused tests for the affected fields in each binding.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗



Remediation recommended

2. Bounded coordinates can still send NaN ✓ Resolved
Description
_out_of_bounds treats NaN as in range because every comparison with a numeric bound is false. A
caller can set a bounded float such as geolocation heading to float('nan'), and outbound
serialization sends NaN instead of rejecting it; the inbound check likewise accepts it if
received.
Code

py/selenium/webdriver/common/_bidi/serialization.py[R418-421]

+    if w.min is not None and (value <= w.min if w.exclusive_min else value < w.min):
+        return f"{'>' if w.exclusive_min else '>='} {w.min}"
+    if w.max is not None and (value >= w.max if w.exclusive_max else value > w.max):
+        return f"{'<' if w.exclusive_max else '<='} {w.max}"
Evidence
The schema declares heading as a number bounded from 0 to less than 360. The float primitive check
accepts Python floats, while the new range check uses only comparisons, which cannot detect NaN.
Outbound JSON encoding uses json.dumps without disabling NaN serialization.

common/bidi/schema.json[6045-6058]
py/selenium/webdriver/common/_bidi/serialization.py[401-422]
py/selenium/webdriver/common/_bidi/serialization.py[454-459]
py/selenium/webdriver/common/_bidi/serialization.py[534-542]
py/selenium/webdriver/remote/websocket_connection.py[128-133]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Bound comparisons do not reject `NaN`, so bounded numeric fields can accept it on receipt and send it as invalid JSON.
## Fix Focus Areas
- py/selenium/webdriver/common/_bidi/serialization.py[416-422]
- py/test/unit/selenium/webdriver/common/bidi_serialization_tests.py[502-558]
## Recommended Fix
Reject non-finite numeric values in the bounds check before comparing endpoints, preserving `BiDiSerializationError` on both paths. Add inbound and outbound tests using a bounded float field and `float('nan')`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: Auto: 🧠 Deep: Multiple independent generator and runtime validation paths create subtle defect risk.

Grey Divider

Tip of the day
💡 Did you know, you can reply 'qodo' on any finding to push back, ask questions, or dig deeper

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit dd9a6e9 🧠 Deep

Results up to commit 07721fd ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Bounded coordinates can still send NaN ✓ Resolved
Description
_out_of_bounds treats NaN as in range because every comparison with a numeric bound is false. A
caller can set a bounded float such as geolocation heading to float('nan'), and outbound
serialization sends NaN instead of rejecting it; the inbound check likewise accepts it if
received.
Code

py/selenium/webdriver/common/_bidi/serialization.py[R418-421]

+    if w.min is not None and (value <= w.min if w.exclusive_min else value < w.min):
+        return f"{'>' if w.exclusive_min else '>='} {w.min}"
+    if w.max is not None and (value >= w.max if w.exclusive_max else value > w.max):
+        return f"{'<' if w.exclusive_max else '<='} {w.max}"
Evidence
The schema declares heading as a number bounded from 0 to less than 360. The float primitive check
accepts Python floats, while the new range check uses only comparisons, which cannot detect NaN.
Outbound JSON encoding uses json.dumps without disabling NaN serialization.

common/bidi/schema.json[6045-6058]
py/selenium/webdriver/common/_bidi/serialization.py[401-422]
py/selenium/webdriver/common/_bidi/serialization.py[454-459]
py/selenium/webdriver/common/_bidi/serialization.py[534-542]
py/selenium/webdriver/remote/websocket_connection.py[128-133]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Bound comparisons do not reject `NaN`, so bounded numeric fields can accept it on receipt and send it as invalid JSON.
## Fix Focus Areas
- py/selenium/webdriver/common/_bidi/serialization.py[416-422]
- py/test/unit/selenium/webdriver/common/bidi_serialization_tests.py[502-558]
## Recommended Fix
Reject non-finite numeric values in the bounds check before comparing endpoints, preserving `BiDiSerializationError` on both paths. Add inbound and outbound tests using a bounded float field and `float('nan')`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 39e01e6 ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Bindings accept different numeric values 📘 Rule violation ≡ Correctness
Description
Python now rejects max_node_count=0 and heading=360 through _out_of_bounds, while equivalent
Java and .NET APIs continue accepting those values. Calls using the same BiDi fields therefore
succeed in some Selenium bindings but fail before transmission in Python.
Code

py/selenium/webdriver/common/_bidi/serialization.py[R457-459]

+        bound = _out_of_bounds(w, raw)
+        if bound:
+            raise BiDiSerializationError(f"{cls.__name__}.{name}: {raw!r} is out of range (must be {bound})")
Evidence
The new Python inbound and outbound checks reject values outside generated numeric bounds.
Repository evidence shows Ruby already enforces comparable bounds, while Java accepts
maxNodeCount=0 and .NET does not reject heading=360, so equivalent user inputs have different
outcomes across bindings.

AGENTS.md: Maintain Cross-Binding Consistency for User-Visible Behavior
py/selenium/webdriver/common/_bidi/serialization.py[457-459]
py/selenium/webdriver/common/_bidi/serialization.py[540-542]
py/test/unit/selenium/webdriver/common/bidi_protocol_command_tests.py[189-214]
java/test/org/openqa/selenium/bidi/protocol/input/JsIntRangeTest.java[74-86]
dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs[104-121]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Python runtime now rejects schema-defined out-of-range numeric values, but equivalent Java and .NET bindings still accept some of those values, creating inconsistent user-visible behavior across Selenium bindings.

## Fix Focus Areas
- py/selenium/webdriver/common/_bidi/serialization.py[457-459]
- py/selenium/webdriver/common/_bidi/serialization.py[540-542]
- java/src/org/openqa/selenium/bidi/BiDiGenerator.java[1402-1432]
- dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs[104-121]

## Recommended Fix
Coordinate the numeric-bound behavior across affected language bindings so equivalent BiDi fields enforce the same inclusive and exclusive ranges, or explicitly defer the Python behavior until the other bindings are updated. Add matching focused tests for the affected fields in each binding.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗


Results up to commit 8df6456 ⚖️ Balanced


No changes from previous review

Grey Divider

Qodo Logo

The generator now combines a field's own min/max/exclusiveMin/exclusiveMax
with those of the alias chain it follows (so `maxNodeCount: js-uint .ge 1`
is 1..2**53-1) and emits them as field metadata. The serialization runtime
rejects an out-of-range value before sending and on receipt.

Python part of #18195.

Claude-Session: https://claude.ai/code/session_019vA1Mw8jHCvicmtUrR9Fhe
@AutomatedTester
AutomatedTester force-pushed the claude/jolly-einstein-hijyeq branch from 07721fd to 39e01e6 Compare October 23, 2026 05:16
@selenium-ci

Copy link
Copy Markdown
Member

/agentic_review

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 39e01e6

NaN compares false against every bound and an infinity escapes a one-sided
range, so neither was caught by the range check; neither is a JSON number.

Claude-Session: https://claude.ai/code/session_019vA1Mw8jHCvicmtUrR9Fhe
@selenium-ci

Copy link
Copy Markdown
Member

/agentic_review

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 8df6456

@AutomatedTester
AutomatedTester force-pushed the claude/jolly-einstein-hijyeq branch from 8df6456 to dd9a6e9 Compare October 23, 2026 06:19
@selenium-ci

Copy link
Copy Markdown
Member

/agentic_review

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit dd9a6e9

@AutomatedTester
AutomatedTester merged commit fdaebd8 into trunk Oct 23, 2026
40 checks passed
@AutomatedTester
AutomatedTester deleted the claude/jolly-einstein-hijyeq branch October 23, 2026 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-py Python Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants