re-enable mypy GitHub Actions CI job (#2390)

# What this PR does

```bash
❯ mypy .
Success: no issues found in 595 source files
```

- re-enable the mypy CI check
- fixes all `django-manager-missing` mypy errors
- disable all other rules currently giving mypy errors
- changing the approach here. rather than enforcing that backend
contributors fix >= 1 `mypy` error on their PR, lets simply disable all
the rules that're currently returning errors and slowly re-enable these
one at a time #2392

## Checklist

- [ ] Unit, integration, and e2e (if applicable) tests updated (N/A)
- [ ] Documentation added (or `pr:no public docs` PR label added if not
required) (N/A)
- [ ] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required) (N/A)
This commit is contained in:
Joey Orlando 2023-06-29 16:01:52 +02:00 committed by GitHub
parent c705bded9f
commit cc20c9dfdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 157 additions and 11 deletions

View file

@ -283,8 +283,6 @@ jobs:
mypy:
name: "mypy"
# disable until we fix all the pre-existing errors (aka https://github.com/grafana/oncall/issues/2168 is marked as completed)
if: ${{ false }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

View file

@ -41,7 +41,7 @@ from common.public_primary_keys import generate_public_primary_key, increase_pub
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import GrafanaAlertingContactPoint
from apps.alerts.models import ChannelFilter, GrafanaAlertingContactPoint
logger = logging.getLogger(__name__)
@ -114,6 +114,7 @@ class AlertReceiveChannel(IntegrationOptionsMixin, MaintainableObject):
Channel generated by user to receive Alerts to.
"""
channel_filters: "RelatedManager['ChannelFilter']"
contact_points: "RelatedManager['GrafanaAlertingContactPoint']"
objects = AlertReceiveChannelManager()

View file

@ -1,6 +1,7 @@
import json
import logging
import re
import typing
from json import JSONDecodeError
from django.conf import settings
@ -14,6 +15,12 @@ from common.jinja_templater import apply_jinja_template
from common.jinja_templater.apply_jinja_template import JinjaTemplateError, JinjaTemplateWarning
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import EscalationPolicy
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
@ -46,6 +53,8 @@ class CustomButtonManager(models.Manager):
class CustomButton(models.Model):
escalation_policies: "RelatedManager['EscalationPolicy']"
objects = CustomButtonManager()
objects_with_deleted = models.Manager()

View file

@ -1,3 +1,5 @@
import typing
from django.conf import settings
from django.core.validators import MinLengthValidator
from django.db import models, transaction
@ -5,6 +7,11 @@ from django.db import models, transaction
from apps.alerts.models.escalation_policy import generate_public_primary_key_for_escalation_policy
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import ChannelFilter, EscalationPolicy
def generate_public_primary_key_for_escalation_chain():
prefix = "F"
@ -21,6 +28,9 @@ def generate_public_primary_key_for_escalation_chain():
class EscalationChain(models.Model):
channel_filters: "RelatedManager['ChannelFilter']"
escalation_policies: "RelatedManager['EscalationPolicy']"
public_primary_key = models.CharField(
max_length=20,
validators=[MinLengthValidator(settings.PUBLIC_PRIMARY_KEY_MIN_LENGTH + 1)],

View file

@ -229,7 +229,10 @@ class EscalationPolicy(OrderedModel):
"alerts.EscalationChain", on_delete=models.CASCADE, related_name="escalation_policies"
)
notify_to_users_queue = models.ManyToManyField("user_management.User")
notify_to_users_queue = models.ManyToManyField(
"user_management.User",
related_name="escalation_policy_notify_queues",
)
last_notified_user = models.ForeignKey(
"user_management.User",
@ -244,6 +247,7 @@ class EscalationPolicy(OrderedModel):
notify_to_group = models.ForeignKey(
"slack.SlackUserGroup",
on_delete=models.SET_NULL,
related_name="escalation_policies",
default=None,
null=True,
)

View file

@ -8,6 +8,8 @@ from apps.user_management.models import Organization, User
class ApiAuthToken(BaseAuthToken):
objects: models.QuerySet["ApiAuthToken"]
user = models.ForeignKey(to=User, null=False, blank=False, related_name="auth_tokens", on_delete=models.CASCADE)
organization = models.ForeignKey(
to=Organization, null=False, blank=False, related_name="auth_tokens", on_delete=models.CASCADE

View file

@ -16,8 +16,14 @@ from apps.user_management.models import Organization
class PluginAuthToken(BaseAuthToken):
objects: models.Manager["PluginAuthToken"]
salt = models.CharField(max_length=constants.AUTH_TOKEN_CHARACTER_LENGTH, null=True)
organization = models.ForeignKey(to=Organization, on_delete=models.CASCADE)
organization = models.ForeignKey(
to=Organization,
on_delete=models.CASCADE,
related_name="plugin_auth_tokens",
)
@classmethod
def create_auth_token(cls, organization: Organization) -> Tuple["PluginAuthToken", str]:

View file

@ -9,6 +9,8 @@ from apps.user_management.models import Organization, User
class ScheduleExportAuthToken(BaseAuthToken):
objects: models.Manager["ScheduleExportAuthToken"]
class Meta:
unique_together = ("user", "organization", "schedule")

View file

@ -8,6 +8,8 @@ from apps.user_management.models import Organization, User
class UserScheduleExportAuthToken(BaseAuthToken):
objects: models.Manager["UserScheduleExportAuthToken"]
class Meta:
unique_together = ("user", "organization")

View file

@ -52,6 +52,8 @@ class MobileAppVerificationToken(BaseAuthToken):
class MobileAppAuthToken(BaseAuthToken):
objects: models.Manager["MobileAppAuthToken"]
user = models.OneToOneField(to=User, null=False, blank=False, on_delete=models.CASCADE)
organization = models.ForeignKey(
to=Organization, null=False, blank=False, related_name="mobile_app_auth_tokens", on_delete=models.CASCADE

View file

@ -2,6 +2,7 @@ import copy
import datetime
import itertools
import logging
import typing
from calendar import monthrange
from uuid import uuid4
@ -27,6 +28,12 @@ from apps.schedules.tasks import (
from apps.user_management.models import User
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.schedules.models import OnCallSchedule
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
@ -46,6 +53,8 @@ def generate_public_primary_key_for_custom_oncall_shift():
class CustomOnCallShift(models.Model):
schedules: "RelatedManager['OnCallSchedule']"
(
FREQUENCY_DAILY,
FREQUENCY_WEEKLY,

View file

@ -46,6 +46,13 @@ from apps.user_management.models import User
from common.database import NON_POLYMORPHIC_CASCADE, NON_POLYMORPHIC_SET_NULL
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import EscalationPolicy
from apps.auth_token.models import ScheduleExportAuthToken
RE_ICAL_SEARCH_USERNAME = r"SUMMARY:(\[L[0-9]+\] )?{}"
RE_ICAL_FETCH_USERNAME = re.compile(r"SUMMARY:(?:\[L[0-9]+\] )?(\w+)")
@ -836,6 +843,10 @@ class OnCallSchedule(PolymorphicModel):
class OnCallScheduleICal(OnCallSchedule):
escalation_policies: "RelatedManager['EscalationPolicy']"
objects: models.Manager["OnCallScheduleICal"]
schedule_export_token: "RelatedManager['ScheduleExportAuthToken']"
# For the ical schedule both primary and overrides icals are imported via ical url
ical_url_primary = models.CharField(max_length=500, null=True, default=None)
ical_file_error_primary = models.CharField(max_length=200, null=True, default=None)
@ -901,6 +912,10 @@ class OnCallScheduleICal(OnCallSchedule):
class OnCallScheduleCalendar(OnCallSchedule):
escalation_policies: "RelatedManager['EscalationPolicy']"
objects: models.Manager["OnCallScheduleCalendar"]
schedule_export_token: "RelatedManager['ScheduleExportAuthToken']"
# For the calendar schedule only overrides ical is imported via ical url.
ical_url_overrides = models.CharField(max_length=500, null=True, default=None)
ical_file_error_overrides = models.CharField(max_length=200, null=True, default=None)
@ -994,6 +1009,10 @@ class OnCallScheduleCalendar(OnCallSchedule):
class OnCallScheduleWeb(OnCallSchedule):
escalation_policies: "RelatedManager['EscalationPolicy']"
objects: models.Manager["OnCallScheduleWeb"]
schedule_export_token: "RelatedManager['ScheduleExportAuthToken']"
time_zone = models.CharField(max_length=100, default="UTC")
def _generate_ical_file_primary(self):

View file

@ -1,4 +1,5 @@
import logging
import typing
import requests
from django.conf import settings
@ -13,6 +14,13 @@ from apps.slack.slack_client.exceptions import SlackAPIException
from apps.user_management.models.user import User
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import EscalationPolicy
from apps.schedules.models import OnCallSchedule
logger = logging.getLogger(__name__)
@ -31,6 +39,9 @@ def generate_public_primary_key_for_slack_user_group():
class SlackUserGroup(models.Model):
escalation_policies: "RelatedManager['EscalationPolicy']"
oncall_schedules: "RelatedManager['OnCallSchedule']"
public_primary_key = models.CharField(
max_length=20,
validators=[MinLengthValidator(settings.PUBLIC_PRIMARY_KEY_MIN_LENGTH + 1)],

View file

@ -1,5 +1,5 @@
import logging
from typing import Optional
import typing
from django.conf import settings
from django.core.validators import MinLengthValidator
@ -13,6 +13,12 @@ from apps.telegram.models import TelegramMessage
from common.insight_log.chatops_insight_logs import ChatOpsEvent, ChatOpsTypePlug, write_chatops_insight_log
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import ChannelFilter
logger = logging.getLogger(__name__)
@ -31,6 +37,8 @@ def generate_public_primary_key_for_telegram_to_at_connector() -> str:
class TelegramToOrganizationConnector(models.Model):
channel_filter: "RelatedManager['ChannelFilter']"
public_primary_key = models.CharField(
max_length=20,
validators=[MinLengthValidator(settings.PUBLIC_PRIMARY_KEY_MIN_LENGTH + 1)],
@ -60,7 +68,7 @@ class TelegramToOrganizationConnector(models.Model):
return self.channel_chat_id is not None and self.discussion_group_chat_id is not None
@classmethod
def get_channel_for_alert_group(cls, alert_group: AlertGroup) -> Optional["TelegramToOrganizationConnector"]:
def get_channel_for_alert_group(cls, alert_group: AlertGroup) -> typing.Optional["TelegramToOrganizationConnector"]:
# TODO: add custom queryset
dm_messages_exist = alert_group.telegram_messages.filter(
~Q(chat_id__startswith="-")

View file

@ -21,6 +21,13 @@ from common.public_primary_keys import generate_public_primary_key, increase_pub
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.auth_token.models import (
ApiAuthToken,
PluginAuthToken,
ScheduleExportAuthToken,
UserScheduleExportAuthToken,
)
from apps.mobile_app.models import MobileAppAuthToken
from apps.schedules.models import OnCallSchedule
from apps.user_management.models import User
@ -69,8 +76,13 @@ class OrganizationManager(models.Manager):
class Organization(MaintainableObject):
users: "RelatedManager['User']"
auth_tokens: "RelatedManager['ApiAuthToken']"
mobile_app_auth_tokens: "RelatedManager['MobileAppAuthToken']"
oncall_schedules: "RelatedManager['OnCallSchedule']"
plugin_auth_tokens: "RelatedManager['PluginAuthToken']"
schedule_export_token: "RelatedManager['ScheduleExportAuthToken']"
user_schedule_export_token: "RelatedManager['UserScheduleExportAuthToken']"
users: "RelatedManager['User']"
objects = OrganizationManager()
objects_with_deleted = models.Manager()

View file

@ -1,3 +1,5 @@
import typing
from django.conf import settings
from django.core.validators import MinLengthValidator
from django.db import models
@ -6,6 +8,11 @@ from apps.metrics_exporter.helpers import metrics_bulk_update_team_label_cache
from apps.metrics_exporter.metrics_cache_manager import MetricsCacheManager
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import AlertGroupLogRecord
def generate_public_primary_key_for_team():
prefix = "T"
@ -76,6 +83,8 @@ class TeamManager(models.Manager):
class Team(models.Model):
oncall_schedules: "RelatedManager['AlertGroupLogRecord']"
public_primary_key = models.CharField(
max_length=20,
validators=[MinLengthValidator(settings.PUBLIC_PRIMARY_KEY_MIN_LENGTH + 1)],

View file

@ -21,6 +21,12 @@ from apps.api.permissions import (
from apps.schedules.tasks import drop_cached_ical_for_custom_events_for_organization
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import EscalationPolicy
from apps.auth_token.models import ApiAuthToken, ScheduleExportAuthToken, UserScheduleExportAuthToken
logger = logging.getLogger(__name__)
@ -137,6 +143,12 @@ class UserQuerySet(models.QuerySet):
class User(models.Model):
auth_tokens: "RelatedManager['ApiAuthToken']"
escalation_policy_notify_queues: "RelatedManager['EscalationPolicy']"
last_notified_in_escalation_policies: "RelatedManager['EscalationPolicy']"
schedule_export_token: "RelatedManager['ScheduleExportAuthToken']"
user_schedule_export_token: "RelatedManager['UserScheduleExportAuthToken']"
objects = UserManager.from_queryset(UserQuerySet)()
class Meta:

View file

@ -1,4 +1,5 @@
import json
import typing
from json import JSONDecodeError
import requests
@ -23,6 +24,11 @@ from common.jinja_templater import apply_jinja_template
from common.jinja_templater.apply_jinja_template import JinjaTemplateError, JinjaTemplateWarning
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
if typing.TYPE_CHECKING:
from django.db.models.manager import RelatedManager
from apps.alerts.models import EscalationPolicy
WEBHOOK_FIELD_PLACEHOLDER = "****************"
@ -54,6 +60,8 @@ class WebhookManager(models.Manager):
class Webhook(models.Model):
escalation_policies: "RelatedManager['EscalationPolicy']"
objects = WebhookManager()
objects_with_deleted = models.Manager()

View file

@ -23,6 +23,28 @@ exclude = [
"tests/test_.*\\.py$", # test files
"migrations/\\d*.*\\.py", # migration files
]
disable_error_code = [
"abstract",
"annotation-unchecked",
"arg-type",
"assignment",
"attr-defined",
"call-arg",
"call-overload",
"has-type",
"import",
"index",
"misc",
"name-defined",
"no-redef",
"operator",
"return",
"return-value",
"typeddict-item",
"union-attr",
"valid-type",
"var-annotated",
]
# mypy per-module options
[[tool.mypy.overrides]]

View file

@ -1,8 +1,8 @@
celery-types==0.18.0
django-filter-stubs==0.1.3
django-stubs[compatible-mypy]==4.2.1
djangorestframework-stubs[compatible-mypy]==3.14.1
mypy==1.3.0
django-stubs[compatible-mypy]==4.2.2
djangorestframework-stubs[compatible-mypy]==3.14.2
mypy==1.4.1
pre-commit==2.15.0
pytest==7.3.1
pytest-django==4.5.2