Skip to content
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

[py] BiDi Network implementation of Intercepts and Auth in Python #14592

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

Conversation

shbenzer
Copy link
Contributor

@shbenzer shbenzer commented Oct 13, 2024

User description

Add implementations for BiDi Network's Auth and Interception to Python

Description

Added network.py: Network, Request, and Response classes w/ related methods
Added bidi_network_tests.py

Motivation and Context

Issue #13993

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have read the contributing document.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

PR Type

Enhancement, Tests


Description

  • Implemented a new Network class to handle network events and requests, supporting BiDi protocol operations.
  • Added command constants and mapped them to HTTP methods for network operations.
  • Integrated the Network class into the WebDriver, allowing network interception and authentication handling.
  • Developed tests to verify the new network functionalities, including request interception and authentication.

Changes walkthrough 📝

Relevant files
Enhancement
network.py
Implement Network class for BiDi protocol support               

py/selenium/webdriver/common/bidi/network.py

  • Implemented the Network class for handling network events and
    requests.
  • Added methods for intercepting requests and handling authentication.
  • Introduced event subscription and callback handling.
  • +94/-0   
    command.py
    Add network command constants for BiDi operations               

    py/selenium/webdriver/remote/command.py

  • Added new command constants for network interception and continuation.

  • +5/-1     
    remote_connection.py
    Map network commands to HTTP endpoints                                     

    py/selenium/webdriver/remote/remote_connection.py

    • Mapped new network commands to HTTP methods and endpoints.
    +5/-0     
    webdriver.py
    Integrate Network class into WebDriver                                     

    py/selenium/webdriver/remote/webdriver.py

  • Integrated Network class into WebDriver for BiDi support.
  • Added a property to access network operations.
  • +7/-0     
    Tests
    bidi_network_tests.py
    Add tests for BiDi network functionalities                             

    py/test/selenium/webdriver/common/bidi_network_tests.py

  • Added tests for network interception and continuation functionalities.
  • Verified handling of authentication and request modifications.
  • +49/-0   

    💡 PR-Agent usage: Comment /help "your question" on any pull request to receive relevant information

    Copy link
    Contributor

    qodo-merge-pro bot commented Oct 13, 2024

    PR Reviewer Guide 🔍

    (Review updated until commit 01f6aaf)

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 PR contains tests
    🔒 Security concerns

    Sensitive information exposure:
    The continue_with_auth method in the Network class (py/selenium/webdriver/common/bidi/network.py) handles username and password. While it's not directly exposing this information, care should be taken to ensure these credentials are not logged or stored insecurely during the authentication process.

    ⚡ Recommended focus areas for review

    Error Handling
    The Network class lacks proper error handling and exception raising. This could lead to silent failures or unexpected behavior when network operations fail.

    Type Hinting
    The Network class methods lack type hints, which could make the code harder to understand and maintain, especially for complex objects like 'conn'.

    Test Coverage
    While basic tests are implemented, there's a lack of comprehensive test cases covering edge cases, error scenarios, and all network events.

    Copy link
    Contributor

    qodo-merge-pro bot commented Oct 13, 2024

    PR Code Suggestions ✨

    Latest suggestions up to 01f6aaf
    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    Best practice
    Add input validation to network operation methods to prevent issues caused by invalid parameters

    Consider adding input validation for the parameters in methods like
    continue_response, continue_request, and add_intercept. This can help prevent issues
    caused by invalid input and improve the overall robustness of the code.

    py/selenium/webdriver/common/bidi/network.py [39-48]

     def continue_response(self, request_id, status_code, headers=None, body=None):
    +    if not isinstance(request_id, str) or not request_id:
    +        raise ValueError("request_id must be a non-empty string")
    +    if not isinstance(status_code, int) or status_code < 100 or status_code >= 600:
    +        raise ValueError("status_code must be a valid HTTP status code")
         params = {
             'requestId': request_id,
             'status': status_code
         }
         if headers is not None:
    +        if not isinstance(headers, dict):
    +            raise ValueError("headers must be a dictionary")
             params['headers'] = headers
         if body is not None:
    +        if not isinstance(body, (str, bytes)):
    +            raise ValueError("body must be a string or bytes")
             params['body'] = body
         self.conn.execute('network.continueResponse', params)
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: Input validation is crucial for preventing errors and ensuring that methods receive valid data. This suggestion enhances the robustness and reliability of the code by checking parameter types and values before proceeding with network operations.

    8
    Enhancement
    Implement robust error handling for network operations to improve reliability and debugging

    Consider using a more robust error handling mechanism for the network operations.
    Wrap the self.conn.execute() calls in try-except blocks to catch and handle
    potential exceptions, providing more informative error messages or logging.

    py/selenium/webdriver/common/bidi/network.py [48]

    -self.conn.execute('network.continueResponse', params)
    +try:
    +    self.conn.execute('network.continueResponse', params)
    +except Exception as e:
    +    logging.error(f"Failed to continue response: {str(e)}")
    +    raise
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: Adding error handling around network operations can improve the robustness of the code by catching and logging exceptions, which aids in debugging and ensures that the application can handle unexpected issues gracefully.

    7
    ✅ Add a method to remove event listeners, improving flexibility in event management
    Suggestion Impact:The commit introduced methods to remove event handlers, such as `remove_authentication_handler`, `remove_request_handler`, and `remove_response_handler`, which align with the suggestion to provide more flexibility in managing event subscriptions.

    code diff:

    +    def remove_authentication_handler(self, username,):
    +        """Removes an authentication handler."""
    +        self.__remove_intercept(intercept='auth_required')
    +        del self.subscriptions['auth_required']
    +        session_unsubscribe(self.conn, self.EVENTS['auth_required'])
    +
    +    def add_request_handler(self, callback, url_pattern=''):
    +        """
    +        Adds a request handler that executes a callback function when a request matches the given URL pattern.
    +
    +        Parameters:
    +            callback (function): A function to be executed when url is matched by a URL pattern
    +                The callback function receives a `Response` object as its argument.
    +            url_pattern (str, optional): A substring to match against the response URL.
    +                Default is an empty string, which matches all URLs.
    +
    +        Returns:
    +            str: The request ID of the intercepted response.
    +        """
    +        self.__add_intercept(phases=[self.PHASES['before_request']])
    +        def callback_on_url_match(data):
    +            if url_pattern in data['request']['url']:
    +                # create request object to pass to callback
    +                request_id = data['request'].get('requestId')
    +                url = data['request'].get('url')
    +                method = data['request'].get('method')
    +                headers = data['request'].get('headers', {})
    +                body = data['request'].get('postData', None)
    +                request = Request(request_id, url, method, headers, body, self)
    +                callback(request)
    +        self.__on('before_request', callback_on_url_match)
    +        self.callbacks[request_id] = callback
    +        if 'before_request' not in self.subscriptions or not self.subscriptions.get('before_request'):
    +            self.subscriptions['before_request'] = [request_id]
    +        else:
    +            self.subscriptions['before_request'].append(request_id)
    +        return request_id
    +
    +    def remove_request_handler(self, request_id):
    +        """Removes a request handler."""
    +        self.__remove_intercept(request_id=request_id)
    +        self.subscriptions['before_request'].remove(request_id)
    +        del self.callbacks[request_id]
    +        if len(self.subscriptions['before_request']) == 0:
    +            session_unsubscribe(self.conn, self.EVENTS['before_request']) 
    +
    +    def add_response_handler(self, callback, url_pattern=''):
    +        """
    +        Adds a response handler that executes a callback function when a response matches the given URL pattern.
    +
    +        Parameters:
    +            callback (function): A function to be executed when url is matched by a url_pattern
    +                The callback function receives a `Response` object as its argument.
    +            url_pattern (str, optional): A substring to match against the response URL.
    +                Default is an empty string, which matches all URLs.
    +
    +        Returns:
    +            str: The request ID of the intercepted response.
    +        """
    +        self.__add_intercept(phases=[self.PHASES['response_started']])
    +        def callback_on_url_match(data):
    +            # create response object to pass to callback
    +            if url_pattern in data['response']['url']:
    +                request_id = data['request'].get('requestId')
    +                url = data['response'].get('url')
    +                status_code = data['response'].get('status')
    +                body = data['response'].get('body', None)
    +                headers = data['response'].get('headers', {})
    +                response = Response(request_id, url, status_code, headers, body, self)
    +                callback(response)
    +        self.__on('response_started', callback_on_url_match)
    +        self.callbacks[request_id] = callback
    +        if 'response_started' not in self.subscriptions or not self.subscriptions.get('response_started'):
    +            self.subscriptions['response_started'] = [request_id]
    +        else:
    +            self.subscriptions['response_started'].append(request_id)
    +        return request_id
    +
    +    def remove_response_handler(self, response_id):
    +        """Removes a response handler."""
    +        self.__remove_intercept(request_id=response_id)
    +        self.subscriptions['response_started'].remove(response_id)
    +        del self.callbacks[response_id]
    +        if len(self.subscriptions['response_started']) == 0:
    +            session_unsubscribe(self.conn, self.EVENTS['response_started']) 

    Consider implementing a method to remove all event listeners for a specific event or
    all events. This would provide more flexibility in managing event subscriptions and
    prevent potential memory leaks.

    py/selenium/webdriver/common/bidi/network.py [91-94]

     def on(self, event, callback):
         event = self.EVENTS.get(event, event)
         self.callbacks[event] = callback
         session_subscribe(self.conn, event, self.handle_event)
     
    +def off(self, event=None):
    +    if event:
    +        event = self.EVENTS.get(event, event)
    +        if event in self.callbacks:
    +            del self.callbacks[event]
    +            session_unsubscribe(self.conn, event, self.handle_event)
    +    else:
    +        for event in list(self.callbacks.keys()):
    +            session_unsubscribe(self.conn, event, self.handle_event)
    +        self.callbacks.clear()
    +
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: Implementing a method to remove event listeners provides better control over event management and can prevent potential memory leaks. This enhancement increases the flexibility and maintainability of the code.

    7
    Expand test coverage to include various scenarios and edge cases for network operations

    Enhance the test coverage by adding more comprehensive test cases for different
    scenarios, including edge cases and error conditions. This will help ensure the
    robustness of the network functionality.

    py/test/selenium/webdriver/common/bidi_network_tests.py [27-32]

    -def test_continue_response(driver, network):
    +@pytest.mark.parametrize("status_code,expected_text", [
    +    (200, "authorized"),
    +    (401, "unauthorized"),
    +    (500, "server error")
    +])
    +def test_continue_response(driver, network, status_code, expected_text):
         network.add_intercept(phases=[Network.PHASES['before_request']])
    -    network.on('before_request', lambda event: network.continue_response(event['requestId'], 200))
    +    network.on('before_request', lambda event: network.continue_response(event['requestId'], status_code))
         
         driver.get(url_for("basicAuth"))
    -    assert driver.find_element_by_tag_name('h1').text == 'authorized'
    +    assert expected_text in driver.page_source.lower()
    • Apply this suggestion
    Suggestion importance[1-10]: 6

    Why: Enhancing test coverage by including different scenarios and edge cases can significantly improve the reliability of the network functionality. This suggestion is valuable for ensuring that the code behaves correctly under various conditions.

    6

    💡 Need additional feedback ? start a PR chat


    Previous suggestions

    ✅ Suggestions up to commit 14bf971
    CategorySuggestion                                                                                                                                    Score
    Possible issue
    Validate input parameters to prevent potential issues with invalid data being passed to the BiDi protocol

    Consider implementing input validation for the add_intercept method to ensure that
    the provided phases are valid according to the PHASES dictionary. This can prevent
    potential issues with invalid phase names being passed to the BiDi protocol.

    py/selenium/webdriver/common/bidi/network.py [68-76]

     def add_intercept(self, phases=None, contexts=None, url_patterns=None):
         if phases is None:
             phases = []
    +    else:
    +        valid_phases = set(self.PHASES.values())
    +        if not all(phase in valid_phases for phase in phases):
    +            raise ValueError(f"Invalid phase(s) provided. Valid phases are: {', '.join(valid_phases)}")
         params = {
             'phases': phases,
             'contexts': contexts,
             'urlPatterns': url_patterns
         }
         self.conn.execute('network.addIntercept', params)
    Suggestion importance[1-10]: 8

    Why: Implementing input validation for the add_intercept method is a valuable enhancement that prevents invalid phase names from causing issues. This suggestion addresses a potential bug and improves the method's robustness.

    8
    Enhancement
    Implement error handling for network operations to improve robustness and prevent unexpected crashes

    Consider using a more robust error handling mechanism for the network operations.
    Wrap the self.conn.execute() calls in try-except blocks to catch and handle
    potential exceptions, ensuring graceful error handling and preventing crashes.

    py/selenium/webdriver/common/bidi/network.py [43-52]

     def continue_response(self, request_id, status_code, headers=None, body=None):
         params = {
             'requestId': request_id,
             'status': status_code
         }
         if headers is not None:
             params['headers'] = headers
         if body is not None:
             params['body'] = body
    -    self.conn.execute('network.continueResponse', params)
    +    try:
    +        self.conn.execute('network.continueResponse', params)
    +    except Exception as e:
    +        logging.error(f"Error in continue_response: {str(e)}")
    +        raise
    Suggestion importance[1-10]: 7

    Why: Adding error handling to network operations can improve the robustness of the code by preventing crashes due to unhandled exceptions. This suggestion is relevant and enhances the reliability of the continue_response method.

    7
    ✅ Enhance test assertions to provide more comprehensive verification of network interception behavior
    Suggestion Impact:The commit added more comprehensive assertions to verify network interception behavior, such as checking the status of responses and the method of requests, which aligns with the suggestion to enhance test assertions.

    code diff:

    +def test_add_response_handler(response):
    +    passed = [False]
     
    -def test_continue_request(driver, network):
    -    network.add_intercept(phases=[Network.PHASES['before_request']])
    -    network.on('before_request', lambda event: network.continue_request(event['requestId'], url=url_for("basicAuth")))
    -    
    -    driver.get(url_for("basicAuth"))
    -    assert driver.find_element_by_tag_name('h1').text == 'authorized'
    +    def callback(event):
    +        if event['response']['status'] == 200:
    +            passed[0] = True
     
    -def test_continue_with_auth(driver, network):
    -    username = 'your_username'
    -    password = 'your_password'
    -    
    -    network.add_intercept(phases=[Network.PHASES['auth_required']])
    -    network.on('auth_required', lambda event: network.continue_with_auth(event['requestId'], username, password))
    -    
    -    driver.get(url_for("basicAuth"))
    -    assert driver.find_element_by_tag_name('h1').text == 'authorized'+    network_response.add_response_handler(callback)
    +    pages.load("basicAuth")
    +    assert passed[0] == True, "Callback was NOT successful"
    +
    +def test_remove_response_handler(response):
    +    passed = [False]
    +
    +    def callback(event):
    +        if event['response']['status'] == 200:
    +            passed[0] = True
    +
    +    network_response.add_response_handler(callback)
    +    network_response.remove_response_handler(callback)
    +    pages.load("basicAuth")
    +    assert passed[0] == False, "Callback was successful"
    +
    +def test_add_request_handler(request):
    +    passed = [False]
    +
    +    def callback(event):
    +        if event['request']['method'] == 'GET':
    +            passed[0] = True
    +
    +    network_request.add_request_handler(callback)
    +    pages.load("basicAuth")
    +    assert passed[0] == True, "Callback was NOT successful"
    +
    +def test_remove_request_handler(request):
    +    passed = [False]
    +
    +    def callback(event):
    +        if event['request']['method'] == 'GET':
    +            passed[0] = True
    +
    +    network_request.add_request_handler(callback)
    +    network_request.remove_request_handler(callback)
    +    pages.load("basicAuth")
    +    assert passed[0] == False, "Callback was successful"
    +
    +def test_add_authentication_handler(network):
    +    network.add_authentication_handler('test','test')
    +    pages.load("basicAuth")
    +    assert driver.find_element_by_tag_name('h1').text == 'authorized', "Authentication was NOT successful"
    +
    +def test_remove_authentication_handler(network):
    +    network.add_authentication_handler('test', 'test')
    +    network.remove_authentication_handler()
    +    pages.load("basicAuth")

    Consider adding more comprehensive assertions to verify the behavior of network
    interceptions. This could include checking the content of intercepted requests or
    responses, verifying headers, or ensuring that the correct number of interceptions
    occur.

    py/test/selenium/webdriver/common/bidi_network_tests.py [29-34]

     def test_continue_response(driver, network):
    +    intercepted_requests = []
         network.add_intercept(phases=[Network.PHASES['before_request']])
    +    network.on('before_request', lambda event: intercepted_requests.append(event))
         network.on('before_request', lambda event: network.continue_response(event['requestId'], 200))
         
         driver.get(url_for("basicAuth"))
         assert driver.find_element_by_tag_name('h1').text == 'authorized'
    +    assert len(intercepted_requests) > 0, "No requests were intercepted"
    +    assert intercepted_requests[0]['request']['url'] == url_for("basicAuth"), "Unexpected URL intercepted"
    Suggestion importance[1-10]: 7

    Why: Adding more comprehensive assertions in tests improves the verification of network interception behavior, ensuring the tests are more thorough and reliable. This suggestion enhances the quality of the test suite.

    7
    Best practice
    Use a context manager for WebDriver instances to ensure proper resource cleanup

    Consider using a context manager for the WebDriver instance to ensure proper
    cleanup, even if an exception occurs during the test. This can help prevent resource
    leaks and improve test reliability.

    py/test/selenium/webdriver/common/bidi_network_tests.py [11-16]

     @pytest.fixture
     def driver():
         options = webdriver.ChromeOptions()
         options.add_argument('--remote-debugging-port=9222')
    -    driver = webdriver.Chrome(options=options)
    -    yield driver
    -    driver.quit()
    +    with webdriver.Chrome(options=options) as driver:
    +        yield driver
    Suggestion importance[1-10]: 6

    Why: Using a context manager for the WebDriver instance ensures proper cleanup and resource management, even if exceptions occur. This suggestion follows best practices for resource handling in tests.

    6

    @shbenzer shbenzer marked this pull request as draft October 18, 2024 22:52
    @shbenzer
    Copy link
    Contributor Author

    shbenzer commented Oct 18, 2024

    was adding this to BUILD.bazel for easy testing:

    py_test(
        name = "bidi_network_tests",
        srcs = ["test/selenium/webdriver/common/bidi_network_tests.py"],
        deps = [
            ":init-tree",
            ":selenium",
            ":webserver",
        ] + TEST_DEPS,
    )
    

    so i could run bazel test //py:bidi_network_tests

    @shbenzer
    Copy link
    Contributor Author

    shbenzer commented Oct 18, 2024

    Think it's ready now... @AutomatedTester could you give it a look?

    @shbenzer shbenzer marked this pull request as ready for review October 18, 2024 23:21
    Copy link
    Contributor

    Persistent review updated to latest commit 01f6aaf

    @shbenzer
    Copy link
    Contributor Author

    I think I figured it out, could you run the merge workflow again @pujagani ?

    @shbenzer
    Copy link
    Contributor Author

    @p0deje hoping this fix does it - if you have a better idea let me know

    @shbenzer
    Copy link
    Contributor Author

    Able to initialize connections now. However connections are getting lost because of InvalidArgumentExceptions

    py/test/selenium/webdriver/common/bidi_network_tests.py::test_remove_authentication_handler[chrome] FAILED [100%]
    __________________ test_remove_authentication_handler[chrome] __________________
    
    driver = <selenium.webdriver.chrome.webdriver.WebDriver (session="0ad0ececb7125dcf6a0e586d8bde047c")>
    pages = <conftest.pages.<locals>.Pages object at 0x1079a4a60>
    
        @pytest.mark.xfail_safari
        def test_remove_authentication_handler(driver, pages):
    >       driver.network.add_authentication_handler('test', 'test')
    
    py/test/selenium/webdriver/common/bidi_network_tests.py:87: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    py/selenium/webdriver/common/bidi/network.py:102: in add_authentication_handler
        self.__add_intercept(phases=[self.PHASES['auth_required']])
    py/selenium/webdriver/common/bidi/network.py:57: in __add_intercept
        self.conn.execute(command)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    self = <selenium.webdriver.remote.websocket_connection.WebSocketConnection object at 0x1079a47f0>
    command = {'command': 'network.addIntercept', 'id': 2, 'params': {'contexts': None, 'phases': ['authRequired'], 'urlPatterns': None}}
    
        def execute(self, command):
            self._id += 1
            payload = self._serialize_command(command)
            payload["id"] = self._id
            if self.session_id:
                payload["sessionId"] = self.session_id
        
            data = json.dumps(payload)
            logger.debug(f"-> {data}"[: self._max_log_message_size])
            self._ws.send(data)
        
            self._wait_until(lambda: self._id in self._messages)
            response = self._messages.pop(self._id)
        
            if "error" in response:
    >           raise Exception(response["error"])
    E           Exception: invalid argument
    
    py/selenium/webdriver/remote/websocket_connection.py:67: Exception
    
    ------------------------------ live log logreport ------------------------------
    ERROR    websocket:_logging.py:77 Connection to remote host was lost. - goodbye
    
    =========================== short test summary info ============================
    FAILED py/test/selenium/webdriver/common/bidi_network_tests.py::test_add_response_handler[chrome]
    FAILED py/test/selenium/webdriver/common/bidi_network_tests.py::test_remove_response_handler[chrome]
    FAILED py/test/selenium/webdriver/common/bidi_network_tests.py::test_add_request_handler[chrome]
    FAILED py/test/selenium/webdriver/common/bidi_network_tests.py::test_remove_request_handler[chrome]
    FAILED py/test/selenium/webdriver/common/bidi_network_tests.py::test_add_authentication_handler[chrome]
    FAILED py/test/selenium/webdriver/common/bidi_network_tests.py::test_remove_authentication_handler[chrome]
    ========================= 6 failed, 1 passed in 19.79s =========================
    

    @shbenzer
    Copy link
    Contributor Author

    shbenzer commented Nov 18, 2024

    @p0deje

    Current status: Only 1 test is currently passing (test_network_initialized()), however the browser now recognizes commands as legitimate seemingly. I am not sure why callbacks are not being called, as the returned request_ids from add_request/response_handler() are Null

    Possible causes:

    • race-conditions (should we make implementation async again?)
    • incorrect implementation of add_intercept (could be why auth handler is not working in pages.load(basicAuth))

    @p0deje
    Copy link
    Member

    p0deje commented Nov 18, 2024

    @shbenzer You might need to add some waits to give the time for the callback to be called. Start by adding sleep(5) and see if it stabilizes the test. If yes, you can figure out a better waiting strategy. If no, there is probably something wrong with the implementation itself.

    @shbenzer
    Copy link
    Contributor Author

    @p0deje Tried some sleeps (e.g.

    @pytest.mark.xfail_safari
    def test_add_response_handler(driver, pages):
        passed = [False]
    
        def callback(response):
            passed[0] = True
            response.continue_response()
    
        driver.network.add_response_handler(callback)
        pages.load("basicAuth")
        sleep(10)
        assert passed[0], "Callback was NOT successful"
    

    and failures persist

    @shbenzer
    Copy link
    Contributor Author

    @aguspe you have any suggestions?

    @VietND96 VietND96 added the C-py label Nov 19, 2024
    @p0deje
    Copy link
    Member

    p0deje commented Dec 19, 2024

    @shbenzer Any chance you could take a look at #14900? The implementation @aguspe made works and you can follow it to make the Python bindings part.

    @aguspe
    Copy link
    Contributor

    aguspe commented Dec 19, 2024

    Oh sorry @shbenzer I think I got your notification lost and I marked everything as read :)

    I can give it a deeper look over the weekend, but maybe the issue is here:

    def __on(self, event, callback): """Set a callback function to subscribe to a network event.""" event = self.EVENTS.get(event, event) self.callbacks[event] = callback if len(self.subscriptions[event]) == 0: session_subscribe(self.conn, event, self.__handle_event)

    The part that confused me the most was not how to add a callback, but also to have the listener listening for the event, it looks right but maybe you can print out to the console the responses and the requests

    I noticed a couple of errors while I was implementing it, and by debugging it that way I noticed that I was using the listener wrongly :)

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    5 participants