Browse Source

ref: fix typing for sentry.utils.json.dumps (#50659)

`json.dumps` has `**kwargs: NoReturn` specifically to find these typing
issues (but allow them to silently succeed at runtime)
anthony sottile 1 year ago
parent
commit
756242ba32

+ 0 - 5
pyproject.toml

@@ -496,10 +496,7 @@ module = [
     "sentry.db.deletion",
     "sentry.db.mixin",
     "sentry.db.models.base",
-    "sentry.db.models.fields.gzippeddict",
-    "sentry.db.models.fields.jsonfield",
     "sentry.db.models.fields.node",
-    "sentry.db.models.fields.picklefield",
     "sentry.db.models.manager.base",
     "sentry.db.models.paranoia",
     "sentry.db.models.query",
@@ -1040,7 +1037,6 @@ module = [
     "sentry.runner.commands.migrations",
     "sentry.runner.commands.plugins",
     "sentry.runner.commands.run",
-    "sentry.runner.commands.spans",
     "sentry.runner.commands.tsdb",
     "sentry.runner.commands.upgrade",
     "sentry.runner.importer",
@@ -1250,7 +1246,6 @@ module = [
     "sentry.utils.request_cache",
     "sentry.utils.safe",
     "sentry.utils.sdk",
-    "sentry.utils.sentry_apps.request_buffer",
     "sentry.utils.sentry_apps.webhooks",
     "sentry.utils.services",
     "sentry.utils.settings",

+ 1 - 1
src/sentry/api/endpoints/issue_occurrence.py

@@ -68,7 +68,7 @@ class IssueOccurrenceEndpoint(Endpoint):
         producer.produce(
             topic=topic,
             key=None,
-            value=json.dumps(dummy_occurrence, default=str),
+            value=json.dumps(dummy_occurrence),
         )
         producer.flush()
 

+ 1 - 1
src/sentry/charts/chartcuterie.py

@@ -75,7 +75,7 @@ class Chartcuterie(ChartRenderer):
             # Using sentry json formatter to handle datetime objects
             resp = requests.post(
                 url=urljoin(self.service_url, "render"),
-                data=json.dumps(payload, cls=json._default_encoder),
+                data=json.dumps(payload),
                 headers={"Content-Type": "application/json"},
             )
 

+ 1 - 1
src/sentry/data_export/models.py

@@ -122,7 +122,7 @@ class ExportedData(Model):
             context={
                 "creation": self.format_date(self.date_added),
                 "error_message": message,
-                "payload": json.dumps(self.payload, indent=2, sort_keys=True),
+                "payload": json.dumps(self.payload),
             },
             type="organization.export-data",
             template="sentry/emails/data-export-failure.txt",

+ 2 - 3
src/sentry/db/models/fields/gzippeddict.py

@@ -5,7 +5,6 @@ import pickle
 
 from django.db.models import TextField
 
-from sentry.db.models.fields import jsonfield
 from sentry.db.models.utils import Creator
 from sentry.utils import json
 from sentry.utils.strings import decompress
@@ -20,7 +19,7 @@ VALIDATE_JSON_SAMPLE_RATE = 1
 
 def _validate_roundtrip(o: object) -> None:
     try:
-        s = json.dumps(o, default=jsonfield.default)
+        s = json.dumps(o)
     except Exception:
         raise TypeError(
             "Tried to serialize a pickle field with a value that cannot be serialized as JSON"
@@ -76,7 +75,7 @@ class GzippedDictField(TextField):
             value = value.decode("utf-8")
         if value is None and self.null:
             return None
-        return json.dumps(value, default=jsonfield.default)
+        return json.dumps(value)
 
     def value_to_string(self, obj):
         return self.get_prep_value(self.value_from_object(obj))

+ 6 - 31
src/sentry/db/models/fields/jsonfield.py

@@ -25,38 +25,15 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 """
-import datetime
-from decimal import Decimal
-
-from django.conf import settings
 from django.core.exceptions import ValidationError
 from django.db import models
-from django.db.models.lookups import Contains, Exact, IContains, IExact, In
+from django.db.models.lookups import Contains, Exact, IContains, IExact, In, Lookup
 from django.utils.translation import ugettext_lazy as _
 
 from sentry.db.models.utils import Creator
 from sentry.utils import json
 
 
-def default(o):
-    if hasattr(o, "to_json"):
-        return o.to_json()
-    if isinstance(o, Decimal):
-        return str(o)
-    if isinstance(o, datetime.datetime):
-        if o.tzinfo:
-            return o.strftime("%Y-%m-%dT%H:%M:%S%z")
-        return o.strftime("%Y-%m-%dT%H:%M:%S")
-    if isinstance(o, datetime.date):
-        return o.strftime("%Y-%m-%d")
-    if isinstance(o, datetime.time):
-        if o.tzinfo:
-            return o.strftime("%H:%M:%S%z")
-        return o.strftime("%H:%M:%S")
-
-    raise TypeError(repr(o) + " is not JSON serializable")
-
-
 class JSONField(models.TextField):
     """
     A field that will ensure the data entered into it is valid JSON.
@@ -73,16 +50,14 @@ class JSONField(models.TextField):
     surpresses this behavior.
     """
 
-    default_error_messages = {"invalid": _("'%s' is not a valid JSON string.")}
+    # https://github.com/typeddjango/django-stubs/pull/1538
+    default_error_messages = {"invalid": _("'%s' is not a valid JSON string.")}  # type: ignore[dict-item]
     description = "JSON object"
     no_creator_hook = False
 
     def __init__(self, *args, **kwargs):
         if not kwargs.get("null", False):
             kwargs["default"] = kwargs.get("default", dict)
-        self.encoder_kwargs = {
-            "indent": kwargs.pop("indent", getattr(settings, "JSONFIELD_INDENT", None))
-        }
         super().__init__(*args, **kwargs)
         self.validate(self.get_default(), None)
 
@@ -142,13 +117,13 @@ class JSONField(models.TextField):
             if not self.null and self.blank:
                 return ""
             return None
-        return json.dumps(value, default=default, **self.encoder_kwargs)
+        return json.dumps(value)
 
     def value_to_string(self, obj):
         return self.value_from_object(obj)
 
 
-class NoPrepareMixin:
+class NoPrepareMixin(Lookup):
     def get_prep_lookup(self):
         return self.rhs
 
@@ -171,7 +146,7 @@ class JSONFieldInLookup(NoPrepareMixin, In):
         ]
 
 
-class ContainsLookupMixin:
+class ContainsLookupMixin(Lookup):
     def get_prep_lookup(self):
         if isinstance(self.rhs, (list, tuple)):
             raise TypeError(

+ 1 - 2
src/sentry/db/models/fields/picklefield.py

@@ -1,5 +1,4 @@
 import django_picklefield
-from sentry.db.models.fields import jsonfield
 from sentry.utils import json
 
 
@@ -21,7 +20,7 @@ class PickledObjectField(django_picklefield.PickledObjectField):
             value = value.decode("utf-8")
         if value is None and self.null:
             return None
-        return json.dumps(value, default=jsonfield.default)
+        return json.dumps(value)
 
     def to_python(self, value):
         if value is None:

+ 1 - 1
src/sentry/eventstore/compressor.py

@@ -60,7 +60,7 @@ def deduplicate(data):
             continue
 
         to_deduplicate, to_inline = interface.encode(data.pop(key))
-        to_deduplicate_serialized = json.dumps(to_deduplicate, sort_keys=True).encode("utf8")
+        to_deduplicate_serialized = json.dumps(to_deduplicate).encode()
         checksum = hashlib.md5(to_deduplicate_serialized).hexdigest()
         extra_keys[checksum] = to_deduplicate
         patchsets.append([key, checksum, to_inline])

+ 1 - 1
src/sentry/interfaces/security.py

@@ -173,7 +173,7 @@ class Csp(SecurityReport):
         return super().to_python(data, **kwargs)
 
     def to_string(self, is_public=False, **kwargs):
-        return json.dumps({"csp-report": self.get_api_context()}, indent=2)
+        return json.dumps({"csp-report": self.get_api_context()})
 
     def to_email_html(self, event, **kwargs):
         return render_to_string(

+ 1 - 1
src/sentry/runner/commands/spans.py

@@ -42,7 +42,7 @@ def write_hashes(filename):
 
     with open(new_filename, "w") as out_file:
         results.write_to_event(data)
-        out_file.write(json.dumps(data, indent=4))
+        out_file.write(json.dumps(data))
 
     click.echo("Done")
     click.echo("\n")

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