-
Notifications
You must be signed in to change notification settings - Fork 120
Asyncio vector deletion error #577
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
jhamon
wants to merge
6
commits into
main
Choose a base branch
from
cursor/PIN-12-asyncio-vector-deletion-error-4cfc
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
8ada357
Fix: Gracefully handle _response_info assignment for primitive respon…
cursoragent 2170f4f
Fix lint errors in test_response_info_assignment.py
cursoragent 8647bfd
Remove FIX_SUMMARY.md - not needed in repo
cursoragent c0209e2
Fix resource leak in test_asyncio_api_client_dict_response
cursoragent 817beb1
Add integration tests for async vector deletion
cursoragent ae3145d
Merge branch 'main' into cursor/PIN-12-asyncio-vector-deletion-error-…
jhamon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,227 @@ | ||
| """Test that response_info assignment handles all types correctly""" | ||
| import pytest | ||
| from unittest.mock import Mock | ||
| from pinecone.openapi_support.api_client import ApiClient | ||
| from pinecone.openapi_support.asyncio_api_client import AsyncioApiClient | ||
| from pinecone.config.openapi_configuration import Configuration | ||
|
|
||
|
|
||
| class TestResponseInfoAssignment: | ||
| """Test that _response_info assignment works for all response types""" | ||
|
|
||
| def setup_method(self): | ||
| """Set up test fixtures""" | ||
| self.config = Configuration() | ||
|
|
||
| def test_sync_api_client_dict_response(self, mocker): | ||
| """Test that dict responses get _response_info as a key""" | ||
| api_client = ApiClient(self.config) | ||
|
|
||
| # Mock the request method to return a dict response | ||
| mock_response = Mock() | ||
| mock_response.data = b'{}' | ||
| mock_response.status = 200 | ||
| mock_response.getheaders = Mock(return_value={'x-pinecone-request-latency-ms': '100'}) | ||
| mock_response.getheader = Mock(side_effect=lambda x: 'application/json' if x == 'content-type' else None) | ||
|
|
||
| mocker.patch.object(api_client, 'request', return_value=mock_response) | ||
|
|
||
| # Call the API | ||
| result = api_client.call_api( | ||
| resource_path='/test', | ||
| method='POST', | ||
| response_type=(dict,), | ||
| _return_http_data_only=True, | ||
| ) | ||
|
|
||
| # Verify _response_info is set as a dict key | ||
| assert isinstance(result, dict) | ||
| assert '_response_info' in result | ||
|
|
||
| def test_sync_api_client_string_response(self, mocker): | ||
| """Test that string responses don't cause AttributeError""" | ||
| api_client = ApiClient(self.config) | ||
|
|
||
| # Mock the request method to return a string response | ||
| mock_response = Mock() | ||
| mock_response.data = b'"success"' | ||
| mock_response.status = 200 | ||
| mock_response.getheaders = Mock(return_value={'x-pinecone-request-latency-ms': '100'}) | ||
| mock_response.getheader = Mock(side_effect=lambda x: 'application/json' if x == 'content-type' else None) | ||
|
|
||
| mocker.patch.object(api_client, 'request', return_value=mock_response) | ||
|
|
||
| # This should not raise AttributeError when trying to set _response_info | ||
| try: | ||
| api_client.call_api( | ||
| resource_path='/test', | ||
| method='POST', | ||
| response_type=(str,), | ||
| _return_http_data_only=True, | ||
| _check_type=False, | ||
| ) | ||
| # If we get a string back, it should not have _response_info | ||
| # (we don't check what type we get back because it depends on deserializer behavior) | ||
| except AttributeError as e: | ||
| if "'str' object has no attribute '_response_info'" in str(e): | ||
| pytest.fail(f"Should not raise AttributeError for string response: {e}") | ||
| # Other AttributeErrors may be raised by deserializer for invalid types | ||
|
|
||
| def test_sync_api_client_none_response(self, mocker): | ||
| """Test that None responses are handled correctly""" | ||
| api_client = ApiClient(self.config) | ||
|
|
||
| # Mock the request method to return no content | ||
| mock_response = Mock() | ||
| mock_response.data = b'' | ||
| mock_response.status = 204 | ||
| mock_response.getheaders = Mock(return_value={'x-pinecone-request-latency-ms': '100'}) | ||
| mock_response.getheader = Mock(side_effect=lambda x: None) | ||
|
|
||
| mocker.patch.object(api_client, 'request', return_value=mock_response) | ||
|
|
||
| # This should not raise AttributeError | ||
| try: | ||
| result = api_client.call_api( | ||
| resource_path='/test', | ||
| method='DELETE', | ||
| response_type=None, | ||
| _return_http_data_only=True, | ||
| ) | ||
| assert result is None | ||
| except AttributeError as e: | ||
| pytest.fail(f"Should not raise AttributeError for None response: {e}") | ||
|
|
||
| @pytest.mark.asyncio | ||
| @pytest.mark.skip(reason="Requires asyncio extras") | ||
| async def test_asyncio_api_client_dict_response(self, mocker): | ||
| """Test that dict responses get _response_info as a key in asyncio""" | ||
| api_client = AsyncioApiClient(self.config) | ||
|
|
||
| # Mock the request method to return a dict response | ||
| mock_response = Mock() | ||
| mock_response.data = b'{}' | ||
| mock_response.status = 200 | ||
| mock_response.getheaders = Mock(return_value={'x-pinecone-request-latency-ms': '100'}) | ||
| mock_response.getheader = Mock(side_effect=lambda x: 'application/json' if x == 'content-type' else None) | ||
|
|
||
| async def mock_request(*args, **kwargs): | ||
| return mock_response | ||
|
|
||
| mocker.patch.object(api_client, 'request', side_effect=mock_request) | ||
|
|
||
| # Call the API | ||
| result = await api_client.call_api( | ||
| resource_path='/test', | ||
| method='POST', | ||
| response_type=(dict,), | ||
| _return_http_data_only=True, | ||
| ) | ||
|
|
||
| # Verify _response_info is set as a dict key | ||
| assert isinstance(result, dict) | ||
| assert '_response_info' in result | ||
|
|
||
| await api_client.close() | ||
|
|
||
| @pytest.mark.asyncio | ||
| @pytest.mark.skip(reason="Requires asyncio extras") | ||
| async def test_asyncio_api_client_string_response(self, mocker): | ||
| """Test that string responses don't cause AttributeError in asyncio""" | ||
| api_client = AsyncioApiClient(self.config) | ||
|
|
||
| # Mock the request method to return a string response | ||
| mock_response = Mock() | ||
| mock_response.data = b'"success"' | ||
| mock_response.status = 200 | ||
| mock_response.getheaders = Mock(return_value={'x-pinecone-request-latency-ms': '100'}) | ||
| mock_response.getheader = Mock(side_effect=lambda x: 'application/json' if x == 'content-type' else None) | ||
|
|
||
| async def mock_request(*args, **kwargs): | ||
| return mock_response | ||
|
|
||
| mocker.patch.object(api_client, 'request', side_effect=mock_request) | ||
|
|
||
| # This should not raise AttributeError when trying to set _response_info | ||
| try: | ||
| await api_client.call_api( | ||
| resource_path='/test', | ||
| method='POST', | ||
| response_type=(str,), | ||
| _return_http_data_only=True, | ||
| _check_type=False, | ||
| ) | ||
| # If we get a string back, it should not have _response_info | ||
| except AttributeError as e: | ||
| if "'str' object has no attribute '_response_info'" in str(e): | ||
| pytest.fail(f"Should not raise AttributeError for string response: {e}") | ||
| # Other AttributeErrors may be raised by deserializer for invalid types | ||
| finally: | ||
| await api_client.close() | ||
|
|
||
| @pytest.mark.asyncio | ||
| @pytest.mark.skip(reason="Requires asyncio extras") | ||
| async def test_asyncio_api_client_none_response(self, mocker): | ||
| """Test that None responses are handled correctly in asyncio""" | ||
| api_client = AsyncioApiClient(self.config) | ||
|
|
||
| # Mock the request method to return no content | ||
| mock_response = Mock() | ||
| mock_response.data = b'' | ||
| mock_response.status = 204 | ||
| mock_response.getheaders = Mock(return_value={'x-pinecone-request-latency-ms': '100'}) | ||
| mock_response.getheader = Mock(side_effect=lambda x: None) | ||
|
|
||
| async def mock_request(*args, **kwargs): | ||
| return mock_response | ||
|
|
||
| mocker.patch.object(api_client, 'request', side_effect=mock_request) | ||
|
|
||
| # This should not raise AttributeError | ||
| try: | ||
| result = await api_client.call_api( | ||
| resource_path='/test', | ||
| method='DELETE', | ||
| response_type=None, | ||
| _return_http_data_only=True, | ||
| ) | ||
| assert result is None | ||
| except AttributeError as e: | ||
| pytest.fail(f"Should not raise AttributeError for None response: {e}") | ||
| finally: | ||
| await api_client.close() | ||
|
|
||
| def test_sync_api_client_model_response(self, mocker): | ||
| """Test that OpenAPI model responses get _response_info as an attribute""" | ||
| api_client = ApiClient(self.config) | ||
|
|
||
| # Create a mock model class that supports attribute assignment | ||
| class MockModel: | ||
| def __init__(self): | ||
| pass | ||
|
|
||
| # Mock the request and deserializer | ||
| mock_response = Mock() | ||
| mock_response.data = b'{"test": "value"}' | ||
| mock_response.status = 200 | ||
| mock_response.getheaders = Mock(return_value={'x-pinecone-request-latency-ms': '100'}) | ||
| mock_response.getheader = Mock(side_effect=lambda x: 'application/json' if x == 'content-type' else None) | ||
|
|
||
| mocker.patch.object(api_client, 'request', return_value=mock_response) | ||
|
|
||
| # Mock the deserializer to return a model instance | ||
| mock_model_instance = MockModel() | ||
| mocker.patch('pinecone.openapi_support.deserializer.Deserializer.deserialize', | ||
| return_value=mock_model_instance) | ||
| mocker.patch('pinecone.openapi_support.deserializer.Deserializer.decode_response') | ||
|
|
||
| # Call the API | ||
| result = api_client.call_api( | ||
| resource_path='/test', | ||
| method='GET', | ||
| response_type=(MockModel,), | ||
| _return_http_data_only=True, | ||
| ) | ||
|
|
||
| # Verify _response_info is set as an attribute | ||
| assert hasattr(result, '_response_info') | ||
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.
Uh oh!
There was an error while loading. Please reload this page.