diff --git a/backend/apps/ai/models/context.py b/backend/apps/ai/models/context.py index f94d6810f0..b98d2e1835 100644 --- a/backend/apps/ai/models/context.py +++ b/backend/apps/ai/models/context.py @@ -10,6 +10,7 @@ from apps.common.utils import truncate logger = logging.getLogger(__name__) +SOURCE_MAX_LENGTH = 100 class Context(TimestampedModel): @@ -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" diff --git a/backend/apps/common/utils.py b/backend/apps/common/utils.py index 4b561670fc..1ce3a9a0f8 100644 --- a/backend/apps/common/utils.py +++ b/backend/apps/common/utils.py @@ -12,6 +12,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 + def convert_to_camel_case(text: str) -> str: @@ -47,7 +50,7 @@ def convert_to_snake_case(text: str) -> str: return re.sub(r"(? str | None: +def clean_url(url: Optional[str]) -> Optional[str]: """Clean a URL by removing whitespace and trailing punctuation. Args: @@ -86,7 +89,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: @@ -103,24 +106,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 is_valid_json(content: str) -> bool: - """Check if content is JSON format. - - Args: - content: The content to check - - Returns: - bool: True if content is valid JSON, False otherwise - - """ - try: - json.loads(content) - except (TypeError, ValueError): - return False - return True - - -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: @@ -134,7 +120,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: @@ -154,7 +140,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: @@ -211,7 +197,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: diff --git a/backend/apps/github/models/commit.py b/backend/apps/github/models/commit.py index b5525e56c4..04729b6bf2 100644 --- a/backend/apps/github/models/commit.py +++ b/backend/apps/github/models/commit.py @@ -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.""" @@ -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", ) @@ -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 diff --git a/backend/apps/owasp/models/mixins/project.py b/backend/apps/owasp/models/mixins/project.py index 515173359a..f20d6a29de 100644 --- a/backend/apps/owasp/models/mixins/project.py +++ b/backend/apps/owasp/models/mixins/project.py @@ -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 @@ -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: