fix: resolve CI type checking issues
- Add return type annotations to __hash__ (-> int) and __eq__ (-> bool) in HistoryEntry - Add TextIO import and type annotations for file parameters - Add type ignore comment for fuzzywuzzy import - Add HistoryEntry import and list type annotations in time_analysis - Add assert statements for Optional[datetime] timestamps - Add TypedDict classes for type-safe pattern dictionaries - Add CommandPattern import and list[CommandPattern] type annotation - Add -> None return types to all test methods - Remove unused HistoryEntry import (F401)
This commit is contained in:
@@ -1 +1,96 @@
|
||||
bmFtZTogQ0kKCm9uOgogIHB1c2g6CiAgICBicmFuY2hlczogW21haW5dCiAgcHVsbF9yZXF1ZXN0OgogICAgYnJhbmNoZXM6IFttYWluXQoKam9iczogCiAgdGVzdDoKICAgIHJ1bnMtb246IHVidW50dS1sYXRlc3QKICAgIHN0ZXBzOgogICAgICAtIHVzZXM6IGFjdGlvbnMvY2hlY2tvdXQdjNFgKICAgICAgdXNlczogYWN0aW9ucy9zZXR1cC1weXRob25fdjUKICAgICAgd2l0aDoKICAgICAgICBweXRob24tdmVyc2lvbjogJzMuMTEnCiAgICAtIHJ1bjogcGlwIGluc3RhbGwgLWUgIltcImRldlwiXSIKICAgIC0gcnVuOiBweXRlc3QgdGVzdHMvIC12CiAgICAtIHJ1bjogcnVmZiBjaGVjayAu
|
||||
"""Search functionality for shell history."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from fuzzywuzzy import fuzz # type: ignore
|
||||
|
||||
from shellhist.core import HistoryEntry, HistoryStore
|
||||
|
||||
|
||||
def fuzzy_search(
|
||||
store: HistoryStore,
|
||||
query: str,
|
||||
threshold: int = 70,
|
||||
limit: int = 20,
|
||||
reverse: bool = False,
|
||||
recent: bool = False,
|
||||
) -> list[tuple[HistoryEntry, int]]:
|
||||
"""Search history with fuzzy matching.
|
||||
|
||||
Args:
|
||||
store: HistoryStore to search.
|
||||
query: Search query string.
|
||||
threshold: Minimum similarity score (0-100).
|
||||
limit: Maximum number of results to return.
|
||||
reverse: If True, sort by recency (newest first).
|
||||
recent: If True, boost scores for recent commands.
|
||||
|
||||
Returns:
|
||||
List of (HistoryEntry, score) tuples sorted by score.
|
||||
"""
|
||||
commands = store.get_unique_commands()
|
||||
|
||||
if not commands:
|
||||
return []
|
||||
|
||||
results = []
|
||||
now = datetime.now()
|
||||
|
||||
for command in commands:
|
||||
score = fuzz.token_sort_ratio(query.lower(), command.lower())
|
||||
|
||||
if score >= threshold:
|
||||
entry = _get_first_entry(store, command)
|
||||
if entry:
|
||||
if recent and entry.timestamp:
|
||||
hours_old = (now - entry.timestamp).total_seconds() / 3600
|
||||
if hours_old < 24:
|
||||
score = min(100, score + 10)
|
||||
|
||||
results.append((entry, score))
|
||||
|
||||
results.sort(key=lambda x: x[1], reverse=not reverse)
|
||||
|
||||
return results[:limit]
|
||||
|
||||
|
||||
def _get_first_entry(store: HistoryStore, command: str) -> Optional[HistoryEntry]:
|
||||
"""Get the first entry for a command from the store."""
|
||||
for entry in store.entries:
|
||||
if entry.command == command:
|
||||
return entry
|
||||
return None
|
||||
|
||||
|
||||
def rank_by_frequency(
|
||||
store: HistoryStore,
|
||||
results: list[tuple[HistoryEntry, int]],
|
||||
boost_recent: bool = False,
|
||||
) -> list[tuple[HistoryEntry, int, int]]:
|
||||
"""Rank search results by frequency.
|
||||
|
||||
Args:
|
||||
store: HistoryStore for frequency lookups.
|
||||
results: List of (HistoryEntry, score) tuples.
|
||||
boost_recent: If True, boost scores for recent commands.
|
||||
|
||||
Returns:
|
||||
List of (HistoryEntry, score, frequency) tuples.
|
||||
"""
|
||||
ranked = []
|
||||
now = datetime.now()
|
||||
|
||||
for entry, score in results:
|
||||
freq = store.get_frequency(entry.command)
|
||||
|
||||
if boost_recent and entry.timestamp:
|
||||
hours_old = (now - entry.timestamp).total_seconds() / 3600
|
||||
if hours_old < 24:
|
||||
freq = freq * 2
|
||||
|
||||
ranked.append((entry, score, freq))
|
||||
|
||||
ranked.sort(key=lambda x: (x[1], x[2]), reverse=True)
|
||||
|
||||
return ranked
|
||||
|
||||
Reference in New Issue
Block a user