Browse Source

ref(py3): Add crc32 compat (#20675)

Evan Purkhiser 4 years ago
parent
commit
08f111f856
3 changed files with 24 additions and 5 deletions
  1. 1 2
      src/sentry/buffer/redis.py
  2. 1 3
      src/sentry/tsdb/redis.py
  3. 22 0
      src/sentry/utils/compat/__init__.py

+ 1 - 2
src/sentry/buffer/redis.py

@@ -4,7 +4,6 @@ import six
 
 import threading
 from time import time
-from binascii import crc32
 
 from datetime import datetime
 from django.db import models
@@ -15,7 +14,7 @@ from sentry.buffer import Buffer
 from sentry.exceptions import InvalidConfiguration
 from sentry.tasks.process_buffer import process_incr, process_pending
 from sentry.utils import json, metrics
-from sentry.utils.compat import pickle
+from sentry.utils.compat import pickle, crc32
 from sentry.utils.hashlib import md5_text
 from sentry.utils.imports import import_string
 from sentry.utils.redis import get_cluster_from_options

+ 1 - 3
src/sentry/tsdb/redis.py

@@ -5,7 +5,6 @@ import logging
 import operator
 import random
 import uuid
-from binascii import crc32
 from collections import defaultdict, namedtuple
 from hashlib import md5
 
@@ -19,8 +18,7 @@ from sentry.utils.dates import to_datetime, to_timestamp
 from sentry.utils.redis import check_cluster_versions, get_cluster_from_options, SentryScript
 from sentry.utils.versioning import Version
 from six.moves import reduce
-from sentry.utils.compat import map
-from sentry.utils.compat import zip
+from sentry.utils.compat import map, zip, crc32
 
 logger = logging.getLogger(__name__)
 

+ 22 - 0
src/sentry/utils/compat/__init__.py

@@ -51,8 +51,30 @@ if six.PY2:
         del cls.__bool__
         return cls
 
+    from binascii import crc32
 
 else:
     implements_to_string = _identity
     implements_iterator = _identity
     implements_bool = _identity
+
+    from binascii import crc32 as _crc32
+
+    # In python3 crc32 was changed to never return a signed value, which is
+    # different from the python2 implementation. As noted in
+    # https://docs.python.org/3/library/binascii.html#binascii.crc32
+    #
+    # Note the documentation suggests the following:
+    #
+    # > Changed in version 3.0: The result is always unsigned. To generate the
+    # > same numeric value across all Python versions and platforms, use
+    # > crc32(data) & 0xffffffff.
+    #
+    # However this will not work when transitioning between versions, as the
+    # value MUST match what was generated in python 2.
+    #
+    # We can sign the return value using the following bit math to ensure we
+    # match the python2 output of crc32.
+    def crc32(*args):
+        rt = _crc32(*args)
+        return rt - ((rt & 0x80000000) << 1)