• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

anthonypdawson / vector-inspector / 26337619024

23 May 2026 04:18PM UTC coverage: 80.557% (-0.03%) from 80.584%
26337619024

push

github

anthonypdawson
deps: update pymilvus dependency to include milvus_lite extra

- Remove pymilvus from core dependencies (make it optional like other providers)
- Update all references to pymilvus to use pymilvus[milvus_lite]>=2.6.8
- Ensure milvus_lite is installed when using pip install vector-inspector[milvus]
- Apply changes consistently across:
  - [dependency-groups] milvus
  - [project.optional-dependencies] milvus
  - Both 'all' bundles (dependency-groups and optional-dependencies)

15351 of 19056 relevant lines covered (80.56%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.67
/src/vector_inspector/core/cache_manager.py
1
"""
2
Cache manager for storing databrowser and search panel state by database and collection.
3
Provides fast switching between collections with automatic invalidation on refresh or settings changes.
4
"""
5

6
from dataclasses import dataclass, field
1✔
7
from datetime import datetime
1✔
8
from typing import Any, Optional
1✔
9

10

11
@dataclass
1✔
12
class CacheEntry:
1✔
13
    """Represents a cached state for a specific database and collection."""
14

15
    data: Any
1✔
16
    timestamp: datetime = field(default_factory=datetime.now)
1✔
17

18
    # Browser state
19
    scroll_position: int = 0
1✔
20
    selected_indices: list = field(default_factory=list)
1✔
21

22
    # Search panel state
23
    search_query: str = ""
1✔
24
    search_filters: dict[str, Any] = field(default_factory=dict)
1✔
25
    search_results: Optional[Any] = None
1✔
26

27
    # User inputs
28
    user_inputs: dict[str, Any] = field(default_factory=dict)
1✔
29

30

31
class CacheManager:
1✔
32
    """
33
    Manages cache for databrowser and search panel by (database, collection) key.
34
    Supports invalidation on refresh or settings changes.
35

36
    Uses singleton pattern to ensure only one instance exists, preventing state inconsistencies
37
    when code creates instances directly vs using AppState.
38
    """
39

40
    _instance: Optional["CacheManager"] = None
1✔
41

42
    def __new__(cls):
1✔
43
        """Ensure only one instance exists (singleton pattern)."""
44
        if cls._instance is None:
1✔
45
            cls._instance = super().__new__(cls)
1✔
46
        return cls._instance
1✔
47

48
    def __init__(self):
1✔
49
        """Initialize cache manager (only runs once due to singleton)."""
50
        # Skip if already initialized (check instance dict only, not class dict)
51
        if "_initialized" in self.__dict__:
1✔
52
            return
1✔
53
        self._initialized = True
1✔
54

55
        self._cache: dict[tuple[str, str], CacheEntry] = {}
1✔
56
        self._enabled = True
1✔
57

58
    def get(self, database: str, collection: str) -> Optional[CacheEntry]:
1✔
59
        """Retrieve cached entry for a database and collection."""
60
        if not self._enabled:
1✔
61
            return None
1✔
62

63
        key = (database, collection)
1✔
64
        return self._cache.get(key)
1✔
65

66
    def set(self, database: str, collection: str, entry: CacheEntry) -> None:
1✔
67
        """Store a cache entry for a database and collection."""
68
        if not self._enabled:
1✔
69
            return
1✔
70

71
        key = (database, collection)
1✔
72
        entry.timestamp = datetime.now()
1✔
73
        self._cache[key] = entry
1✔
74

75
    def update(self, database: str, collection: str, **kwargs) -> None:
1✔
76
        """Update specific fields in an existing cache entry."""
77
        key = (database, collection)
1✔
78
        if key in self._cache:
1✔
79
            entry = self._cache[key]
×
80
            for field_name, value in kwargs.items():
×
81
                if hasattr(entry, field_name):
×
82
                    setattr(entry, field_name, value)
×
83
            entry.timestamp = datetime.now()
×
84
        else:
85
            # Create new entry with provided fields
86
            entry = CacheEntry(data=None)
1✔
87
            for field_name, value in kwargs.items():
1✔
88
                if hasattr(entry, field_name):
1✔
89
                    setattr(entry, field_name, value)
1✔
90
            self._cache[key] = entry
1✔
91

92
    def invalidate(self, database: Optional[str] = None, collection: Optional[str] = None) -> None:
1✔
93
        """
94
        Invalidate cache entries.
95
        - If both database and collection are provided, invalidate that specific entry.
96
        - If only database is provided, invalidate all collections in that database.
97
        - If neither is provided, invalidate all entries (global refresh).
98
        """
99
        if database is None and collection is None:
1✔
100
            # Clear all cache
101
            self._cache.clear()
1✔
102
        elif collection is None and database is not None:
1✔
103
            # Clear all collections in the specified database
104
            keys_to_remove = [key for key in self._cache.keys() if key[0] == database]
1✔
105
            for key in keys_to_remove:
1✔
106
                del self._cache[key]
1✔
107
        elif database is not None and collection is not None:
1✔
108
            # Clear specific database/collection combination
109
            key = (database, collection)
1✔
110
            if key in self._cache:
1✔
111
                del self._cache[key]
1✔
112

113
    def clear(self) -> None:
1✔
114
        """Clear all cached entries."""
115
        self._cache.clear()
1✔
116

117
    def enable(self) -> None:
1✔
118
        """Enable caching."""
119
        self._enabled = True
1✔
120

121
    def disable(self) -> None:
1✔
122
        """Disable caching and clear all entries."""
123
        self._enabled = False
1✔
124
        self._cache.clear()
1✔
125

126
    def is_enabled(self) -> bool:
1✔
127
        """Check if caching is enabled."""
128
        return self._enabled
1✔
129

130
    def get_cache_info(self) -> dict[str, Any]:
1✔
131
        """Get information about the current cache state."""
132
        return {
1✔
133
            "enabled": self._enabled,
134
            "entry_count": len(self._cache),
135
            "entries": [
136
                {
137
                    "database": db,
138
                    "collection": coll,
139
                    "timestamp": entry.timestamp.isoformat(),
140
                    "has_data": entry.data is not None,
141
                    "has_search_results": entry.search_results is not None,
142
                }
143
                for (db, coll), entry in self._cache.items()
144
            ],
145
        }
146

147

148
# Legacy global function for backward compatibility
149
# DEPRECATED: New code should use app_state.cache_manager instead
150
def get_cache_manager() -> CacheManager:
1✔
151
    """Get the singleton cache manager instance.
152

153
    DEPRECATED: This returns the singleton instance for legacy code.
154
    New code should use app_state.cache_manager instead.
155

156
    Note: CacheManager uses singleton pattern, so this always returns the same instance
157
    that AppState uses.
158
    """
159
    return CacheManager()
1✔
160

161

162
def invalidate_cache_on_settings_change() -> None:
1✔
163
    """Invalidate all cache when settings change."""
164
    cache = get_cache_manager()
1✔
165
    cache.invalidate()
1✔
166

167

168
def invalidate_cache_on_refresh(database: Optional[str] = None, collection: Optional[str] = None) -> None:
1✔
169
    """Invalidate cache on refresh action."""
170
    cache = get_cache_manager()
1✔
171
    cache.invalidate(database, collection)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc