feat(client): add get_alias_names() shortcut method to all 6 client classes - #1307
feat(client): add get_alias_names() shortcut method to all 6 client classes#1307Harsh23Kashyap wants to merge 1 commit into
get_alias_names() shortcut method to all 6 client classes#1307Conversation
… classes `QdrantClient`, `AsyncQdrantClient`, `QdrantRemote`, `AsyncQdrantRemote`, `QdrantLocal`, and `AsyncQdrantLocal` all gain a public `get_alias_names()` method that returns a `list[str]` of all alias names. The common case -- 'I just want the alias names' -- currently requires `[a.alias_name for a in client.get_aliases().aliases]`. The new method is a one-liner shortcut. - Remote mode: delegates to `get_aliases()` and extracts `.alias_name` from each `AliasDescription`. No new network round-trip. - Local mode: reads `self.aliases.keys()` directly. No intermediate `CollectionsAliasesResponse` model construction. - The async facade uses `inspect.iscoroutine` to handle both the sync (local) and async (remote) inner clients. Sibling of #1302 (`get_collection_names`). Same regen-aware shape: `generate_async_client.sh` has an AST-based post-regen step that re-injects `async def get_alias_names` into the facade and remote async files. The facade's injected method uses `inspect.iscoroutine`, so the sed step also adds `import inspect` at the top of the facade (idempotent: skips if already present). `AsyncQdrantLocal.get_alias_names` stays a sync `def` (no I/O), kept as sync by the local transformer without intervention. Fixes #1306
✅ Deploy Preview for poetic-froyo-8baba7 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughAdds Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: 🚥 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: 2
🤖 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 `@qdrant_client/async_qdrant_client.py`:
- Line 12: Update AsyncQdrantBase to declare get_alias_names with overloads or a
signature that supports both synchronous and asynchronous implementations, so
callers using a statically typed AsyncQdrantBase can safely inspect and await
the result. Preserve AsyncQdrantRemote’s async behavior and AsyncQdrantLocal’s
sync behavior.
In `@qdrant_client/local/async_qdrant_local.py`:
- Around line 676-680: Update the closed-instance error in get_alias_names to
use the established “QdrantLocal instance is closed. Please create a new
instance.” wording, matching the other closed checks in the file.
🪄 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: 6979111d-4fec-4195-b446-2103ae9d525f
📒 Files selected for processing (10)
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_get_alias_names.pytools/async_client_generator/client_generator.pytools/async_client_generator/remote_generator.pytools/generate_async_client.sh
| # | ||
| # ****** WARNING: THIS FILE IS AUTOGENERATED ****** | ||
|
|
||
| import inspect |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Inspect how get_alias_names is declared on the async base class(es).
rg -n -B2 -A5 'def get_alias_names' qdrant_client/async_client_base.py qdrant_client/client_base.py 2>/dev/nullRepository: qdrant/qdrant-client
Length of output: 158
🏁 Script executed:
#!/bin/bash
set -u
echo "Tracked files matching get_alias_names or async client base:"
git ls-files | rg '(^|/)(async_qdrant_client\.py|async_client_base\.py|.*client_base\.[pm]y)$' || true
echo
echo "Search get_alias_names across repository:"
rg -n -B3 -A6 'get_alias_names\s*[:=]' . || true
echo
echo "Search inspect.iscoroutine and alias names:"
rg -n -B3 -A6 'inspect\.iscoroutine|iscoroutine|AliasNames|alias_names' qdrant_client || true
echo
echo "List qdrant_client top files:"
find qdrant_client -maxdepth 2 -type f | sortRepository: qdrant/qdrant-client
Length of output: 12681
🏁 Script executed:
#!/bin/bash
set -u
echo "Check async_qdrant_client around import and get_alias_names if present:"
wc -l qdrant_client/async_qdrant_client.py 2>/dev/null || true
sed -n '1,25p' qdrant_client/async_qdrant_client.py 2>/dev/null || true
sed -n '1480,1540p' qdrant_client/async_qdrant_client.py 2>/dev/null || true
echo
echo "Inspect base class files if present:"
for f in qdrant_client/async_client_base.py qdrant_client/client_base.py; do
if [ -f "$f" ]; then
echo "--- $f"
wc -l "$f"
rg -n -B2 -A8 'class .*Base|get_alias_names|alias_names' "$f" || true
fi
done
echo
echo "Search for AsyncQdrantLocal/AsyncQdrantRemote definitions:"
rg -n -B2 -A10 'class AsyncQdrant(Local|Remote)|AsyncQdrantBase' qdrant_client || trueRepository: qdrant/qdrant-client
Length of output: 14118
🏁 Script executed:
#!/bin/bash
set -u
echo "AsyncQdrantBase alias-related methods:"
rg -n -B3 -A12 'get_alias_names|get_aliases|update_collection_aliases|get_collection_aliases' qdrant_client/async_client_base.py
echo
echo "AsyncQdrantLocal methods around alias methods and class inheritance:"
rg -n -B5 -A8 'get_alias_names|get_aliases|class AsyncQdrantLocal|AsyncQdrantBase|super\(' qdrant_client/local/async_qdrant_local.py
echo
echo "AsyncQdrantRemote methods around alias methods and class inheritance:"
rg -n -B5 -A8 'get_alias_names|get_aliases|class AsyncQdrantRemote|AsyncQdrantBase|super\(' qdrant_client/async_qdrant_remote.pyRepository: qdrant/qdrant-client
Length of output: 7545
Declare get_alias_names() in the async base before awaiting it.
AsyncQdrantBase does not define get_alias_names(), but AsyncQdrantRemote.get_alias_names() is async and AsyncQdrantLocal.get_alias_names() is sync. Add a base overloads/signature that covers both call forms, or change the local implementation so inspect.iscoroutine(result) and await result is not mypy-invisible when _client is statically typed as AsyncQdrantBase.
🤖 Prompt for 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.
In `@qdrant_client/async_qdrant_client.py` at line 12, Update AsyncQdrantBase to
declare get_alias_names with overloads or a signature that supports both
synchronous and asynchronous implementations, so callers using a statically
typed AsyncQdrantBase can safely inspect and await the result. Preserve
AsyncQdrantRemote’s async behavior and AsyncQdrantLocal’s sync behavior.
| def get_alias_names(self) -> list[str]: | ||
| if self.closed: | ||
| raise RuntimeError("AsyncQdrantLocal instance is closed. Please create a new instance.") | ||
| return list(self.aliases.keys()) | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Match the established "closed" error message wording in this file.
Every other closed-instance check in this file uses "QdrantLocal instance is closed. Please create a new instance." Line 678 uses "AsyncQdrantLocal instance is closed." instead. Use the same wording as the rest of the file for consistency.
✏️ Proposed fix
def get_alias_names(self) -> list[str]:
if self.closed:
- raise RuntimeError("AsyncQdrantLocal instance is closed. Please create a new instance.")
+ raise RuntimeError("QdrantLocal instance is closed. Please create a new instance.")
return list(self.aliases.keys())📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def get_alias_names(self) -> list[str]: | |
| if self.closed: | |
| raise RuntimeError("AsyncQdrantLocal instance is closed. Please create a new instance.") | |
| return list(self.aliases.keys()) | |
| def get_alias_names(self) -> list[str]: | |
| if self.closed: | |
| raise RuntimeError("QdrantLocal instance is closed. Please create a new instance.") | |
| return list(self.aliases.keys()) |
🤖 Prompt for 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.
In `@qdrant_client/local/async_qdrant_local.py` around lines 676 - 680, Update the
closed-instance error in get_alias_names to use the established “QdrantLocal
instance is closed. Please create a new instance.” wording, matching the other
closed checks in the file.
Summary
Add a public
get_alias_names() -> list[str]method to all 6 client classes. The current workaround is a list comprehension over the existingget_aliases().aliases. The new method is the obvious one-liner shortcut for "I just want the alias names".Sibling of #1302 (
get_collection_names()). Same regen-aware shape, but a different model and a different call site.Fixes #1306
Changes
qdrant_client/qdrant_client.py— facade sync method that delegates to the inner clientqdrant_client/async_qdrant_client.py— facade async method that usesinspect.iscoroutineto handle both sync (local) and async (remote) inner clientsqdrant_client/qdrant_remote.py— remote sync method,return [a.alias_name for a in self.get_aliases().aliases]qdrant_client/async_qdrant_remote.py— remote async method,return [a.alias_name for a in (await self.get_aliases()).aliases]qdrant_client/local/qdrant_local.py— local sync method, readsself.aliases.keys()directly (noget_aliases()round-trip, noCollectionsAliasesResponsemodel)qdrant_client/local/async_qdrant_local.py— local async method (kept as syncdefsince no I/O; the local transformer preserves it as sync)tools/async_client_generator/client_generator.py—get_alias_namesadded toexclude_methodstools/async_client_generator/remote_generator.py—get_alias_namesadded toexclude_methodstools/generate_async_client.sh— AST-based post-regen sed step re-injectsasync def get_alias_namesintoasync_qdrant_client.pyandasync_qdrant_remote.py. Also addsimport inspectto the facade (the remote method doesn't use it, so no spurious import). Fails loudly with non-zero exit ifclose()cannot be found.tests/test_get_alias_names.py— 14 new tests: sync + async × in-memory / path / remote × empty / after-create-alias × list-not-model, plus local-direct-access verification (noget_aliases()round-trip in local mode) and closed-state testsBehavior
Async equivalent (the async facade method is
asyncand must be awaited):Remote mode delegates to the existing
get_aliases()call. Local mode readsself.aliases.keys()directly — no intermediateCollectionsAliasesResponsemodel, no round-trip through the publicget_aliases()API.Verification
.ossvenv/bin/python -m pytest tests/test_get_alias_names.py -v— 14/14 pass.ossvenv/bin/python -m ruff checkon the 9 changed source files — clean (the 3 pre-existing F541 errors onmaster/devare in the__init__of the remote classes, not in my added code).ossvenv/bin/python -m ruff format --check --line-length 99on the changed files — clean.ossvenv/bin/python -m mypyon the 6 source files — cleanbash tools/generate_async_client.shend-to-end with the new sed step:async def get_alias_namesis correctly re-injected intoasync_qdrant_client.pyandasync_qdrant_remote.py, andimport inspectis added to the facade (idempotent). Re-running the sed step is a no-op.Notes
dev(per the PR template and maintainer joein's 2026-07-21 guidance on PRs pointing the wrong base)generate_async_client.shis the only fragile part. Same AST-based pattern as feat(client): addget_collection_names()shortcut method to all 6 client classes #1302 / feat(client): addqdrant_version()method to all 6 client classes #1294 / feat(client): addserver_info()method returning the fullVersionInfomodel #1296 / feat(client): add server_info() method returning the full VersionInfo model #1297, with one addition: the sed step also insertsimport inspectat the top ofasync_qdrant_client.py(the facade only — the remote method is plain await + return and doesn't need it). Idempotent: ifimport inspectis already present, the sed step skips it.AsyncQdrantLocal.get_alias_namesis a syncdef(no I/O), so the local transformer keeps it as sync without intervention.feat/client-contains-dunderfrom a scoping change mid-implementation; the implementation isget_alias_names(), not a dunder. Sorry for the confusion.