You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Good, the regex match works because re.search does substring matching. Now let me think through the review carefully.
Analysis of the changes:
_real_name property (lines 1108-1113): Gets the JS constructor name for better error messages. Uses a bare except Exception as a fallback, which is reasonable here.
__getitem__ for int keys (lines 1151-1154): When key is an int, it uses bracket indexing on the JS binding instead of getattr. This is the core fix for the toArray() result where arr[0] was failing with "attribute name must be string, not 'int'". Looks correct.
__iter__ (lines 1156-1161): Delegates iteration to the underlying binding, converting each item. Raises a descriptive TypeError if the binding isn't iterable. This is the core fix for for row in cursor.
__len__ (lines 1163-1167): Checks for JS length property and returns it. Raises TypeError if not available.
Potential issues to evaluate:
__len__ returning binding.length: This returns the raw JS value. For a JsProxy, binding.length should return a Python int, so this should be fine. No conversion needed.
__iter__ and _convert_result: Each iterated item goes through _convert_result, which calls python_from_rpc. For SQL cursor rows, these would be JsProxy objects representing row objects. If python_from_rpc can't fully convert them (they remain JsProxy), they'll be re-wrapped as _BindingWrapper. This is actually the correct behavior since the test then accesses row["id"] and row["val"] via __getitem__, which delegates to getattr on the binding.
__getitem__ for int vs str: The int branch does self._binding[key] while the str branch does getattr(self._binding, key). This is correct because JS array-like indexing uses brackets while JS property access uses dot notation (mapped to getattr in Pyodide).
Test coverage: Tests cover iteration (test_sql_cursor_iter), integer indexing via toArray() (test_sql_cursor_toarray_getitem_int), negative tests for non-iterable bindings (test_binding_not_iterable), and non-lennable bindings (test_binding_no_len). Good coverage.
Edge case: __iter__ on something with __iter__ that isn't really iterable? The hasattr(binding, "__iter__") check is reasonable. Pyodide JsProxy objects get __iter__ if the JS object is iterable (has Symbol.iterator).
I don't see any actionable bugs, security issues, backward compatibility problems, or logic errors. The change is well-scoped and the tests are thorough.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes another bug reported in #125
Durable Objects Storage returns a cursor when
ctx.storage.sql.exec("...")is called. This cursor is an iterable that users can dofor row in cursor.However, our
_BindingWrapperdoes not handle iterable correctly, hence users were getting the following error message.