From f2b3e72ea8d864a4b1934b330fcb1a5c41ba02e6 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Thu, 18 Dec 2014 16:05:15 +0000 Subject: [PATCH] Downgraded tastypie from 0.12.1 to 0.11.1 for compatibility with Django 1.6 and south. - Legacy-Id: 8753 --- tastypie/__init__.py | 2 +- tastypie/api.py | 1 + tastypie/authentication.py | 12 +- tastypie/compat.py | 29 ++-- tastypie/contrib/gis/resources.py | 5 +- tastypie/fields.py | 17 +-- .../management/commands/backfill_api_keys.py | 3 +- tastypie/migrations/0001_initial.py | 129 +++++++++++++----- .../0002_add_apikey_index.py | 0 tastypie/models.py | 7 +- tastypie/resources.py | 11 +- tastypie/serializers.py | 2 +- tastypie/south_migrations/0001_initial.py | 97 ------------- tastypie/south_migrations/__init__.py | 0 14 files changed, 128 insertions(+), 187 deletions(-) rename tastypie/{south_migrations => migrations}/0002_add_apikey_index.py (100%) delete mode 100644 tastypie/south_migrations/0001_initial.py delete mode 100644 tastypie/south_migrations/__init__.py diff --git a/tastypie/__init__.py b/tastypie/__init__.py index 370ca7714..758b5c7c7 100644 --- a/tastypie/__init__.py +++ b/tastypie/__init__.py @@ -2,4 +2,4 @@ from __future__ import unicode_literals __author__ = 'Daniel Lindsley & the Tastypie core team' -__version__ = (0, 12, 1) +__version__ = (0, 11, 1) diff --git a/tastypie/api.py b/tastypie/api.py index 1535af792..d8788afb9 100644 --- a/tastypie/api.py +++ b/tastypie/api.py @@ -9,6 +9,7 @@ from tastypie.serializers import Serializer from tastypie.utils import trailing_slash, is_valid_jsonp_callback_value from tastypie.utils.mime import determine_format, build_content_type + class Api(object): """ Implements a registry to tie together the various resources that make up diff --git a/tastypie/authentication.py b/tastypie/authentication.py index cd529d2e9..7f3281d6a 100644 --- a/tastypie/authentication.py +++ b/tastypie/authentication.py @@ -11,7 +11,7 @@ from django.middleware.csrf import _sanitize_token, constant_time_compare from django.utils.http import same_origin from django.utils.translation import ugettext as _ from tastypie.http import HttpUnauthorized -from tastypie.compat import get_user_model, get_username_field +from tastypie.compat import User, username_field try: from hashlib import sha1 @@ -180,6 +180,7 @@ class ApiKeyAuthentication(Authentication): Should return either ``True`` if allowed, ``False`` if not or an ``HttpResponse`` if you need something custom. """ + from tastypie.compat import User try: username, api_key = self.extract_credentials(request) @@ -189,9 +190,6 @@ class ApiKeyAuthentication(Authentication): if not username or not api_key: return self._unauthorized() - username_field = get_username_field() - User = get_user_model() - try: lookup_kwargs = {username_field: username} user = User.objects.get(**lookup_kwargs) @@ -282,8 +280,7 @@ class SessionAuthentication(Authentication): This implementation returns the user's username. """ - - return getattr(request.user, get_username_field()) + return getattr(request.user, username_field) class DigestAuthentication(Authentication): @@ -369,9 +366,6 @@ class DigestAuthentication(Authentication): return True def get_user(self, username): - username_field = get_username_field() - User = get_user_model() - try: lookup_kwargs = {username_field: username} user = User.objects.get(**lookup_kwargs) diff --git a/tastypie/compat.py b/tastypie/compat.py index 4191bc545..aa7961031 100644 --- a/tastypie/compat.py +++ b/tastypie/compat.py @@ -1,25 +1,24 @@ from __future__ import unicode_literals from django.conf import settings +from django.core.exceptions import ImproperlyConfigured import django -__all__ = ['get_user_model', 'get_username_field', 'AUTH_USER_MODEL'] +__all__ = ['User', 'AUTH_USER_MODEL'] AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') # Django 1.5+ compatibility if django.VERSION >= (1, 5): - def get_user_model(): - from django.contrib.auth import get_user_model as django_get_user_model - - return django_get_user_model() - - def get_username_field(): - return get_user_model().USERNAME_FIELD + try: + from django.contrib.auth import get_user_model + User = get_user_model() + username_field = User.USERNAME_FIELD + except ImproperlyConfigured: + # The the users model might not be read yet. + # This can happen is when setting up the create_api_key signal, in your + # custom user module. + User = None + username_field = None else: - def get_user_model(): - from django.contrib.auth.models import User - - return User - - def get_username_field(): - return 'username' + from django.contrib.auth.models import User + username_field = 'username' diff --git a/tastypie/contrib/gis/resources.py b/tastypie/contrib/gis/resources.py index da96969e7..be1509677 100644 --- a/tastypie/contrib/gis/resources.py +++ b/tastypie/contrib/gis/resources.py @@ -1,9 +1,6 @@ # See COPYING file in this directory. # Some code originally from django-boundaryservice from __future__ import unicode_literals - -import json - try: from urllib.parse import unquote except ImportError: @@ -12,6 +9,8 @@ except ImportError: from django.contrib.gis.db.models import GeometryField from django.contrib.gis.geos import GEOSGeometry +import json + from tastypie.fields import ApiField, CharField from tastypie import resources diff --git a/tastypie/fields.py b/tastypie/fields.py index e282c76fd..bdbb36a11 100644 --- a/tastypie/fields.py +++ b/tastypie/fields.py @@ -10,7 +10,6 @@ from tastypie.bundle import Bundle from tastypie.exceptions import ApiFieldError, NotFound from tastypie.utils import dict_strip_unicode_keys, make_aware -import debug class NOT_PROVIDED: def __str__(self): @@ -231,6 +230,7 @@ class IntegerField(ApiField): def convert(self, value): if value is None: return None + return int(value) @@ -543,7 +543,6 @@ class RelatedField(ApiField): # to rely on). Try to throw a useful error. raise ImportError("Tastypie requires a Python-style path () to lazy load related resources. Only given '%s'." % self.to) - import debug self._to_class = getattr(module, class_name, None) if self._to_class is None: @@ -708,7 +707,6 @@ class ToOneField(RelatedField): def dehydrate(self, bundle, for_list=True): foreign_obj = None - error_to_raise = None if isinstance(self.attribute, six.string_types): attrs = self.attribute.split('__') @@ -720,19 +718,14 @@ class ToOneField(RelatedField): foreign_obj = getattr(foreign_obj, attr, None) except ObjectDoesNotExist: foreign_obj = None - elif callable(self.attribute): - previous_obj = bundle.obj foreign_obj = self.attribute(bundle) - + if not foreign_obj: if not self.null: - if callable(self.attribute): - raise ApiFieldError("The related resource for resource %s could not be found." % (previous_obj)) - else: - raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, self.instance_name)) - - return None + raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr)) + + return None self.fk_resource = self.get_related_resource(foreign_obj) fk_bundle = Bundle(obj=foreign_obj, request=bundle.request) diff --git a/tastypie/management/commands/backfill_api_keys.py b/tastypie/management/commands/backfill_api_keys.py index 633c4a410..fe60c0caa 100644 --- a/tastypie/management/commands/backfill_api_keys.py +++ b/tastypie/management/commands/backfill_api_keys.py @@ -1,7 +1,7 @@ from __future__ import print_function from __future__ import unicode_literals from django.core.management.base import NoArgsCommand -from tastypie.compat import get_user_model +from tastypie.compat import User from tastypie.models import ApiKey @@ -12,7 +12,6 @@ class Command(NoArgsCommand): """Goes through all users and adds API keys for any that don't have one.""" self.verbosity = int(options.get('verbosity', 1)) - User = get_user_model() for user in User.objects.all().iterator(): try: api_key = ApiKey.objects.get(user=user) diff --git a/tastypie/migrations/0001_initial.py b/tastypie/migrations/0001_initial.py index d06753162..ebd9e526c 100644 --- a/tastypie/migrations/0001_initial.py +++ b/tastypie/migrations/0001_initial.py @@ -1,42 +1,97 @@ -# -*- coding: utf-8 -*- +# encoding: utf-8 from __future__ import unicode_literals - -from django.db import models, migrations -from django.conf import settings -import tastypie.utils.timezone +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models +from tastypie.compat import AUTH_USER_MODEL -class Migration(migrations.Migration): +class Migration(SchemaMigration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] + def forwards(self, orm): - operations = [ - migrations.CreateModel( - name='ApiAccess', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('identifier', models.CharField(max_length=255)), - ('url', models.CharField(default='', max_length=255, blank=True)), - ('request_method', models.CharField(default='', max_length=10, blank=True)), - ('accessed', models.PositiveIntegerField()), - ], - options={ - }, - bases=(models.Model,), - ), - migrations.CreateModel( - name='ApiKey', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('key', models.CharField(default='', max_length=128, db_index=True, blank=True)), - ('created', models.DateTimeField(default=tastypie.utils.timezone.now)), - ('user', models.OneToOneField(related_name='api_key', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, - }, - bases=(models.Model,), - ), - ] + # Adding model 'ApiAccess' + db.create_table('tastypie_apiaccess', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('identifier', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('url', self.gf('django.db.models.fields.CharField')(default='', max_length=255, blank=True)), + ('request_method', self.gf('django.db.models.fields.CharField')(default='', max_length=10, blank=True)), + ('accessed', self.gf('django.db.models.fields.PositiveIntegerField')()), + )) + db.send_create_signal('tastypie', ['ApiAccess']) + + # Adding model 'ApiKey' + db.create_table('tastypie_apikey', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.OneToOneField')(related_name='api_key', unique=True, to=orm[AUTH_USER_MODEL])), + ('key', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + )) + db.send_create_signal('tastypie', ['ApiKey']) + + + def backwards(self, orm): + + # Deleting model 'ApiAccess' + db.delete_table('tastypie_apiaccess') + + # Deleting model 'ApiKey' + db.delete_table('tastypie_apikey') + + + 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': {'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_MODEL: { + 'Meta': {'object_name': AUTH_USER_MODEL.split('.')[-1]}, + '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', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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': {'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'}) + }, + 'tastypie.apiaccess': { + 'Meta': {'object_name': 'ApiAccess'}, + 'accessed': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'identifier': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'request_method': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '10', 'blank': 'True'}), + 'url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}) + }, + 'tastypie.apikey': { + 'Meta': {'object_name': 'ApiKey'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'api_key'", 'unique': 'True', 'to': "orm['%s']" % AUTH_USER_MODEL}) + } + } + + complete_apps = ['tastypie'] diff --git a/tastypie/south_migrations/0002_add_apikey_index.py b/tastypie/migrations/0002_add_apikey_index.py similarity index 100% rename from tastypie/south_migrations/0002_add_apikey_index.py rename to tastypie/migrations/0002_add_apikey_index.py diff --git a/tastypie/models.py b/tastypie/models.py index d8ceec808..dd7978a6a 100644 --- a/tastypie/models.py +++ b/tastypie/models.py @@ -3,7 +3,6 @@ import hmac import time from django.conf import settings from django.db import models -from django.utils.encoding import python_2_unicode_compatible from tastypie.utils import now try: @@ -12,7 +11,7 @@ except ImportError: import sha sha1 = sha.sha -@python_2_unicode_compatible + class ApiAccess(models.Model): """A simple model for use with the ``CacheDBThrottle`` behaviors.""" identifier = models.CharField(max_length=255) @@ -20,8 +19,8 @@ class ApiAccess(models.Model): request_method = models.CharField(max_length=10, blank=True, default='') accessed = models.PositiveIntegerField() - def __str__(self): - return "%s @ %s" % (self.identifier, self.accessed) + def __unicode__(self): + return u"%s @ %s" % (self.identifier, self.accessed) def save(self, *args, **kwargs): self.accessed = int(time.time()) diff --git a/tastypie/resources.py b/tastypie/resources.py index 69744d9ae..1cb747f50 100644 --- a/tastypie/resources.py +++ b/tastypie/resources.py @@ -805,10 +805,12 @@ class Resource(six.with_metaclass(DeclarativeMetaclass)): # We mangle the path a bit further & run URL resolution against *only* # the current class. This ought to prevent bad URLs from resolving to # incorrect data. - found_at = chomped_uri.rfind(self._meta.resource_name) - if found_at == -1: + try: + found_at = chomped_uri.index(self._meta.resource_name) + chomped_uri = chomped_uri[found_at:] + except ValueError: raise NotFound("An incorrect URL was provided '%s' for the '%s' resource." % (uri, self.__class__.__name__)) - chomped_uri = chomped_uri[found_at:] + try: for url_resolver in getattr(self, 'urls', []): result = url_resolver.resolve(chomped_uri) @@ -835,9 +837,6 @@ class Resource(six.with_metaclass(DeclarativeMetaclass)): # Dehydrate each field. for field_name, field_object in self.fields.items(): -# import debug -# debug.show('field_name') -# debug.show('field_object') # If it's not for use in this mode, skip field_use_in = getattr(field_object, 'use_in', 'all') if callable(field_use_in): diff --git a/tastypie/serializers.py b/tastypie/serializers.py index a5064a650..527ed3ef3 100644 --- a/tastypie/serializers.py +++ b/tastypie/serializers.py @@ -371,7 +371,7 @@ class Serializer(object): options = options or {} data = self.to_simple(data, options) - return djangojson.json.dumps(data, cls=djangojson.DjangoJSONEncoder, sort_keys=True, ensure_ascii=False, indent=2) + return djangojson.json.dumps(data, cls=djangojson.DjangoJSONEncoder, sort_keys=True, ensure_ascii=False) def from_json(self, content): """ diff --git a/tastypie/south_migrations/0001_initial.py b/tastypie/south_migrations/0001_initial.py deleted file mode 100644 index ebd9e526c..000000000 --- a/tastypie/south_migrations/0001_initial.py +++ /dev/null @@ -1,97 +0,0 @@ -# encoding: utf-8 -from __future__ import unicode_literals -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models -from tastypie.compat import AUTH_USER_MODEL - - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding model 'ApiAccess' - db.create_table('tastypie_apiaccess', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('identifier', self.gf('django.db.models.fields.CharField')(max_length=255)), - ('url', self.gf('django.db.models.fields.CharField')(default='', max_length=255, blank=True)), - ('request_method', self.gf('django.db.models.fields.CharField')(default='', max_length=10, blank=True)), - ('accessed', self.gf('django.db.models.fields.PositiveIntegerField')()), - )) - db.send_create_signal('tastypie', ['ApiAccess']) - - # Adding model 'ApiKey' - db.create_table('tastypie_apikey', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('user', self.gf('django.db.models.fields.related.OneToOneField')(related_name='api_key', unique=True, to=orm[AUTH_USER_MODEL])), - ('key', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), - )) - db.send_create_signal('tastypie', ['ApiKey']) - - - def backwards(self, orm): - - # Deleting model 'ApiAccess' - db.delete_table('tastypie_apiaccess') - - # Deleting model 'ApiKey' - db.delete_table('tastypie_apikey') - - - 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': {'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_MODEL: { - 'Meta': {'object_name': AUTH_USER_MODEL.split('.')[-1]}, - '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', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - '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': {'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'}) - }, - 'tastypie.apiaccess': { - 'Meta': {'object_name': 'ApiAccess'}, - 'accessed': ('django.db.models.fields.PositiveIntegerField', [], {}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'identifier': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'request_method': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '10', 'blank': 'True'}), - 'url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}) - }, - 'tastypie.apikey': { - 'Meta': {'object_name': 'ApiKey'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'api_key'", 'unique': 'True', 'to': "orm['%s']" % AUTH_USER_MODEL}) - } - } - - complete_apps = ['tastypie'] diff --git a/tastypie/south_migrations/__init__.py b/tastypie/south_migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000