Skip to content

Commit c5c4ff5

Browse files
committed
Added ruff linting checks and applied fixes
1 parent e27abdd commit c5c4ff5

35 files changed

+146
-113
lines changed

pyproject.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ classifiers = [
2828
"Framework :: Django :: 6.0",
2929
]
3030

31+
[project.urls]
32+
Home = "https://github.com/wagtail/django-ai-core"
33+
34+
3135
[dependency-groups]
3236
dev = [
3337
"django>=5.2.3",
@@ -57,6 +61,22 @@ build-backend = "uv_build"
5761
[tool.uv]
5862
default-groups = ["dev", "test"]
5963

64+
[tool.ruff.lint]
65+
select = [
66+
"B", # flake8-bugbear
67+
"C4", # flake8-comprehensions
68+
"C90", # mccabe
69+
"DJ", # flake8-django
70+
"E", # pycodestyle errors
71+
"F", # pyflakes
72+
"I", # isort
73+
"RUF", # ruff-specific rules
74+
"TRY", # tryceratops
75+
"PT", # flake8-pytest-style
76+
"SIM", # flake8-simplify
77+
]
78+
ignore = ["TRY003", "E501", "RUF012"]
79+
6080
[tool.pytest.ini_options]
6181
DJANGO_SETTINGS_MODULE = "testapp.settings"
6282
pythonpath = ["./src", "./tests"]

src/django_ai_core/contrib/agents/base.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import inspect
22
from abc import ABC, abstractmethod
33
from dataclasses import dataclass
4-
from typing import get_args, get_origin, Annotated
4+
from typing import Annotated, get_args, get_origin
55

6-
from django.core.validators import validate_slug
76
from django.core.exceptions import ValidationError
7+
from django.core.validators import validate_slug
88

99
from .permissions import BasePermission
1010
from .views import AgentExecutionView
@@ -68,10 +68,10 @@ def __init_subclass__(cls, **kwargs):
6868
if hasattr(cls, "slug"):
6969
try:
7070
validate_slug(cls.slug)
71-
except ValidationError:
71+
except ValidationError as e:
7272
raise ValueError(
7373
f"Agent {cls.__name__} has an invalid slug: {cls.slug}. Use a valid “slug” consisting of letters, numbers, underscores or hyphens."
74-
)
74+
) from e
7575

7676

7777
class AgentRegistry:
@@ -82,7 +82,7 @@ def register(self):
8282
"""Decorator to register an agent."""
8383

8484
def decorator(cls: type[Agent]) -> type[Agent]:
85-
agent_slug = getattr(cls, "slug")
85+
agent_slug = cls.slug
8686
self._agents[agent_slug] = cls
8787
return cls
8888

src/django_ai_core/contrib/agents/views.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
from typing import Any, TYPE_CHECKING
21
import json
2+
from typing import TYPE_CHECKING, Any
33

44
from django.http import JsonResponse
5+
from django.utils.decorators import method_decorator
56
from django.views import View
67
from django.views.decorators.csrf import csrf_exempt
7-
from django.utils.decorators import method_decorator
88

99
from .permissions import AllowAny
1010

@@ -97,8 +97,8 @@ def _get_agent(self) -> "Agent":
9797

9898
try:
9999
return registry.get(self.agent_slug)()
100-
except KeyError:
101-
raise AgentNotFound
100+
except KeyError as e:
101+
raise AgentNotFound from e
102102

103103
def _execute_agent(self, agent: "Agent", arguments: dict[str, Any]) -> Any:
104104
return agent.execute(**arguments)
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from .base import (
2-
VectorIndex,
32
IndexRegistry,
3+
VectorIndex,
44
registry,
55
)
66
from .chunking import (
77
ChunkTransformer,
8-
SimpleChunkTransformer,
9-
SentenceChunkTransformer,
108
ParagraphChunkTransformer,
9+
SentenceChunkTransformer,
10+
SimpleChunkTransformer,
1111
)
1212
from .embedding import (
1313
CoreEmbeddingTransformer,
@@ -22,18 +22,17 @@
2222
StorageProvider,
2323
)
2424

25-
2625
__all__ = [
26+
"CachedEmbeddingTransformer",
2727
"ChunkTransformer",
28-
"ModelSource",
28+
"CoreEmbeddingTransformer",
2929
"IndexRegistry",
30+
"ModelSource",
31+
"ModelSource",
3032
"ParagraphChunkTransformer",
3133
"SentenceChunkTransformer",
3234
"SimpleChunkTransformer",
33-
"CoreEmbeddingTransformer",
34-
"CachedEmbeddingTransformer",
3535
"StorageProvider",
3636
"VectorIndex",
37-
"ModelSource",
3837
"registry",
3938
]

src/django_ai_core/contrib/index/base.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1+
import logging
12
from typing import TYPE_CHECKING, Any, ClassVar, Iterable
3+
24
from django.utils.text import slugify
5+
36
from .source import HasPostIndexUpdateHook
4-
import logging
57

68
if TYPE_CHECKING:
7-
from .schema import Document
8-
from .storage.base import StorageProvider
9-
from .query import ResultQuerySetMixin
109
from .embedding import EmbeddingTransformer
10+
from .query import QueryHandler, ResultQuerySetMixin
11+
from .schema import Document
1112
from .source import Source
12-
from .query import QueryHandler
13+
from .storage.base import StorageProvider
1314

1415

1516
logger = logging.getLogger(__name__)

src/django_ai_core/contrib/index/chunking.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ def __init__(self, chunk_size: int = 1024, chunk_overlap: int = 20):
5252
self.chunk_overlap = chunk_overlap
5353

5454
def transform(self, text: str) -> list[str]:
55-
from llama_index.core.node_parser import SentenceSplitter
5655
from llama_index.core import Document as LlamaDocument
56+
from llama_index.core.node_parser import SentenceSplitter
5757

5858
splitter = SentenceSplitter(
5959
chunk_size=self.chunk_size, chunk_overlap=self.chunk_overlap
@@ -63,7 +63,7 @@ def transform(self, text: str) -> list[str]:
6363
nodes = splitter.get_nodes_from_documents([llama_doc])
6464

6565
chunks = []
66-
for i, node in enumerate(nodes):
66+
for _, node in enumerate(nodes):
6767
chunks.append(
6868
node.get_content(),
6969
)

src/django_ai_core/contrib/index/embedding.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from abc import ABC, abstractmethod
22
from typing import Iterable
3-
from .schema import EmbeddedDocument, Document
43

54
from django_ai_core.llm import LLMService
65

6+
from .schema import Document, EmbeddedDocument
7+
78

89
class EmbeddingTransformer(ABC):
910
"""Base class for embedding transformers which turn Documents into EmbeddedDocuments."""
@@ -13,6 +14,7 @@ def transformer_id(self) -> str:
1314
"""Get unique identifier for this transformer."""
1415
return self.__class__.__name__
1516

17+
@abstractmethod
1618
def embed_string(self, text: str) -> list[float] | None:
1719
"""Embed a string using the transformer."""
1820
pass
@@ -68,7 +70,7 @@ def embed_documents(
6870
texts = [document.content for document in batch]
6971
embeddings = self.llm_service.embedding(texts).data
7072

71-
for document, embedding in zip(batch, embeddings):
73+
for document, embedding in zip(batch, embeddings, strict=False):
7274
embedded_documents.append(document.add_embedding(embedding.embedding))
7375

7476
return embedded_documents

src/django_ai_core/contrib/index/embedding_cache.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
generation to avoid expensive embedding operations for duplicate content.
66
"""
77

8-
from abc import ABC, abstractmethod
98
import logging
9+
from abc import ABC, abstractmethod
1010

1111
from django_ai_core.contrib.index.schema import Document, EmbeddedDocument
1212

@@ -61,13 +61,13 @@ def _get_cache_model(self):
6161
"""Get the cache model."""
6262
try:
6363
from .models import EmbeddingCache
64-
65-
return EmbeddingCache
66-
except ImportError:
64+
except ImportError as e:
6765
raise ImportError(
6866
"Django is not properly configured. Make sure Django settings are loaded "
6967
"and 'django_ai_core.contrib.index' is in INSTALLED_APPS."
70-
)
68+
) from e
69+
else:
70+
return EmbeddingCache
7171

7272
def get_embedding(self, content: str, transformer_id: str) -> list[float] | None:
7373
"""Get cached embedding for content and model."""
@@ -202,7 +202,7 @@ def embed_documents(
202202
result[i] = document
203203

204204
# Place newly embedded documents
205-
for i, document in zip(uncached_indices, embedded_documents):
205+
for i, document in zip(uncached_indices, embedded_documents, strict=False):
206206
result[i] = document
207207

208208
return [document for document in result if document is not None]

src/django_ai_core/contrib/index/management/commands/rebuild_indexes.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
This command rebuilds all registered VectorIndex instances.
55
"""
66

7-
from django.core.management.base import BaseCommand, CommandError
8-
from django.utils import timezone
97
import logging
108
import time
119

10+
from django.core.management.base import BaseCommand, CommandError
11+
from django.utils import timezone
12+
1213
from django_ai_core.contrib.index.base import registry
1314

1415
logger = logging.getLogger(__name__)
@@ -108,8 +109,6 @@ def _rebuild_sequential(
108109
try:
109110
start_time = time.time()
110111
index_cls = registry.get(index_name)
111-
if not index_cls:
112-
raise ValueError(f"Index '{index_name}' not found in registry")
113112

114113
self.stdout.write(
115114
f"\n[{i}/{len(indexes_to_rebuild)}] Rebuilding index: {index_name}"

src/django_ai_core/contrib/index/models.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import hashlib
22
from typing import TYPE_CHECKING
3-
from django.db import models
3+
44
from django.contrib.contenttypes.fields import GenericForeignKey
55
from django.contrib.contenttypes.models import ContentType
6+
from django.db import models
67

78
from .base import registry
89

@@ -79,7 +80,6 @@ def get_or_create_embedding(
7980
content_hash=content_hash,
8081
embedding_transformer_id=embedding_transformer_id,
8182
)
82-
return cache_entry, False
8383
except cls.DoesNotExist:
8484
# Create new cache entry
8585
cache_entry = cls.objects.create(
@@ -90,6 +90,8 @@ def get_or_create_embedding(
9090
embedding_dimensions=len(embedding_vector),
9191
)
9292
return cache_entry, True
93+
else:
94+
return cache_entry, False
9395

9496
@classmethod
9597
def get_cached_embedding(
@@ -105,9 +107,10 @@ def get_cached_embedding(
105107
content_hash=content_hash,
106108
embedding_transformer_id=embedding_transformer_id,
107109
)
108-
return cache_entry.embedding_vector
109110
except cls.DoesNotExist:
110111
return None
112+
else:
113+
return cache_entry.embedding_vector
111114

112115

113116
class DocumentEmbedding(models.Model):
@@ -164,6 +167,9 @@ class Meta:
164167
("content_type", "object_id", "index_name", "source_id"),
165168
]
166169

170+
def __str__(self):
171+
return f"Model Source Index: {self.object_id} in {self.index_name}"
172+
167173
@classmethod
168174
def register(cls, obj, index_name, source_id):
169175
"""Register an object as being indexed in the specified index."""

0 commit comments

Comments
 (0)