chore(core): make ty the default typechecker (#736)

Signed-off-by: phernandez <paul@basicmachines.co>
This commit is contained in:
Paul Hernandez
2026-04-13 10:34:01 -05:00
committed by GitHub
parent abd4a5a6da
commit 052545b661
89 changed files with 1004 additions and 559 deletions
@@ -11,7 +11,7 @@ from basic_memory.repository.embedding_provider import EmbeddingProvider
from basic_memory.repository.semantic_errors import SemanticDependenciesMissingError
if TYPE_CHECKING:
from fastembed import TextEmbedding # type: ignore[import-not-found] # pragma: no cover
from fastembed import TextEmbedding # pragma: no cover
class FastEmbedEmbeddingProvider(EmbeddingProvider):
@@ -62,7 +62,7 @@ class FastEmbedEmbeddingProvider(EmbeddingProvider):
def _create_model() -> "TextEmbedding":
try:
from fastembed import TextEmbedding # type: ignore[import-not-found]
from fastembed import TextEmbedding
except (
ImportError
) as exc: # pragma: no cover - exercised via tests with monkeypatch
@@ -50,7 +50,7 @@ class OpenAIEmbeddingProvider(EmbeddingProvider):
return self._client
try:
from openai import AsyncOpenAI # type: ignore[import-not-found]
from openai import AsyncOpenAI
except ImportError as exc: # pragma: no cover - covered via monkeypatch tests
raise SemanticDependenciesMissingError(
"OpenAI dependency is missing. "
+4 -3
View File
@@ -268,7 +268,7 @@ class Repository[T: Base]:
return await self.select_by_ids(session, [model.id for model in model_list]) # pyright: ignore [reportAttributeAccessIssue]
async def update(self, entity_id: int, entity_data: dict | T) -> Optional[T]:
async def update(self, entity_id: int, entity_data: dict[str, Any] | T) -> Optional[T]:
"""Update an entity with the given data."""
logger.debug(f"Updating {self.Model.__name__} {entity_id} with data: {entity_data}")
async with db.scoped_session(self.session_maker) as session:
@@ -279,12 +279,13 @@ class Repository[T: Base]:
entity = result.scalars().one()
if isinstance(entity_data, dict):
for key, value in entity_data.items():
update_data = cast(dict[str, Any], entity_data)
for key, value in update_data.items():
if key in self.valid_columns:
setattr(entity, key, value)
elif isinstance(entity_data, self.Model):
for column in self.Model.__table__.columns.keys():
for column in self.valid_columns:
setattr(entity, column, getattr(entity_data, column))
await session.flush() # Make sure changes are flushed
@@ -1068,39 +1068,48 @@ class SearchRepositoryBase(ABC):
write_seconds_total=result.write_seconds_total,
)
batch_total_seconds = time.perf_counter() - batch_start
metric_attrs = {
"backend": backend_name,
"skip_only_batch": result.embedding_jobs_total == 0,
}
telemetry.record_histogram(
"vector_sync_batch_total_seconds",
batch_total_seconds,
unit="s",
**metric_attrs,
backend=backend_name,
skip_only_batch=result.embedding_jobs_total == 0,
)
telemetry.add_counter(
"vector_sync_entities_total", result.entities_total, **metric_attrs
"vector_sync_entities_total",
result.entities_total,
backend=backend_name,
skip_only_batch=result.embedding_jobs_total == 0,
)
telemetry.add_counter(
"vector_sync_entities_skipped",
result.entities_skipped,
**metric_attrs,
backend=backend_name,
skip_only_batch=result.embedding_jobs_total == 0,
)
telemetry.add_counter(
"vector_sync_entities_deferred",
result.entities_deferred,
**metric_attrs,
backend=backend_name,
skip_only_batch=result.embedding_jobs_total == 0,
)
telemetry.add_counter(
"vector_sync_embedding_jobs_total",
result.embedding_jobs_total,
**metric_attrs,
backend=backend_name,
skip_only_batch=result.embedding_jobs_total == 0,
)
telemetry.add_counter(
"vector_sync_chunks_total",
result.chunks_total,
backend=backend_name,
skip_only_batch=result.embedding_jobs_total == 0,
)
telemetry.add_counter("vector_sync_chunks_total", result.chunks_total, **metric_attrs)
telemetry.add_counter(
"vector_sync_chunks_skipped",
result.chunks_skipped,
**metric_attrs,
backend=backend_name,
skip_only_batch=result.embedding_jobs_total == 0,
)
if batch_span is not None:
batch_span.set_attributes(
@@ -1675,33 +1684,33 @@ class SearchRepositoryBase(ABC):
) -> None:
"""Log completion and slow-entity warnings with a consistent format."""
backend_name = type(self).__name__.removesuffix("SearchRepository").lower()
metric_attrs = {
"backend": backend_name,
"skip_only_entity": entity_skipped and embedding_jobs_count == 0,
}
telemetry.record_histogram(
"vector_sync_prepare_seconds",
prepare_seconds,
unit="s",
**metric_attrs,
backend=backend_name,
skip_only_entity=entity_skipped and embedding_jobs_count == 0,
)
telemetry.record_histogram(
"vector_sync_queue_wait_seconds",
queue_wait_seconds,
unit="s",
**metric_attrs,
backend=backend_name,
skip_only_entity=entity_skipped and embedding_jobs_count == 0,
)
telemetry.record_histogram(
"vector_sync_embed_seconds",
embed_seconds,
unit="s",
**metric_attrs,
backend=backend_name,
skip_only_entity=entity_skipped and embedding_jobs_count == 0,
)
telemetry.record_histogram(
"vector_sync_write_seconds",
write_seconds,
unit="s",
**metric_attrs,
backend=backend_name,
skip_only_entity=entity_skipped and embedding_jobs_count == 0,
)
if total_seconds > 10:
logger.warning(
@@ -350,7 +350,7 @@ class SQLiteSearchRepository(SearchRepositoryBase):
pass
try:
import sqlite_vec # type: ignore[import-not-found]
import sqlite_vec
except ImportError as exc:
raise SemanticDependenciesMissingError(
"sqlite-vec package is missing. "