Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Feat] Helpful error when incorrectly instantiating Index client (#418)
## Problem Sometimes users incorrectly instantiate the Index client like this: ```python import pinecone # Initialize the Index with the host index = pinecone.Index(index_name, host=index_host) ``` Then they will later get an authentication exception when using it, since the `Index` class does not have the configuration values it needs when attempting to perform vector operations. ```python ForbiddenException: (403) Reason: Forbidden HTTP response headers: HTTPHeaderDict({'Date': 'Wed, 13 Nov 2024 02:06:45 GMT', 'Content-Type': 'text/plain', 'Content-Length': '9', 'Connection': 'keep-alive', 'x-pinecone-auth-rejected-reason': 'Wrong API key', 'www-authenticate': 'Wrong API key', 'server': 'envoy'}) HTTP response body: Forbidden ``` ## Solution - Rename the `Index` implementation to `_Index` so that people will not accidentally interact with it. - Add a new stub implementation for `Index` that throws an informative message. Bonus: - Move the Index client docstrings off the implementation class and into a related abstract base class. This wasn't strictly necessary, but I was feeling a bit overwhelmed by the size of the `index.py` file. I copied this approach from the grpc module. pdoc seems to still find and render the docs okay when doing this. ## Usage The error message incorporates the args/kwargs the user was attempting to pass. One positional arg ```python >>> import pinecone >>> i = pinecone.Index('my-index') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__ raise IndexClientInstantiationError(args, kwargs) pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key. INCORRECT USAGE: ``` import pinecone pc = pinecone.Pinecone(api_key='your-api-key') index = pinecone.Index('my-index') ``` CORRECT USAGE: ``` from pinecone import Pinecone pc = Pinecone(api_key='your-api-key') index = pc.Index('my-index') ``` ``` Multiple positional args ```python >>> i = pinecone.Index('my-index', 'https://my-index.blahblah.com') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__ raise IndexClientInstantiationError(args, kwargs) pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key. INCORRECT USAGE: ``` import pinecone pc = pinecone.Pinecone(api_key='your-api-key') index = pinecone.Index('my-index', 'https://my-index.blahblah.com') ``` CORRECT USAGE: ``` from pinecone import Pinecone pc = Pinecone(api_key='your-api-key') index = pc.Index('my-index', 'https://my-index.blahblah.com') ``` ``` One keyword arg: ```python >>> i = pinecone.Index(host='https://my-index.blahblah.com') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__ raise IndexClientInstantiationError(args, kwargs) pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key. INCORRECT USAGE: ``` import pinecone pc = pinecone.Pinecone(api_key='your-api-key') index = pinecone.Index(host='https://my-index.blahblah.com') ``` CORRECT USAGE: ``` from pinecone import Pinecone pc = Pinecone(api_key='your-api-key') index = pc.Index(host='https://my-index.blahblah.com') ``` ``` Multiple kwargs ```python >>> i = pinecone.Index(name='my-index', host='https://my-index.blahblah.com', pool_threads=20) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__ raise IndexClientInstantiationError(args, kwargs) pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key. INCORRECT USAGE: ``` import pinecone pc = pinecone.Pinecone(api_key='your-api-key') index = pinecone.Index(name='my-index', host='https://my-index.blahblah.com', pool_threads=20) ``` CORRECT USAGE: ``` from pinecone import Pinecone pc = Pinecone(api_key='your-api-key') index = pc.Index(name='my-index', host='https://my-index.blahblah.com', pool_threads=20) ``` ``` Mixed args/kwargs ```python >>> i = pinecone.Index('my-index', host='https://my-index.blahblah.com', pool_threads=20) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__ raise IndexClientInstantiationError(args, kwargs) pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key. INCORRECT USAGE: ``` import pinecone pc = pinecone.Pinecone(api_key='your-api-key') index = pinecone.Index('my-index', host='https://my-index.blahblah.com', pool_threads=20) ``` CORRECT USAGE: ``` from pinecone import Pinecone pc = Pinecone(api_key='your-api-key') index = pc.Index('my-index', host='https://my-index.blahblah.com', pool_threads=20) ``` ## Type of Change - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change This change is a UX feature that could be considered breaking if someone was importing `Index` directly and going out of their way to set it up correctly. This was never documented usage, but somebody skilled at reading code could have figured out how to do this.
- Loading branch information