Skip to content

Task/483 add __repr__ methods#515

Open
tuecoder wants to merge 8 commits intoredis:mainfrom
tuecoder:task/483-Add__repr__methods
Open

Task/483 add __repr__ methods#515
tuecoder wants to merge 8 commits intoredis:mainfrom
tuecoder:task/483-Add__repr__methods

Conversation

@tuecoder
Copy link

@tuecoder tuecoder commented Feb 27, 2026

Summary

  • Add __repr__ to SearchIndex / AsyncSearchIndex (via BaseSearchIndex) showing name, prefix, and storage_type
  • Add __repr__ to SemanticCache showing name, distance_threshold, and ttl
  • Add __repr__ to SemanticRouter showing name and route count
  • Add __repr__ to MessageHistory showing name and session_tag
  • Add __repr__ to SemanticMessageHistory showing name, session_tag, and distance_threshold
  • Add tests/unit/test_repr.py with 11 unit tests covering all new reprs (no Redis required)

Motivation

Core objects previously fell back to the default <ClassName object at 0x...> repr, making notebook debugging, log inspection, and agent-generated diagnostics hard to read. All new reprs are:

  • Human-readable – field names and values are immediately obvious
  • Deterministic – same inputs always produce the same string
  • Non-sensitive – no passwords, URLs, or raw vectors are included

Example output

>>> SearchIndex(schema=schema)
SearchIndex(name='my-index', prefix='rvl', storage_type='hash')

>>> SemanticCache(name='llmcache', distance_threshold=0.1, ttl=300)
SemanticCache(name='llmcache', distance_threshold=0.1, ttl=300)

>>> SemanticRouter(name='router', routes=[...])
SemanticRouter(name='router', routes=3)

>>> MessageHistory(name='chat', session_tag='abc')
MessageHistory(name='chat', session_tag='abc')

>>> SemanticMessageHistory(name='chat', session_tag='abc', distance_threshold=0.3)
SemanticMessageHistory(name='chat', session_tag='abc', distance_threshold=0.3)

For #483


Note

Low Risk
Low risk: adds string representations and unit tests only, with no changes to Redis interactions, query logic, or data handling.

Overview
Adds deterministic, human-readable __repr__ implementations to core RedisVL objects to improve debugging/logging output: BaseSearchIndex (covering SearchIndex/AsyncSearchIndex), SemanticCache, SemanticRouter, MessageHistory, and SemanticMessageHistory.

Introduces tests/unit/test_repr.py, which validates the exact repr strings and uses mocking/model_construct to avoid requiring a running Redis instance or downloading embedding models.

Written by Cursor Bugbot for commit 8bbb90b. This will update automatically on new commits. Configure here.

Add human-readable __repr__ to SearchIndex/AsyncSearchIndex (via
BaseSearchIndex), SemanticCache, SemanticRouter, MessageHistory, and
SemanticMessageHistory. Repr output shows non-sensitive identity fields
(name, prefix, storage_type, distance_threshold, ttl, route count,
session_tag) and is stable for the same construction parameters.
Copilot AI review requested due to automatic review settings February 27, 2026 15:27
@jit-ci
Copy link

jit-ci bot commented Feb 27, 2026

Hi, I’m Jit, a friendly security platform designed to help developers build secure applications from day zero with an MVS (Minimal viable security) mindset.

In case there are security findings, they will be communicated to you as a comment inside the PR.

Hope you’ll enjoy using Jit.

Questions? Comments? Want to learn more? Get in touch with us.

@vishal-bala vishal-bala added the auto:patch Increment the patch version when merged label Feb 27, 2026
Co-authored-by: Vishal Bala <vishal-bala@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 27, 2026 19:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds deterministic, human-readable __repr__ methods to several core RedisVL objects to improve debugging/log readability, plus unit tests validating the exact output strings.

Changes:

  • Implement __repr__ for BaseSearchIndex (covering SearchIndex / AsyncSearchIndex).
  • Implement __repr__ for SemanticCache, SemanticRouter, MessageHistory, and SemanticMessageHistory.
  • Add tests/unit/test_repr.py to assert repr output without requiring Redis/model downloads (via patching/mocking).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
redisvl/index/index.py Adds BaseSearchIndex.__repr__ to surface index identity/config details.
redisvl/extensions/cache/llm/semantic.py Adds SemanticCache.__repr__ including threshold/ttl for easier inspection.
redisvl/extensions/router/semantic.py Adds SemanticRouter.__repr__ with route count for quick diagnostics.
redisvl/extensions/message_history/message_history.py Adds MessageHistory.__repr__ showing name/session tag.
redisvl/extensions/message_history/semantic_history.py Adds SemanticMessageHistory.__repr__ including distance threshold.
tests/unit/test_repr.py Introduces unit tests asserting the new deterministic repr strings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +70 to +80
with (
patch(
"redisvl.extensions.cache.llm.semantic.HFTextVectorizer",
return_value=mock_vec,
),
patch(
"redisvl.extensions.cache.llm.semantic.SearchIndex",
return_value=mock_idx,
),
):
yield
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

This fixture uses the parenthesized multi-context-manager form with (..., ...):, which is only supported in Python 3.10+. The project declares support for Python 3.9, so this will raise a SyntaxError in 3.9 test runs. Use nested with statements or contextlib.ExitStack instead.

Suggested change
with (
patch(
"redisvl.extensions.cache.llm.semantic.HFTextVectorizer",
return_value=mock_vec,
),
patch(
"redisvl.extensions.cache.llm.semantic.SearchIndex",
return_value=mock_idx,
),
):
yield
with patch(
"redisvl.extensions.cache.llm.semantic.HFTextVectorizer",
return_value=mock_vec,
):
with patch(
"redisvl.extensions.cache.llm.semantic.SearchIndex",
return_value=mock_idx,
):
yield

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +177
with (
patch(
"redisvl.extensions.message_history.semantic_history.HFTextVectorizer",
return_value=mock_vec,
),
patch(
"redisvl.extensions.message_history.semantic_history.SearchIndex",
return_value=mock_idx,
),
):
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

This fixture uses the parenthesized multi-context-manager form with (..., ...):, which is only supported in Python 3.10+. Since the package supports Python 3.9, this will cause a SyntaxError under 3.9. Rewrite using nested with blocks or contextlib.ExitStack.

Copilot uses AI. Check for mistakes.
@tylerhutcherson tylerhutcherson self-requested a review February 27, 2026 20:31
@tylerhutcherson
Copy link
Collaborator

@tuecoder there is a mismatch between whats in the __repr__ and what is in the tests fyi after implementing the suggestion from the auto review. Can you address this and then we can merge!

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 28, 2026 09:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +406 to +413
prefix_label = "prefix"
prefix_value = self.prefix

prefixes = getattr(self, "prefixes", None)
if isinstance(prefixes, (list, tuple)) and len(prefixes) != 1:
prefix_label = "prefixes"
prefix_value = prefixes

Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

__repr__ calls self.prefix before inspecting self.prefixes. If schema.index.prefix is an empty list (allowed by the Union[str, List[str]] type), BaseSearchIndex.prefix will raise IndexError, and then repr(index) will raise as well. Consider deriving the displayed prefix from self.prefixes first (handle 0/1/many) so __repr__ never throws and matches the comment about only falling back when multiple prefixes are configured.

Suggested change
prefix_label = "prefix"
prefix_value = self.prefix
prefixes = getattr(self, "prefixes", None)
if isinstance(prefixes, (list, tuple)) and len(prefixes) != 1:
prefix_label = "prefixes"
prefix_value = prefixes
prefixes = getattr(self, "prefixes", None)
# Derive the label/value pair from `prefixes` first so we never
# rely on `self.prefix` indexing into an empty collection.
if isinstance(prefixes, (list, tuple)):
if len(prefixes) == 1:
prefix_label = "prefix"
prefix_value = prefixes[0]
elif len(prefixes) == 0:
# No prefixes configured; show the empty collection.
prefix_label = "prefixes"
prefix_value = prefixes
else:
# Multiple prefixes configured; show them all.
prefix_label = "prefixes"
prefix_value = prefixes
else:
# Fall back to the singular `prefix` attribute when `prefixes`
# is not a sequence. Guard against potential IndexError or
# missing attribute so that __repr__ never raises.
prefix_label = "prefix"
try:
prefix_value = self.prefix
except (AttributeError, IndexError):
prefix_label = "prefixes"
prefix_value = prefixes

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +178
with (
patch(
"redisvl.extensions.message_history.semantic_history.HFTextVectorizer",
return_value=mock_vec,
),
patch(
"redisvl.extensions.message_history.semantic_history.SearchIndex",
return_value=mock_idx,
),
):
yield
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

Same Python-version concern here: with ( ... ): requires Python 3.10+, but the project declares Python 3.9 support. If tests are expected to run on 3.9, rewrite this with statement to a 3.9-compatible multi-context-manager pattern (or bump the supported minimum Python version).

Copilot uses AI. Check for mistakes.
Comment on lines 182 to 187
return (
f"SemanticRouter(" f"name={self.name!r}, " f"routes={len(self.routes)}" f")"
)

@property
def route_names(self) -> List[str]:
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The __repr__ implementation is hard to read due to implicit concatenation of multiple adjacent f-strings. This can be simplified to a single f-string for clarity (no behavior change), which also makes the exact output format easier to audit/maintain.

Suggested change
return (
f"SemanticRouter(" f"name={self.name!r}, " f"routes={len(self.routes)}" f")"
)
@property
def route_names(self) -> List[str]:
return f"SemanticRouter(name={self.name!r}, routes={len(self.routes)})"
@property
def route_names(self) -> List[str]:
def route_names(self) -> List[str]:

Copilot uses AI. Check for mistakes.
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

@tuecoder
Copy link
Author

@tylerhutcherson the mismatch has been addressed.

Copy link
Collaborator

@vishal-bala vishal-bala left a comment

Choose a reason for hiding this comment

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

This is taking shape! There are some comments left by Copilot that would be good to address, around the syntax and maintaining Python 3.9 support (it's slated to be dropped, but for the moment we support it). I left a 👍 reaction on the Copilot comments I think are worth addressing.

Copilot AI review requested due to automatic review settings March 2, 2026 16:31
@tuecoder
Copy link
Author

tuecoder commented Mar 2, 2026

@vishal-bala I have made the changes that you had put thumbs up on.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 2, 2026 16:37
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +403 to +407
def __repr__(self) -> str:
return (
f"{type(self).__name__}(name={self.name!r}, prefixes={self.prefixes!r}, "
f"storage_type={self.storage_type.value!r})"
)
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

The PR description/example output shows SearchIndex/AsyncSearchIndex repr using prefix=..., but the implementation prints prefixes=[...]. Consider updating the PR description/examples to match, or adjust __repr__ to emit prefix= when there is a single prefix (and only use prefixes= for multi-prefix schemas) to keep the stated intent and actual output aligned.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto:patch Increment the patch version when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants