Browse Source

ref: fix 'base class ... defined the type as None mypy errors (attempt 2) (#56206)

the first one ran into an `AttributeError` in the github oauth provider
-- I've enabled typing for that module as well and fixed the problem
there:

```pytb
  File "sentry/auth/helper.py", line 717, in __init__
    super().__init__(request, provider_key, organization, auth_provider)  # type: ignore
  File "sentry/pipeline/base.py", line 124, in __init__
    self.pipeline_views = self.get_pipeline_views()
  File "sentry/auth/helper.py", line 734, in get_pipeline_views
    return self.provider.get_auth_pipeline()
  File "sentry/auth/providers/github/provider.py", line 29, in get_auth_pipeline
    OAuth2Login(authorize_url=self.authorize_url, client_id=self.client_id, scope=SCOPE),
AttributeError: 'GitHubOAuth2Provider' object has no attribute 'client_id'
```
anthony sottile 1 year ago
parent
commit
41e8adcda3

+ 0 - 12
pyproject.toml

@@ -359,7 +359,6 @@ module = [
     "sentry.auth.helper",
     "sentry.auth.helper",
     "sentry.auth.provider",
     "sentry.auth.provider",
     "sentry.auth.providers.dummy",
     "sentry.auth.providers.dummy",
-    "sentry.auth.providers.github.provider",
     "sentry.auth.providers.github.views",
     "sentry.auth.providers.github.views",
     "sentry.auth.providers.google.apps",
     "sentry.auth.providers.google.apps",
     "sentry.auth.providers.google.views",
     "sentry.auth.providers.google.views",
@@ -428,12 +427,10 @@ module = [
     "sentry.integrations.bitbucket.installed",
     "sentry.integrations.bitbucket.installed",
     "sentry.integrations.bitbucket.integration",
     "sentry.integrations.bitbucket.integration",
     "sentry.integrations.bitbucket.issues",
     "sentry.integrations.bitbucket.issues",
-    "sentry.integrations.bitbucket.repository",
     "sentry.integrations.bitbucket.uninstalled",
     "sentry.integrations.bitbucket.uninstalled",
     "sentry.integrations.bitbucket.webhook",
     "sentry.integrations.bitbucket.webhook",
     "sentry.integrations.bitbucket_server.client",
     "sentry.integrations.bitbucket_server.client",
     "sentry.integrations.bitbucket_server.integration",
     "sentry.integrations.bitbucket_server.integration",
-    "sentry.integrations.bitbucket_server.repository",
     "sentry.integrations.bitbucket_server.webhook",
     "sentry.integrations.bitbucket_server.webhook",
     "sentry.integrations.example.integration",
     "sentry.integrations.example.integration",
     "sentry.integrations.example.repository",
     "sentry.integrations.example.repository",
@@ -444,12 +441,10 @@ module = [
     "sentry.integrations.github.webhook",
     "sentry.integrations.github.webhook",
     "sentry.integrations.github_enterprise.client",
     "sentry.integrations.github_enterprise.client",
     "sentry.integrations.github_enterprise.integration",
     "sentry.integrations.github_enterprise.integration",
-    "sentry.integrations.github_enterprise.repository",
     "sentry.integrations.github_enterprise.webhook",
     "sentry.integrations.github_enterprise.webhook",
     "sentry.integrations.gitlab.client",
     "sentry.integrations.gitlab.client",
     "sentry.integrations.gitlab.integration",
     "sentry.integrations.gitlab.integration",
     "sentry.integrations.gitlab.issues",
     "sentry.integrations.gitlab.issues",
-    "sentry.integrations.gitlab.repository",
     "sentry.integrations.gitlab.webhooks",
     "sentry.integrations.gitlab.webhooks",
     "sentry.integrations.jira.actions.create_ticket",
     "sentry.integrations.jira.actions.create_ticket",
     "sentry.integrations.jira.actions.form",
     "sentry.integrations.jira.actions.form",
@@ -521,9 +516,6 @@ module = [
     "sentry.issues.search",
     "sentry.issues.search",
     "sentry.issues.status_change",
     "sentry.issues.status_change",
     "sentry.mail.adapter",
     "sentry.mail.adapter",
-    "sentry.mail.forms.assigned_to",
-    "sentry.mail.forms.member_team",
-    "sentry.mail.forms.notify_email",
     "sentry.mail.notifications",
     "sentry.mail.notifications",
     "sentry.management.commands.makemigrations",
     "sentry.management.commands.makemigrations",
     "sentry.management.commands.send_fake_data",
     "sentry.management.commands.send_fake_data",
@@ -583,12 +575,8 @@ module = [
     "sentry.plugins.endpoints",
     "sentry.plugins.endpoints",
     "sentry.plugins.helpers",
     "sentry.plugins.helpers",
     "sentry.plugins.providers.base",
     "sentry.plugins.providers.base",
-    "sentry.plugins.providers.dummy.repository",
     "sentry.plugins.providers.integration_repository",
     "sentry.plugins.providers.integration_repository",
     "sentry.plugins.providers.repository",
     "sentry.plugins.providers.repository",
-    "sentry.plugins.sentry_interface_types.models",
-    "sentry.plugins.sentry_urls.models",
-    "sentry.plugins.sentry_useragents.models",
     "sentry.plugins.sentry_webhooks.plugin",
     "sentry.plugins.sentry_webhooks.plugin",
     "sentry.plugins.validators.url",
     "sentry.plugins.validators.url",
     "sentry.profiles.task",
     "sentry.profiles.task",

+ 11 - 5
src/sentry/auth/providers/github/provider.py

@@ -10,8 +10,12 @@ class GitHubOAuth2Provider(OAuth2Provider):
     access_token_url = ACCESS_TOKEN_URL
     access_token_url = ACCESS_TOKEN_URL
     authorize_url = AUTHORIZE_URL
     authorize_url = AUTHORIZE_URL
     name = "GitHub"
     name = "GitHub"
-    client_id = CLIENT_ID
-    client_secret = CLIENT_SECRET
+
+    def get_client_id(self):
+        return CLIENT_ID
+
+    def get_client_secret(self):
+        return CLIENT_SECRET
 
 
     def __init__(self, org=None, **config):
     def __init__(self, org=None, **config):
         super().__init__(**config)
         super().__init__(**config)
@@ -22,11 +26,13 @@ class GitHubOAuth2Provider(OAuth2Provider):
 
 
     def get_auth_pipeline(self):
     def get_auth_pipeline(self):
         return [
         return [
-            OAuth2Login(authorize_url=self.authorize_url, client_id=self.client_id, scope=SCOPE),
+            OAuth2Login(
+                authorize_url=self.authorize_url, client_id=self.get_client_id(), scope=SCOPE
+            ),
             OAuth2Callback(
             OAuth2Callback(
                 access_token_url=self.access_token_url,
                 access_token_url=self.access_token_url,
-                client_id=self.client_id,
-                client_secret=self.client_secret,
+                client_id=self.get_client_id(),
+                client_secret=self.get_client_secret(),
             ),
             ),
             FetchUser(org=self.org),
             FetchUser(org=self.org),
             ConfirmEmail(),
             ConfirmEmail(),

+ 4 - 4
src/sentry/auth/providers/oauth2.py

@@ -123,15 +123,15 @@ class OAuth2Callback(AuthView):
 
 
 
 
 class OAuth2Provider(Provider, abc.ABC):
 class OAuth2Provider(Provider, abc.ABC):
-    client_id = None
-    client_secret = None
     is_partner = False
     is_partner = False
 
 
+    @abc.abstractmethod
     def get_client_id(self):
     def get_client_id(self):
-        return self.client_id
+        raise NotImplementedError
 
 
+    @abc.abstractmethod
     def get_client_secret(self):
     def get_client_secret(self):
-        return self.client_secret
+        raise NotImplementedError
 
 
     def get_auth_pipeline(self):
     def get_auth_pipeline(self):
         return [
         return [

+ 6 - 6
src/sentry/integrations/mixins/issues.py

@@ -4,7 +4,7 @@ import enum
 import logging
 import logging
 from collections import defaultdict
 from collections import defaultdict
 from copy import deepcopy
 from copy import deepcopy
-from typing import Any, Mapping, Sequence
+from typing import Any, ClassVar, Mapping, Sequence
 
 
 from sentry.integrations.utils import where_should_sync
 from sentry.integrations.utils import where_should_sync
 from sentry.models import ExternalIssue, GroupLink, UserOption
 from sentry.models import ExternalIssue, GroupLink, UserOption
@@ -341,11 +341,11 @@ class IssueBasicMixin:
 
 
 
 
 class IssueSyncMixin(IssueBasicMixin):
 class IssueSyncMixin(IssueBasicMixin):
-    comment_key = None
-    outbound_status_key = None
-    inbound_status_key = None
-    outbound_assignee_key = None
-    inbound_assignee_key = None
+    comment_key: ClassVar[str | None] = None
+    outbound_status_key: ClassVar[str | None] = None
+    inbound_status_key: ClassVar[str | None] = None
+    outbound_assignee_key: ClassVar[str | None] = None
+    inbound_assignee_key: ClassVar[str | None] = None
 
 
     def should_sync(self, attribute: str) -> bool:
     def should_sync(self, attribute: str) -> bool:
         key = getattr(self, f"{attribute}_key", None)
         key = getattr(self, f"{attribute}_key", None)

+ 1 - 1
src/sentry/mail/forms/assigned_to.py

@@ -4,7 +4,7 @@ from sentry.mail.forms.member_team import MemberTeamForm
 from sentry.notifications.types import ASSIGNEE_CHOICES, AssigneeTargetType
 from sentry.notifications.types import ASSIGNEE_CHOICES, AssigneeTargetType
 
 
 
 
-class AssignedToForm(MemberTeamForm):
+class AssignedToForm(MemberTeamForm[AssigneeTargetType]):
     targetType = forms.ChoiceField(choices=ASSIGNEE_CHOICES)
     targetType = forms.ChoiceField(choices=ASSIGNEE_CHOICES)
 
 
     teamValue = AssigneeTargetType.TEAM
     teamValue = AssigneeTargetType.TEAM

+ 11 - 5
src/sentry/mail/forms/member_team.py

@@ -1,19 +1,24 @@
 from __future__ import annotations
 from __future__ import annotations
 
 
+import enum
+from typing import Generic, TypeVar
+
 from django import forms
 from django import forms
 
 
 from sentry.models import OrganizationMemberTeam, Project
 from sentry.models import OrganizationMemberTeam, Project
 from sentry.services.hybrid_cloud.user.service import user_service
 from sentry.services.hybrid_cloud.user.service import user_service
 
 
+T = TypeVar("T", bound=enum.Enum)
+
 
 
-class MemberTeamForm(forms.Form):
+class MemberTeamForm(forms.Form, Generic[T]):
     targetType = forms.ChoiceField()
     targetType = forms.ChoiceField()
     targetIdentifier = forms.CharField(
     targetIdentifier = forms.CharField(
         required=False, help_text="Only required if 'Member' or 'Team' is selected"
         required=False, help_text="Only required if 'Member' or 'Team' is selected"
     )
     )
-    teamValue = None
-    memberValue = None
-    targetTypeEnum = None
+    teamValue: T
+    memberValue: T
+    targetTypeEnum: type[T]
 
 
     def __init__(self, project, *args, **kwargs):
     def __init__(self, project, *args, **kwargs):
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)
@@ -32,7 +37,8 @@ class MemberTeamForm(forms.Form):
         return targetIdentifier
         return targetIdentifier
 
 
     def clean(self) -> None:
     def clean(self) -> None:
-        cleaned_data = super().clean()
+        super().clean()
+        cleaned_data = self.cleaned_data
         try:
         try:
             targetType = self.targetTypeEnum(cleaned_data.get("targetType"))
             targetType = self.targetTypeEnum(cleaned_data.get("targetType"))
         except ValueError:
         except ValueError:

+ 1 - 1
src/sentry/mail/forms/notify_email.py

@@ -4,7 +4,7 @@ from sentry.mail.forms.member_team import MemberTeamForm
 from sentry.notifications.types import ACTION_CHOICES, ActionTargetType
 from sentry.notifications.types import ACTION_CHOICES, ActionTargetType
 
 
 
 
-class NotifyEmailForm(MemberTeamForm):
+class NotifyEmailForm(MemberTeamForm[ActionTargetType]):
     targetType = forms.ChoiceField(choices=ACTION_CHOICES)
     targetType = forms.ChoiceField(choices=ACTION_CHOICES)
 
 
     teamValue = ActionTargetType.TEAM
     teamValue = ActionTargetType.TEAM

+ 5 - 1
src/sentry/plugins/bases/tag.py

@@ -1,9 +1,13 @@
+from __future__ import annotations
+
+from typing import ClassVar
+
 from sentry.constants import MAX_TAG_VALUE_LENGTH
 from sentry.constants import MAX_TAG_VALUE_LENGTH
 from sentry.plugins.base.v2 import Plugin2
 from sentry.plugins.base.v2 import Plugin2
 
 
 
 
 class TagPlugin(Plugin2):
 class TagPlugin(Plugin2):
-    tag = None
+    tag: ClassVar[str]
     project_default_enabled = True
     project_default_enabled = True
 
 
     def get_tag_values(self, event, **kwargs):
     def get_tag_values(self, event, **kwargs):

+ 3 - 3
src/sentry/plugins/providers/integration_repository.py

@@ -2,7 +2,7 @@ from __future__ import annotations
 
 
 import logging
 import logging
 from datetime import timezone
 from datetime import timezone
-from typing import Any, MutableMapping
+from typing import Any, ClassVar, MutableMapping
 
 
 from dateutil.parser import parse as parse_date
 from dateutil.parser import parse as parse_date
 from rest_framework.request import Request
 from rest_framework.request import Request
@@ -49,8 +49,8 @@ class IntegrationRepositoryProvider:
     Does not include plugins.
     Does not include plugins.
     """
     """
 
 
-    name = None
-    repo_provider = None
+    name: ClassVar[str]
+    repo_provider: ClassVar[str]
 
 
     def __init__(self, id):
     def __init__(self, id):
         self.id = id
         self.id = id

+ 4 - 1
src/sentry/plugins/providers/repository.py

@@ -1,4 +1,7 @@
+from __future__ import annotations
+
 from logging import getLogger
 from logging import getLogger
+from typing import ClassVar
 
 
 from django.db import IntegrityError, router, transaction
 from django.db import IntegrityError, router, transaction
 from django.urls import reverse
 from django.urls import reverse
@@ -24,7 +27,7 @@ class RepositoryProvider(ProviderMixin):
     Does not include the integrations in the sentry repository.
     Does not include the integrations in the sentry repository.
     """
     """
 
 
-    name = None
+    name: ClassVar[str]
 
 
     def __init__(self, id):
     def __init__(self, id):
         self.id = id
         self.id = id

Some files were not shown because too many files changed in this diff