Browse Source

Merge branch 'master' into redesign/react

Conflicts:
	src/sentry/templates/sentry/groups/details.html
David Cramer 10 years ago
parent
commit
d9e1099f1e

+ 3 - 2
.travis.yml

@@ -1,3 +1,4 @@
+sudo: false
 language: python
 services:
   - elasticsearch
@@ -8,7 +9,6 @@ services:
   - redis-server
   - cassandra
 python:
-  - "2.6"
   - "2.7"
 env:
   matrix:
@@ -28,7 +28,8 @@ env:
 
 before_install:
   # Use closer nameservers
-  - printf "nameserver 199.91.168.70\nnameserver 199.91.168.71\n" | sudo tee /etc/resolv.conf
+  # XXX: not supported on containers
+  # - printf "nameserver 199.91.168.70\nnameserver 199.91.168.71\n" | sudo tee /etc/resolv.conf
 
   # These need to be here and not in the env hash because they need to be
   # evaluated after the virtualenv has been setup

+ 6 - 0
CHANGES

@@ -40,6 +40,12 @@ Protocol Version 6
 Version 6 of the protocol has been introduced. The only change is the addition of the `release` attribute.
 
 
+BIGINT
+======
+
+All integer fields have been replaced with bigint's. This migration is *not* automated (due to it causing locking) and if you need it locally you will need to sort out the migration on your own, as well as set `SENTRY_USE_BIG_INTS = True` in your configuration.
+
+
 Version 6.4.0
 -------------
 

+ 1 - 0
setup.py

@@ -21,6 +21,7 @@ any application.
 :copyright: (c) 2011-2014 by the Sentry Team, see AUTHORS for more details.
 :license: BSD, see LICENSE for more details.
 """
+from __future__ import absolute_import
 
 import os.path
 

+ 6 - 0
src/sentry/conf/server.py

@@ -189,6 +189,8 @@ LOCALE_PATHS = (
     os.path.join(PROJECT_ROOT, 'locale'),
 )
 
+CSRF_FAILURE_VIEW = 'sentry.web.frontend.csrf_failure.view'
+
 # Auth configuration
 
 try:
@@ -631,6 +633,10 @@ SENTRY_MANAGED_USER_FIELDS = ('email',)
 # See sentry/options/__init__.py for more information
 SENTRY_OPTIONS = {}
 
+# You should not change this setting after your database has been created
+# unless you have altered all schemas first
+SENTRY_USE_BIG_INTS = False
+
 # Configure celery
 import djcelery
 djcelery.setup_loader()

+ 5 - 2
src/sentry/conf/urls.py

@@ -20,6 +20,7 @@ from django.contrib import admin
 from django.views.defaults import page_not_found
 
 from sentry.web.urls import urlpatterns as web_urlpatterns
+from sentry.web.frontend.csrf_failure import CsrfFailureView
 
 
 admin.autodiscover()
@@ -43,8 +44,10 @@ def handler500(request):
     t = loader.get_template('sentry/500.html')
     return HttpResponseServerError(t.render(Context(context)))
 
+
 urlpatterns = patterns('',
     url(r'^admin/', include(admin.site.urls)),
-    url(r'^500/', handler500),
-    url(r'^404/', handler404),
+    url(r'^500/', handler500, name='error-500'),
+    url(r'^404/', handler404, name='error-400'),
+    url(r'^403-csrf-failure/', CsrfFailureView.as_view(), name='error-403-csrf-failure'),
 ) + web_urlpatterns

+ 1 - 0
src/sentry/db/models/fields/__init__.py

@@ -9,6 +9,7 @@ sentry.db.models.fields
 from __future__ import absolute_import
 
 from .bounded import *  # NOQA
+from .foreignkey import *  # NOQA
 from .gzippeddict import *  # NOQA
 from .node import *  # NOQA
 from .pickle import *  # NOQA

+ 67 - 73
src/sentry/db/models/fields/bounded.py

@@ -7,8 +7,11 @@ sentry.db.models.fields.bounded
 """
 
 from __future__ import absolute_import
-from django.db import models
 
+from django.conf import settings
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+from south.modelsinspector import add_introspection_rules
 
 __all__ = (
     'BoundedAutoField', 'BoundedBigAutoField', 'BoundedIntegerField',
@@ -16,103 +19,94 @@ __all__ = (
 )
 
 
-class BoundedAutoField(models.AutoField):
+class BoundedIntegerField(models.IntegerField):
     MAX_VALUE = 2147483647
 
     def get_prep_value(self, value):
         if value:
             value = int(value)
             assert value <= self.MAX_VALUE
-        return super(BoundedAutoField, self).get_prep_value(value)
+        return super(BoundedIntegerField, self).get_prep_value(value)
 
-    def south_field_triple(self):
-        "Returns a suitable description of this field for South."
-        from south.modelsinspector import introspector
-        field_class = "django.db.models.fields.AutoField"
-        args, kwargs = introspector(self)
-        return (field_class, args, kwargs)
-
-
-class BoundedBigAutoField(models.AutoField):
-    MAX_VALUE = 9223372036854775807
-
-    def db_type(self, connection):
-        engine = connection.settings_dict['ENGINE']
-        if 'mysql' in engine:
-            return "bigint AUTO_INCREMENT"
-        elif 'oracle' in engine:
-            return "NUMBER(19)"
-        elif 'postgres' in engine:
-            return "bigserial"
-        # SQLite doesnt actually support bigints with auto incr
-        elif 'sqlite' in engine:
-            return 'integer'
-        else:
-            raise NotImplemented
-
-    def get_internal_type(self):
-        return "BoundedBigAutoField"
+
+class BoundedPositiveIntegerField(models.PositiveIntegerField):
+    MAX_VALUE = 2147483647
 
     def get_prep_value(self, value):
         if value:
-            value = long(value)
+            value = int(value)
             assert value <= self.MAX_VALUE
-        return super(BoundedBigAutoField, self).get_prep_value(value)
-
-    def south_field_triple(self):
-        "Returns a suitable description of this field for South."
-        from south.modelsinspector import introspector
-        field_class = "sentry.db.models.fields.BoundedBigAutoField"
-        args, kwargs = introspector(self)
-        return (field_class, args, kwargs)
+        return super(BoundedPositiveIntegerField, self).get_prep_value(value)
 
 
-class BoundedIntegerField(models.IntegerField):
+class BoundedAutoField(models.AutoField):
     MAX_VALUE = 2147483647
 
     def get_prep_value(self, value):
         if value:
             value = int(value)
             assert value <= self.MAX_VALUE
-        return super(BoundedIntegerField, self).get_prep_value(value)
+        return super(BoundedAutoField, self).get_prep_value(value)
 
-    def south_field_triple(self):
-        "Returns a suitable description of this field for South."
-        from south.modelsinspector import introspector
-        field_class = "django.db.models.fields.IntegerField"
-        args, kwargs = introspector(self)
-        return (field_class, args, kwargs)
 
+if settings.SENTRY_USE_BIG_INTS:
+    class BoundedBigIntegerField(models.BigIntegerField):
+        description = _("Big Integer")
 
-class BoundedBigIntegerField(models.BigIntegerField):
-    MAX_VALUE = 9223372036854775807
+        MAX_VALUE = 9223372036854775807
 
-    def get_prep_value(self, value):
-        if value:
-            value = long(value)
-            assert value <= self.MAX_VALUE
-        return super(BoundedBigIntegerField, self).get_prep_value(value)
+        def get_internal_type(self):
+            return "BigIntegerField"
 
-    def south_field_triple(self):
-        "Returns a suitable description of this field for South."
-        from south.modelsinspector import introspector
-        field_class = "django.db.models.fields.BigIntegerField"
-        args, kwargs = introspector(self)
-        return (field_class, args, kwargs)
+        def get_prep_value(self, value):
+            if value:
+                value = long(value)
+                assert value <= self.MAX_VALUE
+            return super(BoundedBigIntegerField, self).get_prep_value(value)
 
+    class BoundedBigAutoField(models.AutoField):
+        description = _("Big Integer")
 
-class BoundedPositiveIntegerField(models.PositiveIntegerField):
-    MAX_VALUE = 2147483647
+        MAX_VALUE = 9223372036854775807
+
+        def db_type(self, connection):
+            engine = connection.settings_dict['ENGINE']
+            if 'mysql' in engine:
+                return "bigint AUTO_INCREMENT"
+            elif 'oracle' in engine:
+                return "NUMBER(19)"
+            elif 'postgres' in engine:
+                return "bigserial"
+            # SQLite doesnt actually support bigints with auto incr
+            elif 'sqlite' in engine:
+                return 'integer'
+            else:
+                raise NotImplemented
+
+        def get_related_db_type(self, connection):
+            return BoundedBigIntegerField().db_type(connection)
+
+        def get_internal_type(self):
+            return "BigIntegerField"
+
+        def get_prep_value(self, value):
+            if value:
+                value = long(value)
+                assert value <= self.MAX_VALUE
+            return super(BoundedBigAutoField, self).get_prep_value(value)
+
+else:
+    # we want full on classes for these
+    class BoundedBigIntegerField(BoundedIntegerField):
+        pass
+
+    class BoundedBigAutoField(BoundedAutoField):
+        pass
 
-    def get_prep_value(self, value):
-        if value:
-            value = int(value)
-            assert value <= self.MAX_VALUE
-        return super(BoundedPositiveIntegerField, self).get_prep_value(value)
 
-    def south_field_triple(self):
-        "Returns a suitable description of this field for South."
-        from south.modelsinspector import introspector
-        field_class = "django.db.models.fields.PositiveIntegerField"
-        args, kwargs = introspector(self)
-        return (field_class, args, kwargs)
+add_introspection_rules([], ["^sentry\.db\.models\.fields\.bounded\.BoundedAutoField"])
+add_introspection_rules([], ["^sentry\.db\.models\.fields\.bounded\.BoundedBigAutoField"])
+add_introspection_rules([], ["^sentry\.db\.models\.fields\.bounded\.BoundedIntegerField"])
+add_introspection_rules([], ["^sentry\.db\.models\.fields\.bounded\.BoundedBigIntegerField"])
+add_introspection_rules([], ["^sentry\.db\.models\.fields\.bounded\.BoundedPositiveIntegerField"])
+add_introspection_rules([], ["^sentry\.db\.models\.fields\.pickle\.UnicodePickledObjectField"])

+ 29 - 0
src/sentry/db/models/fields/foreignkey.py

@@ -0,0 +1,29 @@
+"""
+sentry.db.models.fields.foreignkey
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
+:license: BSD, see LICENSE for more details.
+"""
+
+from __future__ import absolute_import
+
+from django.db.models import ForeignKey
+from south.modelsinspector import add_introspection_rules
+
+__all__ = ('FlexibleForeignKey',)
+
+
+class FlexibleForeignKey(ForeignKey):
+    def db_type(self, connection):
+        # This is required to support BigAutoField (or anything similar)
+        rel_field = self.related_field
+        if hasattr(rel_field, 'get_related_db_type'):
+            return rel_field.get_related_db_type(connection)
+        return super(FlexibleForeignKey, self).db_type(connection)
+
+
+add_introspection_rules([], [
+    "^sentry\.db\.models\.fields\.FlexibleForeignKey",
+    "^sentry\.db\.models\.fields\.foreignkey\.FlexibleForeignKey",
+])

+ 6 - 6
src/sentry/migrations/0001_initial.py

@@ -10,7 +10,7 @@ class Migration(SchemaMigration):
 
         # Adding model 'GroupedMessage'
         db.create_table('sentry_groupedmessage', (
-            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('id', self.gf('sentry.db.models.fields.bounded.BoundedBigAutoField')(primary_key=True)),
             ('logger', self.gf('django.db.models.fields.CharField')(default='root', max_length=64, db_index=True, blank=True)),
             ('class_name', self.gf('django.db.models.fields.CharField')(db_index=True, max_length=128, null=True, blank=True)),
             ('level', self.gf('django.db.models.fields.PositiveIntegerField')(default=40, db_index=True, blank=True)),
@@ -32,7 +32,7 @@ class Migration(SchemaMigration):
 
         # Adding model 'Message'
         db.create_table('sentry_message', (
-            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('id', self.gf('sentry.db.models.fields.bounded.BoundedBigAutoField')(primary_key=True)),
             ('logger', self.gf('django.db.models.fields.CharField')(default='root', max_length=64, db_index=True, blank=True)),
             ('class_name', self.gf('django.db.models.fields.CharField')(db_index=True, max_length=128, null=True, blank=True)),
             ('level', self.gf('django.db.models.fields.PositiveIntegerField')(default=40, db_index=True, blank=True)),
@@ -87,7 +87,7 @@ class Migration(SchemaMigration):
         u'auth.permission': {
             'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
             'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
-            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
+            'content_type': ('sentry.db.models.fields.FlexibleForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
             'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
         },
@@ -96,7 +96,7 @@ class Migration(SchemaMigration):
             'checksum': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
             'class_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}),
             'first_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'id': ('sentry.db.models.fields.bounded.BoundedBigAutoField', [], {'primary_key': 'True'}),
             'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
             'level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '40', 'db_index': 'True', 'blank': 'True'}),
             'logger': ('django.db.models.fields.CharField', [], {'default': "'root'", 'max_length': '64', 'db_index': 'True', 'blank': 'True'}),
@@ -114,7 +114,7 @@ class Migration(SchemaMigration):
             'class_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}),
             'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
             'datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'id': ('sentry.db.models.fields.bounded.BoundedBigAutoField', [], {'primary_key': 'True'}),
             'level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '40', 'db_index': 'True', 'blank': 'True'}),
             'logger': ('django.db.models.fields.CharField', [], {'default': "'root'", 'max_length': '64', 'db_index': 'True', 'blank': 'True'}),
             'message': ('django.db.models.fields.TextField', [], {}),
@@ -140,7 +140,7 @@ class Migration(SchemaMigration):
         u'contenttypes.contenttype': {
             'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
             'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            u'id': ('sentry.db.models.fields.bounded.BoundedBigAutoField', [], {'primary_key': 'True'}),
             'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         },

+ 4 - 4
src/sentry/migrations/0002_auto__del_field_groupedmessage_url__chg_field_groupedmessage_view__chg.py

@@ -7,7 +7,7 @@ from django.db import models
 class Migration(SchemaMigration):
 
     def forwards(self, orm):
-        
+
         # Deleting field 'GroupedMessage.url'
         db.delete_column('sentry_groupedmessage', 'url')
 
@@ -19,7 +19,7 @@ class Migration(SchemaMigration):
 
 
     def backwards(self, orm):
-        
+
         # Adding field 'GroupedMessage.url'
         db.add_column('sentry_groupedmessage', 'url', self.gf('django.db.models.fields.URLField')(max_length=200, null=True, blank=True), keep_default=False)
 
@@ -36,7 +36,7 @@ class Migration(SchemaMigration):
             'checksum': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
             'class_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}),
             'first_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'id': ('sentry.db.models.fields.bounded.BoundedBigAutoField', [], {'primary_key': 'True'}),
             'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
             'level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '40', 'db_index': 'True', 'blank': 'True'}),
             'logger': ('django.db.models.fields.CharField', [], {'default': "'root'", 'max_length': '64', 'db_index': 'True', 'blank': 'True'}),
@@ -53,7 +53,7 @@ class Migration(SchemaMigration):
             'class_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}),
             'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
             'datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'id': ('sentry.db.models.fields.bounded.BoundedBigAutoField', [], {'primary_key': 'True'}),
             'level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '40', 'db_index': 'True', 'blank': 'True'}),
             'logger': ('django.db.models.fields.CharField', [], {'default': "'root'", 'max_length': '64', 'db_index': 'True', 'blank': 'True'}),
             'message': ('django.db.models.fields.TextField', [], {}),

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