feat(client): add __repr__ to QdrantClient, AsyncQdrantClient, QdrantRemote, AsyncQdrantRemote, QdrantLocal, AsyncQdrantLocal - #1288
Conversation
…Remote, AsyncQdrantRemote, QdrantLocal, AsyncQdrantLocal Default Python repr() on the six client classes was useless (`<qdrant_client.qdrant_client.QdrantClient object at 0x...>`), making debugging, logging, and Jupyter inspection harder than it needs to be. httpx.Client, redis.Redis, and boto3.client all ship with a meaningful __repr__. Add a one-line __repr__ on each class that surfaces the connection info (mode, scheme, host, port, prefer_grpc for remote; location for local; api_key is never included). The facade's __repr__ prefixes the inner client's repr with mode=remote or mode=local so the user can tell at a glance which backend they're talking to. The async client's __repr__ is a regular def, not async def. `repr()` is called synchronously by Python's built-in formatter and the AST transformer keeps __repr__ sync in the async mirror (since it is not in AsyncQdrantBase or AsyncQdrantRemote and not a coroutine function), so no exclude_methods or regen-script sed step is required. Verified the transformer end-to-end. Tests in tests/test_repr.py cover sync and async, local and remote, in-memory and path-based, with api_key masking. 18/18 new tests pass; 46/46 existing tests in test_tracing.py, test_common.py, test_in_memory.py, and test_local_persistence.py still pass. Fixes #1287
✅ Deploy Preview for poetic-froyo-8baba7 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdded Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_repr.py`:
- Line 23: Replace the fixed persistent-local paths in tests/test_repr.py at
lines 23, 88, 102, and 153 with paths derived from the pytest tmp_path fixture.
Update the affected sync and async facade/local test functions to accept
tmp_path and construct each QdrantClient path beneath it, preserving the
existing test behavior without shared filesystem state.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b31b161c-7607-4e63-b787-4acea4bf4ca9
📒 Files selected for processing (7)
qdrant_client/async_qdrant_client.pyqdrant_client/async_qdrant_remote.pyqdrant_client/local/async_qdrant_local.pyqdrant_client/local/qdrant_local.pyqdrant_client/qdrant_client.pyqdrant_client/qdrant_remote.pytests/test_repr.py
All four persistent-local test cases in tests/test_repr.py used hard-coded `/tmp/qdrant` or `/tmp/qdrant_storage` paths. Under parallel test runs those would collide (Ruff S108) and could leak state between test invocations. Switched all four to the `tmp_path` pytest fixture: - TestQdrantClientRepr::test_local_path - TestQdrantLocalRepr::test_path - TestAsyncQdrantClientRepr::test_local_path - TestAsyncQdrantLocalRepr::test_path The :memory: cases are unchanged. 18/18 tests pass.
Summary
Add
__repr__to all 6 client classes so debugging, logging, and Jupyter inspection produce useful output instead of<qdrant_client.qdrant_client.QdrantClient object at 0x...>.Fixes #1287.
Problem
None of the 6 client classes (QdrantClient, AsyncQdrantClient, QdrantRemote, AsyncQdrantRemote, QdrantLocal, AsyncQdrantLocal) implemented
__repr__. Three concrete pain points:<... object at 0x...>instead of the host/mode.clientin a cell prints the memory address.structlog/logurucallrepr()on objects by default.httpx.Client,redis.Redis,boto3.client, andmotor.AsyncIOMotorClientall ship with a meaningful__repr__. This is the standard Python convention.Implementation
One
__repr__method per class. Each is 3-6 lines, all return a string. No new abstractions, no new state, no public API change beyond the special-method names.QdrantRemoteandAsyncQdrantRemoteshowscheme=http host='localhost' port=6333 prefer_grpc=False.QdrantLocalandAsyncQdrantLocalshowlocation=':memory:'orlocation='/tmp/qdrant'.QdrantClientandAsyncQdrantClient(the facades) prefix the inner repr withmode=remoteormode=local.api_keyis never included in the repr — secrets don't belong in reprs (they end up in logs, exception tracebacks, debuggers).Regen
The async files are generated by the AST transformer pipeline. The transformer converts
def Xtoasync def Xonly whenXis inasync_methods(built fromiscoroutinefunctionof the async base class).__repr__is not in any async base and is not a coroutine function, so the transformer leaves it asdef __repr__in the async mirror. Verified the transformer end-to-end with a small test that round-trips aQdrantClientsnippet throughClientFunctionDefTransformer.No
exclude_methodschange, no regen-script sed step, no maintainer documentation burden.Tests
tests/test_repr.py(18 tests) covers:QdrantClientfacade: local:memory:, local path, remote with default args, remote HTTPS with api_key (asserts no leak), remote URL with port.QdrantRemotedirectly: default, prefer_grpc, api_key masking.QdrantLocaldirectly: in-memory, path.AsyncQdrantClientfacade: same matrix.AsyncQdrantRemotedirectly: default with api_key masking.AsyncQdrantLocaldirectly: in-memory, path.repr()returnstr, never a coroutine.All 18 new tests pass; 46 existing tests in
test_tracing.py,test_common.py,test_in_memory.py, andtest_local_persistence.pystill pass.Verification
__repr__sync in the async mirror.Base branch
PR targets
upstream/devper maintainer joein's 2026-07-21 close comment on #1269: "All the PRs should pointdevbranch, not master." Matches the PR template at.github/PULL_REQUEST_TEMPLATE.md:4.Out of scope
__str__(Python convention is to make__str__and__repr__the same unless they serve different audiences; here they don't).closedproperty on the facade classes (orthogonal; thewithblock from feat(client): support context manager on QdrantClient and AsyncQdrantClient #1286 already covers the common case).client_optionsproperty returning connection state (orthogonal; users can already inspectinit_options).