Skip to content

[py] Simplified complicated conditional in __convert_to_local_value function in bidi/script.py using singledispatchmethod #15989

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from

Conversation

sandeepsuryaprasad
Copy link
Contributor

@sandeepsuryaprasad sandeepsuryaprasad commented Jul 2, 2025

User description

🔗 Related Issues

💥 What does this PR do?

In this PR, I have simplified the complicated nested conditional statement in __convert_to_local_value function in bidi/script.py using singledispatchmethod.

🔧 Implementation Notes

In singledispatchmethod the implementation is chosen based on the type of the first argument. If none of type gets matched python will chose to execute default implementation. This implementation makes the code more readable, maintainable and easy to modify in future in case if we have to.

💡 Additional Considerations

🔄 Types of changes

  • Cleanup (formatting, renaming)

PR Type

Other


Description

  • Refactored complex conditional logic using singledispatchmethod

  • Improved code readability and maintainability

  • Added public convert_to_local_value method


Changes diagram

flowchart LR
  A["Complex if-elif chain"] --> B["singledispatchmethod decorator"]
  B --> C["Type-based dispatch"]
  C --> D["Cleaner, maintainable code"]
Loading

Changes walkthrough 📝

Relevant files
Enhancement
script.py
Refactor value conversion using singledispatchmethod         

py/selenium/webdriver/common/bidi/script.py

  • Replaced complex if-elif conditional with singledispatchmethod pattern
  • Created _SupportedTypes helper class with type-specific handlers
  • Added public convert_to_local_value method for external access
  • Imported singledispatchmethod from functools module
  • +74/-45 

    Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • @selenium-ci selenium-ci added C-py Python Bindings B-devtools Includes everything BiDi or Chrome DevTools related labels Jul 2, 2025
    Copy link
    Contributor

    qodo-merge-pro bot commented Jul 2, 2025

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    🎫 Ticket compliance analysis ❌

    1234 - Not compliant

    Non-compliant requirements:

    • Fix JavaScript execution in link's href on click() for Firefox
    • Ensure compatibility with Selenium 2.48+ versions
    • Maintain functionality that worked in version 2.47.1

    5678 - Not compliant

    Non-compliant requirements:

    • Fix ChromeDriver ConnectFailure error on Ubuntu 16.04.4
    • Resolve connection refused errors for subsequent ChromeDriver instances
    • Ensure first ChromeDriver instance works without console errors

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Circular Reference

    The _SupportedTypes class holds a reference to the Script instance and calls back to convert_to_local_value method, creating potential circular references and making the code harder to understand than the original implementation.

    return {"type": "set", "value": [self.script.convert_to_local_value(item) for item in value]}
    API Change

    Adding a public convert_to_local_value method changes the public API of the Script class without clear justification, potentially exposing internal implementation details.

    def convert_to_local_value(self, value) -> dict:
        return self.__convert_to_local_value(value)

    Copy link
    Contributor

    qodo-merge-pro bot commented Jul 2, 2025

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    General
    Cache instance to avoid recreation

    Creating a new _SupportedTypes instance on every call is inefficient. Consider
    initializing it once in the Script class constructor and reusing it to avoid
    repeated object creation overhead.

    py/selenium/webdriver/common/bidi/script.py [402-407]

     def __convert_to_local_value(self, value) -> dict:
         """
         Converts a Python value to BiDi LocalValue format.
         """
    -    supported_types = _SupportedTypes(self)
    -    return getattr(supported_types, "_type")(value)
    +    if not hasattr(self, '_supported_types'):
    +        self._supported_types = _SupportedTypes(self)
    +    return self._supported_types._type(value)

    [To ensure code accuracy, apply this suggestion manually]

    Suggestion importance[1-10]: 6

    __

    Why: This is a valid performance suggestion; creating the _SupportedTypes instance in the __init__ method and reusing it would be more efficient than recreating it on every call.

    Low
    Use direct method access

    Using getattr to access the _type method is unnecessary and less readable.
    Direct method access is cleaner and more efficient since the method is
    guaranteed to exist.

    py/selenium/webdriver/common/bidi/script.py [407]

    -return getattr(supported_types, "_type")(value)
    +return supported_types._type(value)
    • Apply / Chat
    Suggestion importance[1-10]: 5

    __

    Why: The suggestion correctly points out that direct access supported_types._type(value) is more readable and idiomatic than using getattr since the _type method is known to exist.

    Low
    • More

    @cgoldberg
    Copy link
    Contributor

    This implementation makes the code more readable, maintainable and easy to modify in future in case if we have to.

    I think both are complicated, but the original is better.

    @sandeepsuryaprasad
    Copy link
    Contributor Author

    The original nested conditional is really hard to read and trace.. lots of nested indentations.. I feel the new implementation is far more readable and easy to make changes to any specific type in future. Probably I have introduced one more layer of abstraction for maintaining specific type implementation, but it really pays off and reduces maintenance effort in future.

    @p0deje p0deje requested a review from cgoldberg July 4, 2025 02:24
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    B-devtools Includes everything BiDi or Chrome DevTools related C-py Python Bindings Review effort 3/5
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    3 participants