From 456420ec714b04825df90cede4759954e3e3ea9a Mon Sep 17 00:00:00 2001 From: Leslie Michael Orchard Date: Tue, 24 May 2011 17:00:10 -0400 Subject: [PATCH] Update kuma-lib commit used for submodule; enable South migrations for the demos app; update_site.py tweaks to sync submodule URLs before update, run South migrations --- apps/demos/migrations/0001_initial.py | 120 ++++++++++++++++++ apps/demos/migrations/__init__.py | 0 apps/demos/models.py | 39 +++++- lib/embedutils.py | 7 + .../03-demos-using-south-migrations.sql | 14 ++ requirements/prod.txt | 1 + scripts/update_site.py | 13 +- settings.py | 6 + vendor | 2 +- 9 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 apps/demos/migrations/0001_initial.py create mode 100644 apps/demos/migrations/__init__.py create mode 100644 migrations/03-demos-using-south-migrations.sql diff --git a/apps/demos/migrations/0001_initial.py b/apps/demos/migrations/0001_initial.py new file mode 100644 index 00000000000..e2d256eebab --- /dev/null +++ b/apps/demos/migrations/0001_initial.py @@ -0,0 +1,120 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding model 'Submission' + db.create_table('demos_submission', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), + ('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50, db_index=True)), + ('summary', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('description', self.gf('django.db.models.fields.TextField')(blank=True)), + ('featured', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('hidden', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('censored', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('navbar_optout', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('comments_total', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('tags', self.gf('demos.models.ConstrainedTagField')()), + ('screenshot_1', self.gf('demos.models.ReplacingImageWithThumbField')(max_length=255)), + ('screenshot_2', self.gf('demos.models.ReplacingImageWithThumbField')(max_length=255, blank=True)), + ('screenshot_3', self.gf('demos.models.ReplacingImageWithThumbField')(max_length=255, blank=True)), + ('screenshot_4', self.gf('demos.models.ReplacingImageWithThumbField')(max_length=255, blank=True)), + ('screenshot_5', self.gf('demos.models.ReplacingImageWithThumbField')(max_length=255, blank=True)), + ('video_url', self.gf('embedutils.VideoEmbedURLField')(max_length=200, null=True, blank=True)), + ('demo_package', self.gf('demos.models.ReplacingZipFileField')(max_upload_size=62914560, max_length=255)), + ('source_code_url', self.gf('django.db.models.fields.URLField')(max_length=200, null=True, blank=True)), + ('license_name', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('creator', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + ('likes_total', self.gf('django.db.models.fields.IntegerField')(default=0, db_index=True, blank=True)), + ('likes_recent', self.gf('django.db.models.fields.IntegerField')(default=0, db_index=True, blank=True)), + ('launches_total', self.gf('django.db.models.fields.IntegerField')(default=0, db_index=True, blank=True)), + ('launches_recent', self.gf('django.db.models.fields.IntegerField')(default=0, db_index=True, blank=True)), + )) + db.send_create_signal('demos', ['Submission']) + + + def backwards(self, orm): + + # Deleting model 'Submission' + db.delete_table('demos_submission') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + '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'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'demos.submission': { + 'Meta': {'object_name': 'Submission'}, + 'censored': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'comments_total': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'demo_package': ('demos.models.ReplacingZipFileField', [], {'max_upload_size': '62914560', 'max_length': '255'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'featured': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'launches_recent': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True', 'blank': 'True'}), + 'launches_total': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True', 'blank': 'True'}), + 'license_name': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'likes_recent': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True', 'blank': 'True'}), + 'likes_total': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'navbar_optout': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'screenshot_1': ('demos.models.ReplacingImageWithThumbField', [], {'max_length': '255'}), + 'screenshot_2': ('demos.models.ReplacingImageWithThumbField', [], {'max_length': '255', 'blank': 'True'}), + 'screenshot_3': ('demos.models.ReplacingImageWithThumbField', [], {'max_length': '255', 'blank': 'True'}), + 'screenshot_4': ('demos.models.ReplacingImageWithThumbField', [], {'max_length': '255', 'blank': 'True'}), + 'screenshot_5': ('demos.models.ReplacingImageWithThumbField', [], {'max_length': '255', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}), + 'source_code_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'tags': ('demos.models.ConstrainedTagField', [], {}), + 'taggit_tags': ('taggit.managers.TaggableManager', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'video_url': ('embedutils.VideoEmbedURLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['demos'] diff --git a/apps/demos/migrations/__init__.py b/apps/demos/migrations/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/apps/demos/models.py b/apps/demos/models.py index 8b1961678c7..d108f1026cf 100644 --- a/apps/demos/models.py +++ b/apps/demos/models.py @@ -34,6 +34,8 @@ from django.contrib.sites.models import Site from django.contrib.auth.models import User +import south.modelsinspector + import tagging import tagging.fields import tagging.models @@ -158,6 +160,16 @@ def formfield(self, **kwargs): defaults.update(kwargs) return super(ConstrainedTagField, self).formfield(**defaults) +south.modelsinspector.add_introspection_rules([ + ( + [ ConstrainedTagField ], + [ ], + { + 'max_tags': ['max_tags', {'default':5}], + }, + ) +], ["^demos.models.ConstrainedTagField"]) + def get_root_for_submission(instance): """Build a root path for demo submission files""" @@ -246,6 +258,16 @@ def clean(self, *args, **kwargs): return data +south.modelsinspector.add_introspection_rules([ + ( + [ ReplacingZipFileField ], + [ ], + { + 'max_upload_size': ['max_upload_size', {'default':5}], + }, + ) +], ["^demos.models.ReplacingZipFileField"]) + class ReplacingImageWithThumbFieldFile(ImageFieldFile): @@ -290,9 +312,9 @@ class ReplacingImageWithThumbField(models.ImageField): def __init__(self, *args, **kwargs): self.full_max_width = kwargs.pop("full_max_width", SCREENSHOT_MAXW) - self.full_max_height = kwargs.pop("full_max_width", SCREENSHOT_MAXH) + self.full_max_height = kwargs.pop("full_max_height", SCREENSHOT_MAXH) self.thumb_max_width = kwargs.pop("thumb_max_width", THUMBNAIL_MAXW) - self.thumb_max_height = kwargs.pop("thumb_max_width", THUMBNAIL_MAXH) + self.thumb_max_height = kwargs.pop("thumb_max_height", THUMBNAIL_MAXH) super(ReplacingImageWithThumbField, self).__init__(*args, **kwargs) def clean(self, *args, **kwargs): @@ -307,6 +329,19 @@ def clean(self, *args, **kwargs): return data +south.modelsinspector.add_introspection_rules([ + ( + [ ReplacingImageWithThumbField ], + [ ], + { + 'full_max_width': ['full_max_width', {'default':SCREENSHOT_MAXW}], + 'full_max_width': ['full_max_height', {'default':SCREENSHOT_MAXH}], + 'full_max_width': ['full_max_width', {'default':THUMBNAIL_MAXW}], + 'full_max_width': ['thumb_max_height', {'default':THUMBNAIL_MAXH}], + }, + ) +], ["^demos.models.ReplacingImageWithThumbField"]) + class SubmissionManager(models.Manager): """Manager for Submission objects""" diff --git a/lib/embedutils.py b/lib/embedutils.py index da593ab5909..cd80881270a 100644 --- a/lib/embedutils.py +++ b/lib/embedutils.py @@ -133,3 +133,10 @@ def get_prep_value(self, field_value): def contribute_to_class(self, cls, name): super(VideoEmbedURLField, self).contribute_to_class(cls, name) setattr(cls, self.name, self.descriptor_class(self)) + +try: + import south.modelsinspector + south.modelsinspector.add_introspection_rules([ ], ["^embedutils.VideoEmbedURLField"]) +except ImportError: + pass + diff --git a/migrations/03-demos-using-south-migrations.sql b/migrations/03-demos-using-south-migrations.sql new file mode 100644 index 00000000000..02e89f79b92 --- /dev/null +++ b/migrations/03-demos-using-south-migrations.sql @@ -0,0 +1,14 @@ +-- +-- Initial SQL migration to enable South migrations for demos app +-- + +DROP TABLE IF EXISTS `south_migrationhistory`; +CREATE TABLE `south_migrationhistory` ( + `id` int(11) NOT NULL auto_increment, + `app_name` varchar(255) NOT NULL, + `migration` varchar(255) NOT NULL, + `applied` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; + +INSERT INTO `south_migrationhistory` VALUES (1,'demos','0001_initial','2011-05-23 19:32:05'); diff --git a/requirements/prod.txt b/requirements/prod.txt index d38e133324b..2ca1fef15b5 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -8,6 +8,7 @@ celery==2.1.4 python-dateutil==1.5 django-taggit==0.8.0 pytz +South==0.7.3 # Feeds and cron jobs feedparser==4.1 diff --git a/scripts/update_site.py b/scripts/update_site.py index 1c8e817fcf1..0c18b4d3a90 100755 --- a/scripts/update_site.py +++ b/scripts/update_site.py @@ -7,7 +7,7 @@ Options: -h, --help show this help message and exit -e ENVIRONMENT, --environment=ENVIRONMENT - Type of environment. One of (prod|dev|stage|mdn_stage|mdn_prod) Example: + Type of environment. One of (dev|stage|prod|mdn_dev|mdn_stage|mdn_prod) Example: update_site.py -e stage -v, --verbose Echo actions before taking them. """ @@ -26,12 +26,14 @@ 'dev': ['base', 'master'], 'stage': ['master', 'master'], 'prod': ['prod', 'master'], + 'mdn_dev': ['mdn', 'master'], 'mdn_stage': ['mdn', 'master'], 'mdn_prod': ['mdn_prod', 'master'] } GIT_PULL = "git pull -q origin %(branch)s" -GIT_SUBMODULE = "git submodule update --init" +GIT_SUBMODULE_SYNC = "git submodule sync" +GIT_SUBMODULE_UPDATE = "git submodule update --init --recursive" SVN_UP = "svn update" COMPILE_PO = "./compile-mo.sh ." @@ -49,7 +51,8 @@ def update_site(env, debug): commands = [ (CHDIR, here), (EXEC, GIT_PULL % project_branch), - (EXEC, GIT_SUBMODULE), + (EXEC, GIT_SUBMODULE_SYNC), + (EXEC, GIT_SUBMODULE_UPDATE), ] # Update locale dir if applicable @@ -70,9 +73,11 @@ def update_site(env, debug): commands += [ (CHDIR, os.path.join(here, 'vendor')), (EXEC, GIT_PULL % vendor_branch), - (EXEC, GIT_SUBMODULE), + (EXEC, GIT_SUBMODULE_SYNC), + (EXEC, GIT_SUBMODULE_UPDATE), (CHDIR, os.path.join(here)), (EXEC, 'python2.6 vendor/src/schematic/schematic migrations/'), + (EXEC, 'python2.6 manage.py migrate'), (EXEC, 'python2.6 manage.py compress_assets'), ] diff --git a/settings.py b/settings.py index 97f31e74ab6..9ffbe7d0b58 100644 --- a/settings.py +++ b/settings.py @@ -289,6 +289,9 @@ def __new__(self): # testing. 'django_nose', 'test_utils', + + # migrations + 'south', ) TEST_RUNNER = 'test_utils.runner.RadicalTestSuiteRunner' @@ -695,3 +698,6 @@ def read_only_mode(env): DEMO_UPLOADS_ROOT = path('media/uploads/demos') # Base URL from where files uploaded for demos will be linked and served DEMO_UPLOADS_URL = '/media/uploads/demos/' + +SOUTH_TESTS_MIGRATE = False +SKIP_SOUTH_TESTS = True diff --git a/vendor b/vendor index 955a916da5f..dc1f1017b89 160000 --- a/vendor +++ b/vendor @@ -1 +1 @@ -Subproject commit 955a916da5fc607933b9b9085ea52ab8109781ca +Subproject commit dc1f1017b8926c0d6d62805cc57f8ed9cd087580