Browse Source

ref(backup): Fix mypy errors in backup.py (#53623)

These changes make mypy happy with backup.py.
Alex Zaslavsky 1 year ago
parent
commit
4cd1e5cc38
2 changed files with 22 additions and 21 deletions
  1. 0 1
      pyproject.toml
  2. 22 20
      src/sentry/runner/commands/backup.py

+ 0 - 1
pyproject.toml

@@ -743,7 +743,6 @@ module = [
     "sentry.rules.history.preview",
     "sentry.rules.history.preview",
     "sentry.rules.processor",
     "sentry.rules.processor",
     "sentry.rules.registry",
     "sentry.rules.registry",
-    "sentry.runner.commands.backup",
     "sentry.runner.commands.migrations",
     "sentry.runner.commands.migrations",
     "sentry.runner.importer",
     "sentry.runner.importer",
     "sentry.runner.initializer",
     "sentry.runner.initializer",

+ 22 - 20
src/sentry/runner/commands/backup.py

@@ -5,7 +5,7 @@ from copy import deepcopy
 from datetime import datetime, timedelta, timezone
 from datetime import datetime, timedelta, timezone
 from difflib import unified_diff
 from difflib import unified_diff
 from io import StringIO
 from io import StringIO
-from typing import Dict, List, NamedTuple, NewType
+from typing import Dict, List, NamedTuple
 
 
 import click
 import click
 from dateutil import parser
 from dateutil import parser
@@ -14,6 +14,7 @@ from django.core import management, serializers
 from django.core.serializers import serialize
 from django.core.serializers import serialize
 from django.core.serializers.json import DjangoJSONEncoder
 from django.core.serializers.json import DjangoJSONEncoder
 from django.db import IntegrityError, connection, transaction
 from django.db import IntegrityError, connection, transaction
+from django.db.models.fields.related import ManyToManyField
 
 
 from sentry.runner.decorators import configuration
 from sentry.runner.decorators import configuration
 from sentry.utils.json import JSONData, JSONEncoder, better_default_encoder
 from sentry.utils.json import JSONData, JSONEncoder, better_default_encoder
@@ -23,8 +24,6 @@ JSON_PRETTY_PRINTER = JSONEncoder(
     default=better_default_encoder, indent=2, ignore_nan=True, sort_keys=True
     default=better_default_encoder, indent=2, ignore_nan=True, sort_keys=True
 )
 )
 
 
-ComparatorKind = NewType("ComparatorKind", str)
-
 
 
 # TODO(team-ospo/#155): Figure out if we are going to use `pk` as part of the identifier, or some other kind of sequence number internal to the JSON export instead.
 # TODO(team-ospo/#155): Figure out if we are going to use `pk` as part of the identifier, or some other kind of sequence number internal to the JSON export instead.
 class InstanceID(NamedTuple):
 class InstanceID(NamedTuple):
@@ -41,7 +40,7 @@ class InstanceID(NamedTuple):
 class ComparatorFinding(NamedTuple):
 class ComparatorFinding(NamedTuple):
     """Store all information about a single failed matching between expected and actual output."""
     """Store all information about a single failed matching between expected and actual output."""
 
 
-    kind: ComparatorKind
+    kind: str
     on: InstanceID
     on: InstanceID
     reason: str = ""
     reason: str = ""
 
 
@@ -121,7 +120,7 @@ class JSONScrubbingComparator(ABC):
             del right["fields"][field]
             del right["fields"][field]
             right["scrubbed"][f"{self.get_kind()}::{field}"] = True
             right["scrubbed"][f"{self.get_kind()}::{field}"] = True
 
 
-    def get_kind(self) -> ComparatorKind:
+    def get_kind(self) -> str:
         """A unique identifier for this particular derivation of JSONScrubbingComparator, which will
         """A unique identifier for this particular derivation of JSONScrubbingComparator, which will
         be bubbled up in ComparatorFindings when they are generated."""
         be bubbled up in ComparatorFindings when they are generated."""
 
 
@@ -146,6 +145,7 @@ class DateUpdatedComparator(JSONScrubbingComparator):
                 reason=f"""the left date_updated value on `{on}` ({left_date_updated}) was not less
                 reason=f"""the left date_updated value on `{on}` ({left_date_updated}) was not less
                 than or equal to the right ({right_date_updated})""",
                 than or equal to the right ({right_date_updated})""",
             )
             )
+        return None
 
 
 
 
 ComparatorList = List[JSONScrubbingComparator]
 ComparatorList = List[JSONScrubbingComparator]
@@ -219,7 +219,7 @@ def validate(
             for cmp in comparators[id.model]:
             for cmp in comparators[id.model]:
                 res = cmp.compare(id, exp, act)
                 res = cmp.compare(id, exp, act)
                 if res:
                 if res:
-                    findings.append(ComparatorFinding(cmp.get_kind(), id, res))
+                    findings.append(res)
             for cmp in comparators[id.model]:
             for cmp in comparators[id.model]:
                 cmp.scrub(id, exp, act)
                 cmp.scrub(id, exp, act)
 
 
@@ -284,9 +284,9 @@ def sort_dependencies():
         if app_config.label in EXCLUDED_APPS:
         if app_config.label in EXCLUDED_APPS:
             continue
             continue
 
 
-        model_list = app_config.get_models()
+        model_iterator = app_config.get_models()
 
 
-        for model in model_list:
+        for model in model_iterator:
             models.add(model)
             models.add(model)
             # Add any explicitly defined dependencies
             # Add any explicitly defined dependencies
             if hasattr(model, "natural_key"):
             if hasattr(model, "natural_key"):
@@ -299,23 +299,25 @@ def sort_dependencies():
             # Now add a dependency for any FK relation with a model that
             # Now add a dependency for any FK relation with a model that
             # defines a natural key
             # defines a natural key
             for field in model._meta.fields:
             for field in model._meta.fields:
-                if hasattr(field.remote_field, "model"):
-                    rel_model = field.remote_field.model
-                    if rel_model != model:
-                        # TODO(hybrid-cloud): actor refactor.
-                        # Add cludgy conditional preventing walking actor.team_id, actor.user_id
-                        # Which avoids circular imports
-                        if model == Actor and (rel_model == Team or rel_model == User):
-                            continue
+                rel_model = getattr(field.remote_field, "model", None)
+                if rel_model is not None and rel_model != model:
+                    # TODO(hybrid-cloud): actor refactor.
+                    # Add cludgy conditional preventing walking actor.team_id, actor.user_id
+                    # Which avoids circular imports
+                    if model == Actor and (rel_model == Team or rel_model == User):
+                        continue
 
 
-                        deps.append(rel_model)
+                    deps.append(rel_model)
 
 
             # Also add a dependency for any simple M2M relation with a model
             # Also add a dependency for any simple M2M relation with a model
             # that defines a natural key.  M2M relations with explicit through
             # that defines a natural key.  M2M relations with explicit through
             # models don't count as dependencies.
             # models don't count as dependencies.
-            for field in model._meta.many_to_many:
-                rel_model = field.remote_field.model
-                if rel_model != model:
+            many_to_many_fields = [
+                field for field in model._meta.get_fields() if isinstance(field, ManyToManyField)
+            ]
+            for field in many_to_many_fields:
+                rel_model = getattr(field.remote_field, "model", None)
+                if rel_model is not None and rel_model != model:
                     deps.append(rel_model)
                     deps.append(rel_model)
             model_dependencies.append((model, deps))
             model_dependencies.append((model, deps))