Skip to content

feat(client): add __repr__ to QdrantClient, AsyncQdrantClient, QdrantRemote, AsyncQdrantRemote, QdrantLocal, AsyncQdrantLocal - #1288

Closed
Harsh23Kashyap wants to merge 2 commits into
qdrant:devfrom
Harsh23Kashyap:feat/client-repr
Closed

feat(client): add __repr__ to QdrantClient, AsyncQdrantClient, QdrantRemote, AsyncQdrantRemote, QdrantLocal, AsyncQdrantLocal#1288
Harsh23Kashyap wants to merge 2 commits into
qdrant:devfrom
Harsh23Kashyap:feat/client-repr

Conversation

@Harsh23Kashyap

Copy link
Copy Markdown

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:

  1. Debugging. Exception logs show <... object at 0x...> instead of the host/mode.
  2. Jupyter. client in a cell prints the memory address.
  3. Structured logging. structlog/loguru call repr() on objects by default.

httpx.Client, redis.Redis, boto3.client, and motor.AsyncIOMotorClient all 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.

  • QdrantRemote and AsyncQdrantRemote show scheme=http host='localhost' port=6333 prefer_grpc=False.
  • QdrantLocal and AsyncQdrantLocal show location=':memory:' or location='/tmp/qdrant'.
  • QdrantClient and AsyncQdrantClient (the facades) prefix the inner repr with mode=remote or mode=local.

api_key is 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 X to async def X only when X is in async_methods (built from iscoroutinefunction of the async base class). __repr__ is not in any async base and is not a coroutine function, so the transformer leaves it as def __repr__ in the async mirror. Verified the transformer end-to-end with a small test that round-trips a QdrantClient snippet through ClientFunctionDefTransformer.

No exclude_methods change, no regen-script sed step, no maintainer documentation burden.

Tests

tests/test_repr.py (18 tests) covers:

  • QdrantClient facade: local :memory:, local path, remote with default args, remote HTTPS with api_key (asserts no leak), remote URL with port.
  • QdrantRemote directly: default, prefer_grpc, api_key masking.
  • QdrantLocal directly: in-memory, path.
  • AsyncQdrantClient facade: same matrix.
  • AsyncQdrantRemote directly: default with api_key masking.
  • AsyncQdrantLocal directly: in-memory, path.
  • Sync and async repr() return str, never a coroutine.

All 18 new tests pass; 46 existing tests in test_tracing.py, test_common.py, test_in_memory.py, and test_local_persistence.py still pass.

Verification

  • mypy clean on all 6 modified files.
  • ruff check + format clean on the new test file.
  • AST transformer verified to leave __repr__ sync in the async mirror.

Base branch

PR targets upstream/dev per maintainer joein's 2026-07-21 close comment on #1269: "All the PRs should point dev branch, 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).
  • closed property on the facade classes (orthogonal; the with block from feat(client): support context manager on QdrantClient and AsyncQdrantClient #1286 already covers the common case).
  • A client_options property returning connection state (orthogonal; users can already inspect init_options).

…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
@netlify

netlify Bot commented Jul 28, 2026

Copy link
Copy Markdown

Deploy Preview for poetic-froyo-8baba7 ready!

Name Link
🔨 Latest commit 2ff3531
🔍 Latest deploy log https://app.netlify.com/projects/poetic-froyo-8baba7/deploys/6a68fca0b88f110008307187
😎 Deploy Preview https://deploy-preview-1288--poetic-froyo-8baba7.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 80537598-9c24-4234-87e4-f493a60e7d14

📥 Commits

Reviewing files that changed from the base of the PR and between 1124879 and 2ff3531.

📒 Files selected for processing (1)
  • tests/test_repr.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_repr.py

📝 Walkthrough

Walkthrough

Added __repr__ methods to sync and async facade, remote, and local Qdrant clients. Representations include remote connection details or local storage locations and omit API keys. Added regression tests covering sync and async clients, remote and local configurations, in-memory and filesystem storage, secret omission, and synchronous string return values.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding repr implementations to the six client classes.
Description check ✅ Passed The description is detailed and directly matches the repr-focused changes in this PR.
Linked Issues check ✅ Passed The code and tests satisfy the linked issue goals for all six classes, async syncness, secret omission, and broad repr coverage.
Out of Scope Changes check ✅ Passed The changes appear scoped to repr implementations and supporting tests, with no unrelated code introduced.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between e7aecbd and 1124879.

📒 Files selected for processing (7)
  • qdrant_client/async_qdrant_client.py
  • qdrant_client/async_qdrant_remote.py
  • qdrant_client/local/async_qdrant_local.py
  • qdrant_client/local/qdrant_local.py
  • qdrant_client/qdrant_client.py
  • qdrant_client/qdrant_remote.py
  • tests/test_repr.py

Comment thread tests/test_repr.py Outdated
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.
@Harsh23Kashyap Harsh23Kashyap closed this by deleting the head repository Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant