Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion backend/apps/ai/models/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from apps.common.utils import truncate

logger = logging.getLogger(__name__)
SOURCE_MAX_LENGTH = 100


class Context(TimestampedModel):
Expand All @@ -19,7 +20,8 @@ class Context(TimestampedModel):
entity_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
entity_id = models.PositiveIntegerField()
entity = GenericForeignKey("entity_type", "entity_id")
source = models.CharField(max_length=100, blank=True, default="")
source = models.CharField(
max_length=SOURCE_MAX_LENGTH, blank=True, default="")

class Meta:
db_table = "ai_contexts"
Expand Down
15 changes: 9 additions & 6 deletions backend/apps/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
from django.utils.text import Truncator
from django.utils.text import slugify as django_slugify
from humanize import intword, naturaltime
from typing import Optional, Iterable, Any
from django.http import HttpRequest

Comment on lines +15 to +17
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Address static analysis hints for import optimization.

The static analysis tools have identified two valid improvements:

  1. Iterable should be imported from collections.abc instead of typing (deprecated as of Python 3.9)
  2. HttpRequest is only used in type annotations and should be moved into a TYPE_CHECKING block to avoid runtime import overhead

Apply this diff to fix the imports:

-from typing import Optional, Iterable, Any
-from django.http import HttpRequest
-
+from collections.abc import Iterable
+from typing import TYPE_CHECKING, Any, Optional
+
+if TYPE_CHECKING:
+    from django.http import HttpRequest

As per static analysis hints.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from typing import Optional, Iterable, Any
from django.http import HttpRequest
from collections.abc import Iterable
from typing import TYPE_CHECKING, Any, Optional
if TYPE_CHECKING:
from django.http import HttpRequest
🧰 Tools
🪛 Ruff (0.14.4)

14-14: Import from collections.abc instead: Iterable

Import from collections.abc

(UP035)


15-15: Move third-party import django.http.HttpRequest into a type-checking block

Move into type-checking block

(TC002)

🤖 Prompt for AI Agents
In backend/apps/common/utils.py around lines 14 to 16, update the imports to
import Iterable from collections.abc and move HttpRequest into a TYPE_CHECKING
block: replace "from typing import Optional, Iterable, Any" with "from typing
import Optional, Any" and add "from collections.abc import Iterable", then wrap
"from django.http import HttpRequest" inside "if TYPE_CHECKING:" after adding
"from typing import TYPE_CHECKING" at the top so HttpRequest is only imported
for type checking and avoids runtime overhead.



def convert_to_camel_case(text: str) -> str:
Expand Down Expand Up @@ -46,7 +49,7 @@ def convert_to_snake_case(text: str) -> str:
return re.sub(r"(?<!^)(?=[A-Z])", "_", text).lower()


def clean_url(url: str) -> str | None:
def clean_url(url: Optional[str]) -> Optional[str]:
"""Clean a URL by removing whitespace and trailing punctuation.

Args:
Expand Down Expand Up @@ -85,7 +88,7 @@ def get_nest_user_agent() -> str:
return settings.APP_NAME.replace(" ", "-").lower()


def get_user_ip_address(request) -> str:
def get_user_ip_address(request: HttpRequest) -> str:
"""Retrieve the user's IP address from the request.

Args:
Expand All @@ -102,7 +105,7 @@ def get_user_ip_address(request) -> str:
return x_forwarded_for.split(",")[0] if x_forwarded_for else request.META.get("REMOTE_ADDR")


def join_values(fields: list, delimiter: str = " ") -> str:
def join_values(fields: Iterable[Any], delimiter: str = " ") -> str:
"""Join non-empty field values using a specified delimiter.

Args:
Expand All @@ -116,7 +119,7 @@ def join_values(fields: list, delimiter: str = " ") -> str:
return delimiter.join(field for field in fields if field)


def natural_date(value: int | str) -> str:
def natural_date(value: int | str | datetime) -> str:
"""Convert a date or timestamp into a human-readable format.

Args:
Expand All @@ -136,7 +139,7 @@ def natural_date(value: int | str) -> str:
return naturaltime(dt)


def natural_number(value: int, unit=None) -> str:
def natural_number(value: int, unit: Optional[str] = None) -> str:
"""Convert a number into a human-readable format.

Args:
Expand Down Expand Up @@ -193,7 +196,7 @@ def truncate(text: str, limit: int, truncate: str = "...") -> str:
return Truncator(text).chars(limit, truncate=truncate)


def validate_url(url: str) -> bool:
def validate_url(url: Optional[str]) -> bool:
"""Validate that a URL has proper scheme and netloc.

Args:
Expand Down
10 changes: 7 additions & 3 deletions backend/apps/github/models/commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
from apps.common.models import BulkSaveModel, TimestampedModel
from apps.github.models.common import NodeModel

MAX_SHA_LENGTH = 64
MESSAGE_PREVIEW_LENGTH = 100
SHORT_SHA_LENGTH = 7


class Commit(BulkSaveModel, NodeModel, TimestampedModel):
"""Commit model."""
Expand All @@ -29,7 +33,7 @@ class Meta:
)
sha = models.CharField(
verbose_name="SHA",
max_length=64,
max_length=MAX_SHA_LENGTH,
help_text="Git commit SHA hash",
)

Expand Down Expand Up @@ -59,8 +63,8 @@ class Meta:

def __str__(self) -> str:
"""Return human-readable representation."""
short_sha = self.sha[:7] if self.sha else "unknown"
message_preview = self.message[:100] if self.message else "No message"
short_sha = self.sha[:SHORT_SHA_LENGTH] if self.sha else "unknown"
message_preview = self.message[:MESSAGE_PREVIEW_LENGTH] if self.message else "No message"
return f"{short_sha}: {message_preview}"

@staticmethod
Expand Down
3 changes: 2 additions & 1 deletion backend/apps/owasp/models/mixins/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from apps.owasp.models.mixins.common import RepositoryBasedEntityModelMixin

ISSUES_LIMIT = 6
MAX_HEALTH_SCORE = 100
RELEASES_LIMIT = 4
REPOSITORIES_LIMIT = 4

Expand Down Expand Up @@ -40,7 +41,7 @@ def idx_forks_count(self) -> int:
def idx_health_score(self) -> float | None:
"""Return health score for indexing."""
# TODO(arkid15r): Enable real health score in production when ready.
return 100 if settings.IS_PRODUCTION_ENVIRONMENT else self.health_score
return MAX_HEALTH_SCORE if settings.IS_PRODUCTION_ENVIRONMENT else self.health_score

@property
def idx_is_active(self) -> bool:
Expand Down