Browse Source

fix: add types to monitors/utils (#65348)

Adds types to src/sentry/monitors/utils.py
Yagiz Nizipli 1 year ago
parent
commit
e81240050c

+ 1 - 2
pyproject.toml

@@ -54,7 +54,7 @@ python_version = "3.11"
 mypy_path = ["fixtures/stubs-for-mypy"]
 plugins = ["pydantic.mypy", "mypy_django_plugin.main", "tools.mypy_helpers.plugin"]
 files = ["."]
-exclude = ["^.venv/", "^self-hosted/"]
+exclude = ["^.venv/", "^venv/", "^self-hosted/"]
 
 # minimal strictness settings
 check_untyped_defs = true
@@ -387,7 +387,6 @@ module = [
     "sentry.monitors.endpoints.monitor_ingest_checkin_attachment",
     "sentry.monitors.endpoints.monitor_ingest_checkin_details",
     "sentry.monitors.endpoints.organization_monitor_index",
-    "sentry.monitors.utils",
     "sentry.monkey.pickle",
     "sentry.net.http",
     "sentry.net.socket",

+ 0 - 5
src/sentry/api/base.py

@@ -29,7 +29,6 @@ from sentry.api.exceptions import StaffRequired, SuperuserRequired
 from sentry.apidocs.hooks import HTTP_METHOD_NAME
 from sentry.auth import access
 from sentry.models.environment import Environment
-from sentry.models.user import User
 from sentry.ratelimits.config import DEFAULT_RATE_LIMIT_CONFIG, RateLimitConfig
 from sentry.silo import SiloLimit, SiloMode
 from sentry.types.ratelimit import RateLimit, RateLimitCategory
@@ -689,7 +688,3 @@ Apply to endpoints that are available in all silo modes.
 
 This should be rarely used, but is relevant for resources like ROBOTS.txt.
 """
-
-
-class AuthenticatedRequest(Request):
-    user: User

+ 4 - 3
src/sentry/api/endpoints/group_notes.py

@@ -5,7 +5,7 @@ from rest_framework import status
 from rest_framework.response import Response
 
 from sentry.api.api_publish_status import ApiPublishStatus
-from sentry.api.base import AuthenticatedRequest, region_silo_endpoint
+from sentry.api.base import region_silo_endpoint
 from sentry.api.bases.group import GroupEndpoint
 from sentry.api.paginator import DateTimePaginator
 from sentry.api.serializers import serialize
@@ -15,6 +15,7 @@ from sentry.models.groupsubscription import GroupSubscription
 from sentry.notifications.types import GroupSubscriptionReason
 from sentry.signals import comment_created
 from sentry.types.activity import ActivityType
+from sentry.utils.auth import AuthenticatedHttpRequest
 
 
 @region_silo_endpoint
@@ -24,7 +25,7 @@ class GroupNotesEndpoint(GroupEndpoint):
         "POST": ApiPublishStatus.UNKNOWN,
     }
 
-    def get(self, request: AuthenticatedRequest, group) -> Response:
+    def get(self, request: AuthenticatedHttpRequest, group) -> Response:
         notes = Activity.objects.filter(group=group, type=ActivityType.NOTE.value)
 
         return self.paginate(
@@ -35,7 +36,7 @@ class GroupNotesEndpoint(GroupEndpoint):
             on_results=lambda x: serialize(x, request.user),
         )
 
-    def post(self, request: AuthenticatedRequest, group) -> Response:
+    def post(self, request: AuthenticatedHttpRequest, group) -> Response:
         serializer = NoteSerializer(
             data=request.data,
             context={

+ 2 - 1
src/sentry/monitors/endpoints/organization_monitor_details.py

@@ -42,6 +42,7 @@ from sentry.monitors.utils import (
     update_issue_alert_rule,
 )
 from sentry.monitors.validators import MonitorValidator
+from sentry.utils.auth import AuthenticatedHttpRequest
 from sentry.utils.outcomes import Outcome
 
 
@@ -98,7 +99,7 @@ class OrganizationMonitorDetailsEndpoint(MonitorEndpoint):
             404: RESPONSE_NOT_FOUND,
         },
     )
-    def put(self, request: Request, organization, project, monitor) -> Response:
+    def put(self, request: AuthenticatedHttpRequest, organization, project, monitor) -> Response:
         """
         Update a monitor.
         """

+ 1 - 1
src/sentry/monitors/serializers.py

@@ -223,7 +223,7 @@ class MonitorCheckInSerializer(Serializer):
         if self._expand("groups") and self.start and self.end:
             # aggregate all the trace_ids in the given set of check-ins
             trace_ids = []
-            trace_groups: dict[str, list[dict[str, int]]] = defaultdict(list)
+            trace_groups: dict[str, list[dict[str, int | str]]] = defaultdict(list)
 
             for item in item_list:
                 if item.trace_id:

+ 8 - 4
src/sentry/monitors/utils.py

@@ -20,6 +20,7 @@ from sentry.signals import (
     first_cron_checkin_received,
     first_cron_monitor_created,
 )
+from sentry.utils.auth import AuthenticatedHttpRequest
 
 
 def signal_first_checkin(project: Project, monitor: Monitor):
@@ -61,7 +62,7 @@ def get_max_runtime(max_runtime: int | None) -> timedelta:
 def get_timeout_at(
     monitor_config: dict, status: CheckInStatus, date_added: datetime | None
 ) -> datetime | None:
-    if status == CheckInStatus.IN_PROGRESS:
+    if status == CheckInStatus.IN_PROGRESS and date_added is not None:
         return date_added.replace(second=0, microsecond=0) + get_max_runtime(
             (monitor_config or {}).get("max_runtime")
         )
@@ -98,7 +99,7 @@ def get_checkin_margin(checkin_margin: int | None) -> timedelta:
 
 def fetch_associated_groups(
     trace_ids: list[str], organization_id: int, project_id: int, start: datetime, end
-) -> dict[str, list[dict[str, int]]]:
+) -> dict[str, list[dict[str, int | str]]]:
     """
     Returns serializer appropriate group_ids corresponding with check-in trace ids
     :param trace_ids: list of trace_ids from the given check-ins
@@ -200,8 +201,11 @@ def fetch_associated_groups(
 
 
 def create_issue_alert_rule(
-    request: Request, project: Project, monitor: Monitor, validated_issue_alert_rule: dict
-):
+    request: AuthenticatedHttpRequest,
+    project: Project,
+    monitor: Monitor,
+    validated_issue_alert_rule: dict,
+) -> int | None:
     """
     Creates an Issue Alert `Rule` instance from a request with the given data
     :param request: Request object

+ 7 - 0
src/sentry/utils/auth.py

@@ -13,6 +13,7 @@ from django.contrib.auth.backends import ModelBackend
 from django.http.request import HttpRequest
 from django.urls import resolve, reverse
 from django.utils.http import url_has_allowed_host_and_scheme
+from rest_framework.request import Request
 
 from sentry import options
 from sentry.models.organization import Organization
@@ -448,3 +449,9 @@ def construct_link_with_query(path: str, query_params: dict[str, str]) -> str:
     if query_string:
         redirect_uri += f"?{query_string}"
     return redirect_uri
+
+
+# Used to create a HttpRequest that's guaranteed to have an authenticated user
+# Ref: https://github.com/typeddjango/django-stubs?tab=readme-ov-file#how-can-i-create-a-httprequest-thats-guaranteed-to-have-an-authenticated-user
+class AuthenticatedHttpRequest(Request):
+    user: User