diff --git a/.gitignore b/.gitignore index 394e930..cdf8301 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ pip-log.txt *~ dist/ *.egg-info/ +avatars +.coverage \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0b38572 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +language: python +python: + - 2.6 + - 2.7 + - 3.2 + - 3.3 +install: + - pip install -e . + - pip install -r tests/requirements.txt + - pip install https://github.com/django/django/archive/${DJANGO}.zip#egg=django +script: make test +env: + - DJANGO=1.4.5 + - DJANGO=1.5.1 + - DJANGO=stable/1.6.x +matrix: + exclude: + - python: 3.2 + env: DJANGO=1.4.5 + - python: 3.3 + env: DJANGO=1.4.5 diff --git a/MANIFEST.in b/MANIFEST.in index 676c511..5028a83 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,6 +3,6 @@ include LICENSE.txt include CONTRIBUTORS.txt include avatar/media/avatar/img/default.jpg recursive-include docs * +recursive-include tests * recursive-include avatar/templates *.html *.txt recursive-include avatar/locale/*/LC_MESSAGES *.mo *.po -recursive-include avatar/testdata * diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..09f95cb --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +export DJANGO_SETTINGS_MODULE=tests.settings +export PYTHONPATH=. + +.PHONY: test + +test: + flake8 avatar --ignore=E124,E501,E127,E128 + coverage run --branch --source=avatar `which django-admin.py` test tests + coverage report diff --git a/avatar/admin.py b/avatar/admin.py index a6486ce..d08fbb9 100644 --- a/avatar/admin.py +++ b/avatar/admin.py @@ -3,12 +3,13 @@ from django.utils.translation import ugettext_lazy as _ from avatar.models import Avatar from avatar.templatetags.avatar_tags import avatar -from avatar.util import User +from avatar.util import get_user_model + class AvatarAdmin(admin.ModelAdmin): list_display = ('get_avatar', 'user', 'primary', "date_uploaded") list_filter = ('primary',) - search_fields = ('user__%s' % getattr(User, 'USERNAME_FIELD', 'username'),) + search_fields = ('user__%s' % getattr(get_user_model(), 'USERNAME_FIELD', 'username'),) list_per_page = 50 def get_avatar(self, avatar_in): diff --git a/avatar/forms.py b/avatar/forms.py index 012ab08..d9359ef 100644 --- a/avatar/forms.py +++ b/avatar/forms.py @@ -14,42 +14,51 @@ from avatar.settings import (AVATAR_MAX_AVATARS_PER_USER, AVATAR_MAX_SIZE, def avatar_img(avatar, size): if not avatar.thumbnail_exists(size): avatar.create_thumbnail(size) - return mark_safe("""%s""" % - (avatar.avatar_url(size), unicode(avatar), size, size)) + return mark_safe('%s' % + (avatar.avatar_url(size), unicode(avatar), size, size)) + class UploadAvatarForm(forms.Form): avatar = forms.ImageField(label=_(u"avatar")) - + def __init__(self, *args, **kwargs): self.user = kwargs.pop('user') super(UploadAvatarForm, self).__init__(*args, **kwargs) - + def clean_avatar(self): data = self.cleaned_data['avatar'] if AVATAR_ALLOWED_FILE_EXTS: (root, ext) = os.path.splitext(data.name.lower()) if ext not in AVATAR_ALLOWED_FILE_EXTS: - raise forms.ValidationError( - _(u"%(ext)s is an invalid file extension. Authorized extensions are : %(valid_exts_list)s") % - { 'ext' : ext, 'valid_exts_list' : ", ".join(AVATAR_ALLOWED_FILE_EXTS) }) + raise forms.ValidationError( + _("%(ext)s is an invalid file extension. " + "Authorized extensions are : %(valid_exts_list)s") % + {'ext': ext, 'valid_exts_list': ", ".join(AVATAR_ALLOWED_FILE_EXTS)}) if data.size > AVATAR_MAX_SIZE: - raise forms.ValidationError( - _(u"Your file is too big (%(size)s), the maximum allowed size is %(max_valid_size)s") % - { 'size' : filesizeformat(data.size), 'max_valid_size' : filesizeformat(AVATAR_MAX_SIZE)} ) + error = _("Your file is too big (%(size)s), " + "the maximum allowed size is %(max_valid_size)s") + raise forms.ValidationError(error % { + 'size': filesizeformat(data.size), + 'max_valid_size': filesizeformat(AVATAR_MAX_SIZE) + }) + count = Avatar.objects.filter(user=self.user).count() - if AVATAR_MAX_AVATARS_PER_USER > 1 and \ - count >= AVATAR_MAX_AVATARS_PER_USER: - raise forms.ValidationError( - _(u"You already have %(nb_avatars)d avatars, and the maximum allowed is %(nb_max_avatars)d.") % - { 'nb_avatars' : count, 'nb_max_avatars' : AVATAR_MAX_AVATARS_PER_USER}) - return - + if (AVATAR_MAX_AVATARS_PER_USER > 1 and + count >= AVATAR_MAX_AVATARS_PER_USER): + error = _("You already have %(nb_avatars)d avatars, " + "and the maximum allowed is %(nb_max_avatars)d.") + raise forms.ValidationError(error % { + 'nb_avatars': count, + 'nb_max_avatars': AVATAR_MAX_AVATARS_PER_USER, + }) + return + class PrimaryAvatarForm(forms.Form): - + def __init__(self, *args, **kwargs): - user = kwargs.pop('user') + kwargs.pop('user') size = kwargs.pop('size', AVATAR_DEFAULT_SIZE) avatars = kwargs.pop('avatars') super(PrimaryAvatarForm, self).__init__(*args, **kwargs) @@ -57,10 +66,11 @@ class PrimaryAvatarForm(forms.Form): choices=[(c.id, avatar_img(c, size)) for c in avatars], widget=widgets.RadioSelect) + class DeleteAvatarForm(forms.Form): def __init__(self, *args, **kwargs): - user = kwargs.pop('user') + kwargs.pop('user') size = kwargs.pop('size', AVATAR_DEFAULT_SIZE) avatars = kwargs.pop('avatars') super(DeleteAvatarForm, self).__init__(*args, **kwargs) diff --git a/avatar/management/commands/__init__.py b/avatar/management/commands/__init__.py index 8b13789..e69de29 100644 --- a/avatar/management/commands/__init__.py +++ b/avatar/management/commands/__init__.py @@ -1 +0,0 @@ - diff --git a/avatar/management/commands/rebuild_avatars.py b/avatar/management/commands/rebuild_avatars.py index 83c701d..3a17970 100644 --- a/avatar/management/commands/rebuild_avatars.py +++ b/avatar/management/commands/rebuild_avatars.py @@ -3,12 +3,13 @@ from django.core.management.base import NoArgsCommand from avatar.models import Avatar from avatar.settings import AUTO_GENERATE_AVATAR_SIZES + class Command(NoArgsCommand): help = "Regenerates avatar thumbnails for the sizes specified in " + \ "settings.AUTO_GENERATE_AVATAR_SIZES." - + def handle_noargs(self, **options): for avatar in Avatar.objects.all(): for size in AUTO_GENERATE_AVATAR_SIZES: print "Rebuilding Avatar id=%s at size %s." % (avatar.id, size) - avatar.create_thumbnail(size) \ No newline at end of file + avatar.create_thumbnail(size) diff --git a/avatar/models.py b/avatar/models.py index 95871b2..17decd4 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -2,6 +2,7 @@ import datetime import os import hashlib +from django.conf import settings from django.db import models from django.core.files.base import ContentFile from django.core.files.storage import get_storage_class @@ -9,7 +10,7 @@ from django.utils.translation import ugettext as _ from django.utils.encoding import smart_str from django.db.models import signals -from avatar.util import User, get_username +from avatar.util import get_username try: from cStringIO import StringIO @@ -76,7 +77,7 @@ def find_extension(format): class Avatar(models.Model): - user = models.ForeignKey(User) + user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User')) primary = models.BooleanField(default=False) avatar = models.ImageField(max_length=1024, upload_to=avatar_file_path, diff --git a/avatar/settings.py b/avatar/settings.py index 12d5db2..7b19ef4 100644 --- a/avatar/settings.py +++ b/avatar/settings.py @@ -2,7 +2,7 @@ from django.conf import settings try: from PIL import Image - dir(Image) # Placate PyFlakes + dir(Image) # Placate PyFlakes except ImportError: import Image diff --git a/avatar/signals.py b/avatar/signals.py index 9394445..2ca89f8 100644 --- a/avatar/signals.py +++ b/avatar/signals.py @@ -1,4 +1,4 @@ import django.dispatch -avatar_updated = django.dispatch.Signal(providing_args=["user", "avatar"]) \ No newline at end of file +avatar_updated = django.dispatch.Signal(providing_args=["user", "avatar"]) diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index fbb21df..6ad7584 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -9,8 +9,8 @@ from django.core.urlresolvers import reverse from avatar.settings import (AVATAR_GRAVATAR_BACKUP, AVATAR_GRAVATAR_DEFAULT, AVATAR_DEFAULT_SIZE, AVATAR_GRAVATAR_BASE_URL) -from avatar.util import ( - get_primary_avatar, get_default_avatar_url, cache_result, User, get_user) +from avatar.util import (get_primary_avatar, get_default_avatar_url, + cache_result, get_user_model, get_user) from avatar.models import Avatar register = template.Library() @@ -37,12 +37,12 @@ def avatar_url(user, size=AVATAR_DEFAULT_SIZE): @cache_result @register.simple_tag def avatar(user, size=AVATAR_DEFAULT_SIZE, **kwargs): - if not isinstance(user, User): + if not isinstance(user, get_user_model()): try: user = get_user(user) alt = unicode(user) url = avatar_url(user, size) - except User.DoesNotExist: + except get_user_model().DoesNotExist: url = get_default_avatar_url() alt = _("Default Avatar") else: @@ -59,7 +59,7 @@ def avatar(user, size=AVATAR_DEFAULT_SIZE, **kwargs): @register.filter def has_avatar(user): - if not isinstance(user, User): + if not isinstance(user, get_user_model()): return False return Avatar.objects.filter(user=user, primary=True).exists() diff --git a/avatar/urls.py b/avatar/urls.py index 3635341..c27c6a3 100644 --- a/avatar/urls.py +++ b/avatar/urls.py @@ -1,4 +1,7 @@ -from django.conf.urls.defaults import patterns, url +try: + from django.conf.urls import patterns, url +except ImportError: + from django.conf.urls.defaults import patterns, url urlpatterns = patterns( 'avatar.views', diff --git a/avatar/util.py b/avatar/util.py index 3474ca7..73f55a5 100644 --- a/avatar/util.py +++ b/avatar/util.py @@ -9,9 +9,12 @@ try: from django.contrib.auth import get_user_model except ImportError: from django.contrib.auth.models import User + + def get_user_model(): + return User + custom_user_model = False else: - User = get_user_model() custom_user_model = True from avatar.settings import (AVATAR_DEFAULT_URL, AVATAR_CACHE_TIMEOUT, @@ -19,6 +22,7 @@ from avatar.settings import (AVATAR_DEFAULT_URL, AVATAR_CACHE_TIMEOUT, cached_funcs = set() + def get_username(user): """ Return username of a User instance """ if hasattr(user, 'get_username'): @@ -26,19 +30,20 @@ def get_username(user): else: return user.username + def get_user(username): """ Return user from a username/ish identifier """ if custom_user_model: - return User.objects.get_by_natural_key(username) + return get_user_model().objects.get_by_natural_key(username) else: - return User.objects.get(username=username) + return get_user_model().objects.get(username=username) def get_cache_key(user_or_username, size, prefix): """ Returns a cache key consisten of a username and image size. """ - if isinstance(user_or_username, User): + if isinstance(user_or_username, get_user_model()): user_or_username = get_username(user_or_username) key = u'%s_%s_%s' % (prefix, user_or_username, size) return u'%s_%s' % (slugify(key)[:100], @@ -61,6 +66,7 @@ def cache_result(func): return cache.get(key) or cache_set(key, func(user, size)) return cached_func + def invalidate_cache(user, size=None): """ Function to be called when saving or changing an user's avatars. @@ -72,6 +78,7 @@ def invalidate_cache(user, size=None): for size in sizes: cache.delete(get_cache_key(user, size, prefix)) + def get_default_avatar_url(): base_url = getattr(settings, 'STATIC_URL', None) if not base_url: @@ -88,7 +95,9 @@ def get_default_avatar_url(): return '%s/%s' % (base_url, AVATAR_DEFAULT_URL) return '%s%s' % (base_url, AVATAR_DEFAULT_URL) + def get_primary_avatar(user, size=AVATAR_DEFAULT_SIZE): + User = get_user_model() if not isinstance(user, User): try: user = get_user(user) diff --git a/avatar/views.py b/avatar/views.py index 5910681..a7826c9 100644 --- a/avatar/views.py +++ b/avatar/views.py @@ -1,7 +1,6 @@ from django.core.files.base import ContentFile -from django.http import HttpResponseRedirect, HttpResponse, Http404 -from django.shortcuts import get_object_or_404, render_to_response -from django.template import RequestContext +from django.http import HttpResponse, Http404 +from django.shortcuts import get_object_or_404, render, redirect from django.utils.translation import ugettext as _ from django.views.decorators.csrf import csrf_exempt @@ -12,8 +11,8 @@ from avatar.forms import PrimaryAvatarForm, DeleteAvatarForm, UploadAvatarForm from avatar.models import Avatar from avatar.settings import AVATAR_MAX_AVATARS_PER_USER, AVATAR_DEFAULT_SIZE from avatar.signals import avatar_updated -from avatar.util import ( - get_primary_avatar, get_default_avatar_url, User, get_user) +from avatar.util import (get_primary_avatar, get_default_avatar_url, + get_user_model, get_user) def _get_next(request): @@ -59,7 +58,7 @@ def _get_avatars(user): @csrf_exempt def webcam_upload(request, id): # TODO: add proper security by attaching session to flash request - user = get_object_or_404(User, pk=id) + user = get_object_or_404(get_user_model(), pk=id) if request.method == "POST": avatar = Avatar(user=user, primary=True) avatar.avatar.save("%s_webcam_%s.jpg" % @@ -86,23 +85,21 @@ def add(request, extra_context=None, next_override=None, avatar.save() messages.success(request, _("Successfully uploaded a new avatar.")) avatar_updated.send(sender=Avatar, user=request.user, avatar=avatar) - return HttpResponseRedirect(next_override or _get_next(request)) - return render_to_response( - 'avatar/add.html', - extra_context, - context_instance = RequestContext( - request, - { 'avatar': avatar, - 'avatars': avatars, - 'upload_avatar_form': upload_avatar_form, - 'next': next_override or _get_next(request), } - ) - ) + return redirect(next_override or _get_next(request)) + context = { + 'avatar': avatar, + 'avatars': avatars, + 'upload_avatar_form': upload_avatar_form, + 'next': next_override or _get_next(request), + } + context.update(extra_context) + return render(request, 'avatar/add.html', context) + @login_required def change(request, extra_context=None, next_override=None, - upload_form=UploadAvatarForm, primary_form=PrimaryAvatarForm, - *args, **kwargs): + upload_form=UploadAvatarForm, primary_form=PrimaryAvatarForm, + *args, **kwargs): if extra_context is None: extra_context = {} avatar, avatars = _get_avatars(request.user) @@ -124,19 +121,18 @@ def change(request, extra_context=None, next_override=None, messages.success(request, _("Successfully updated your avatar.")) if updated: avatar_updated.send(sender=Avatar, user=request.user, avatar=avatar) - return HttpResponseRedirect(next_override or _get_next(request)) - return render_to_response( - 'avatar/change.html', - extra_context, - context_instance = RequestContext( - request, - { 'avatar': avatar, - 'avatars': avatars, - 'upload_avatar_form': upload_avatar_form, - 'primary_avatar_form': primary_avatar_form, - 'next': next_override or _get_next(request), } - ) - ) + return redirect(next_override or _get_next(request)) + + context = { + 'avatar': avatar, + 'avatars': avatars, + 'upload_avatar_form': upload_avatar_form, + 'primary_avatar_form': primary_avatar_form, + 'next': next_override or _get_next(request) + } + context.update(extra_context) + return render(request, 'avatar/change.html', context) + @login_required def delete(request, extra_context=None, next_override=None, *args, **kwargs): @@ -158,35 +154,33 @@ def delete(request, extra_context=None, next_override=None, *args, **kwargs): break Avatar.objects.filter(id__in=ids).delete() messages.success(request, _("Successfully deleted the requested avatars.")) - return HttpResponseRedirect(next_override or _get_next(request)) - return render_to_response( - 'avatar/confirm_delete.html', - extra_context, - context_instance = RequestContext( - request, - { 'avatar': avatar, - 'avatars': avatars, - 'delete_avatar_form': delete_avatar_form, - 'next': next_override or _get_next(request), } - ) - ) + return redirect(next_override or _get_next(request)) + context = { + 'avatar': avatar, + 'avatars': avatars, + 'delete_avatar_form': delete_avatar_form, + 'next': next_override or _get_next(request), + } + context.update(extra_context) + + return render(request, 'avatar/confirm_delete.html', context) def avatar_gallery(request, username, template_name="avatar/gallery.html"): try: user = get_user(username) - except User.DoesNotExist: + except get_user_model().DoesNotExist: raise Http404 - return render_to_response(template_name, { + return render(request, template_name, { "other_user": user, "avatars": user.avatar_set.all(), - }, context_instance=RequestContext(request)) + }) def avatar(request, username, id, template_name="avatar/avatar.html"): try: user = get_user(username) - except User.DoesNotExist: + except get_user_model().DoesNotExist: raise Http404 avatars = user.avatar_set.order_by("-date_uploaded") index = None @@ -206,26 +200,26 @@ def avatar(request, username, id, template_name="avatar/avatar.html"): else: next = avatars[1] else: - prev = avatars[index-1] + prev = avatars[index - 1] - if (index+1)>=count: + if (index + 1) >= count: next = avatars[0] - prev_index = index-1 + prev_index = index - 1 if prev_index < 0: prev_index = 0 prev = avatars[prev_index] else: - next = avatars[index+1] + next = avatars[index + 1] - return render_to_response(template_name, { + return render(request, template_name, { "other_user": user, "avatar": avatar, - "index": index+1, + "index": index + 1, "avatars": avatars, "next": next, "prev": prev, "count": count, - }, context_instance=RequestContext(request)) + }) def render_primary(request, extra_context={}, user=None, size=AVATAR_DEFAULT_SIZE, *args, **kwargs): @@ -237,7 +231,6 @@ def render_primary(request, extra_context={}, user=None, size=AVATAR_DEFAULT_SIZ # be useful in certain situations, particulary if there is a CDN and # we want to minimize the storage usage on our static server, letting # the CDN store those files instead - return HttpResponseRedirect(avatar.avatar_url(size)) + return redirect(avatar.avatar_url(size)) else: - url = get_default_avatar_url() - return HttpResponseRedirect(url) + return redirect(get_default_avatar_url()) diff --git a/docs/index.txt b/docs/index.txt index 398708b..49a946d 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -14,4 +14,4 @@ Contents: .. toctree:: install.txt - usage.txt \ No newline at end of file + usage.txt diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/avatar/testdata/imagefilewithoutext b/tests/data/imagefilewithoutext similarity index 100% rename from avatar/testdata/imagefilewithoutext rename to tests/data/imagefilewithoutext diff --git a/avatar/testdata/imagefilewithwrongext.ogg b/tests/data/imagefilewithwrongext.ogg similarity index 100% rename from avatar/testdata/imagefilewithwrongext.ogg rename to tests/data/imagefilewithwrongext.ogg diff --git a/avatar/testdata/nonimagefile b/tests/data/nonimagefile similarity index 100% rename from avatar/testdata/nonimagefile rename to tests/data/nonimagefile diff --git a/avatar/testdata/test.png b/tests/data/test.png similarity index 100% rename from avatar/testdata/test.png rename to tests/data/test.png diff --git a/avatar/testdata/testbig.png b/tests/data/testbig.png similarity index 100% rename from avatar/testdata/testbig.png rename to tests/data/testbig.png diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..054e173 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,3 @@ +flake8 +coverage +django-discover-runner \ No newline at end of file diff --git a/tests/runtests.py b/tests/runtests.py deleted file mode 100755 index c9e375a..0000000 --- a/tests/runtests.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -import tempfile - -ROOT = os.path.abspath(os.path.dirname(__file__)) -APP_ROOT = os.path.join(ROOT, '..') -sys.path.append(APP_ROOT) - -os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' - -from django.conf import settings - -# We do this here because settings.py has a tendency to be imported more than -# once, in certain situations, and we only want one temporary test folder. -MEDIA_ROOT = os.path.join(tempfile.gettempdir(), 'avatars') -if not os.path.exists(MEDIA_ROOT): - os.makedirs(os.path.join(MEDIA_ROOT, 'test')) -settings.MEDIA_ROOT = MEDIA_ROOT - -from django.test.simple import run_tests - -if __name__ == "__main__": - failures = run_tests(['avatar'], verbosity=1) - if failures: - sys.exit(failures) \ No newline at end of file diff --git a/tests/settings.py b/tests/settings.py index dbcd576..e1c6b18 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1,36 +1,36 @@ -from django.conf.urls.defaults import patterns, include, handler500, handler404 - -DEFAULT_CHARSET = 'utf-8' - +import django + DATABASE_ENGINE = 'sqlite3' -DATABASE_NAME = ':memory:' - -ROOT_URLCONF = 'settings' -STATIC_URL = '/site_media/static/' +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } +} -SITE_ID = 1 - -INSTALLED_APPS = ( +INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sites', 'django.contrib.comments', 'avatar', -) - -TEMPLATE_LOADERS = ( - 'django.template.loaders.app_directories.load_template_source', -) - +] + +ROOT_URLCONF = 'tests.urls' + +SITE_ID = 1 + +SECRET_KEY = 'something-something' + +if django.VERSION[:2] < (1, 6): + TEST_RUNNER = 'discover_runner.DiscoverRunner' + +ROOT_URLCONF = 'tests.urls' + +STATIC_URL = '/site_media/static/' + AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png') AVATAR_MAX_SIZE = 1024 * 1024 AVATAR_MAX_AVATARS_PER_USER = 20 - -urlpatterns = patterns('', - (r'^avatar/', include('avatar.urls')), -) - -def __exported_functionality__(): - return (handler500, handler404) diff --git a/avatar/tests.py b/tests/tests.py similarity index 84% rename from avatar/tests.py rename to tests/tests.py index 6d233d8..b05e8e2 100644 --- a/avatar/tests.py +++ b/tests/tests.py @@ -5,15 +5,10 @@ from django.core.urlresolvers import reverse from django.conf import settings from avatar.settings import AVATAR_DEFAULT_URL, AVATAR_MAX_AVATARS_PER_USER -from avatar.util import get_primary_avatar, User +from avatar.util import get_primary_avatar, get_user_model from avatar.models import Avatar +from PIL import Image -try: - from PIL import Image - dir(Image) # Placate PyFlakes -except ImportError: - import Image - def upload_helper(o, filename): f = open(os.path.join(o.testdatapath, filename), "rb") @@ -23,11 +18,12 @@ def upload_helper(o, filename): f.close() return response + class AvatarUploadTests(TestCase): - + def setUp(self): - self.testdatapath = os.path.join(os.path.dirname(__file__), "testdata") - self.user = User.objects.create_user('test', 'lennon@thebeatles.com', 'testpassword') + self.testdatapath = os.path.join(os.path.dirname(__file__), "data") + self.user = get_user_model().objects.create_user('test', 'lennon@thebeatles.com', 'testpassword') self.user.save() self.client.login(username='test', password='testpassword') Image.init() @@ -36,7 +32,7 @@ class AvatarUploadTests(TestCase): response = upload_helper(self, "nonimagefile") self.failUnlessEqual(response.status_code, 200) self.failIfEqual(response.context['upload_avatar_form'].errors, {}) - + def testNormalImageUpload(self): response = upload_helper(self, "test.png") self.failUnlessEqual(response.status_code, 200) @@ -44,28 +40,28 @@ class AvatarUploadTests(TestCase): self.failUnlessEqual(response.context['upload_avatar_form'].errors, {}) avatar = get_primary_avatar(self.user) self.failIfEqual(avatar, None) - + def testImageWithoutExtension(self): # use with AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png') response = upload_helper(self, "imagefilewithoutext") self.failUnlessEqual(response.status_code, 200) - self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked + self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.failIfEqual(response.context['upload_avatar_form'].errors, {}) - + def testImageWithWrongExtension(self): # use with AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png') response = upload_helper(self, "imagefilewithwrongext.ogg") self.failUnlessEqual(response.status_code, 200) - self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked + self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.failIfEqual(response.context['upload_avatar_form'].errors, {}) - + def testImageTooBig(self): # use with AVATAR_MAX_SIZE = 1024 * 1024 response = upload_helper(self, "testbig.png") self.failUnlessEqual(response.status_code, 200) - self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked + self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.failIfEqual(response.context['upload_avatar_form'].errors, {}) - + def testDefaultUrl(self): response = self.client.get(reverse('avatar_render_primary', kwargs={ 'user': self.user.username, @@ -81,13 +77,13 @@ class AvatarUploadTests(TestCase): def testNonExistingUser(self): a = get_primary_avatar("nonexistinguser") self.failUnlessEqual(a, None) - + def testThereCanBeOnlyOnePrimaryAvatar(self): for i in range(1, 10): self.testNormalImageUpload() count = Avatar.objects.filter(user=self.user, primary=True).count() self.failUnlessEqual(count, 1) - + def testDeleteAvatar(self): self.testNormalImageUpload() avatar = Avatar.objects.filter(user=self.user) @@ -99,12 +95,12 @@ class AvatarUploadTests(TestCase): self.failUnlessEqual(len(response.redirect_chain), 1) count = Avatar.objects.filter(user=self.user).count() self.failUnlessEqual(count, 0) - + def testDeletePrimaryAvatarAndNewPrimary(self): self.testThereCanBeOnlyOnePrimaryAvatar() primary = get_primary_avatar(self.user) oid = primary.id - response = self.client.post(reverse('avatar_delete'), { + self.client.post(reverse('avatar_delete'), { 'choices': [oid], }) primaries = Avatar.objects.filter(user=self.user, primary=True) @@ -116,11 +112,11 @@ class AvatarUploadTests(TestCase): def testTooManyAvatars(self): for i in range(0, AVATAR_MAX_AVATARS_PER_USER): self.testNormalImageUpload() - count_before = Avatar.objects.filter(user=self.user).count() + count_before = Avatar.objects.filter(user=self.user).count() response = upload_helper(self, "test.png") count_after = Avatar.objects.filter(user=self.user).count() self.failUnlessEqual(response.status_code, 200) - self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked + self.failUnlessEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.failIfEqual(response.context['upload_avatar_form'].errors, {}) self.failUnlessEqual(count_before, count_after) @@ -129,5 +125,5 @@ class AvatarUploadTests(TestCase): # def testHashFileName # def testHashUserName # def testChangePrimaryAvatar - # def testDeleteThumbnailAndRecreation + # def testDeleteThumbnailAndRecreation # def testAutomaticThumbnailCreation diff --git a/tests/urls.py b/tests/urls.py new file mode 100644 index 0000000..52c00f4 --- /dev/null +++ b/tests/urls.py @@ -0,0 +1,9 @@ +try: + from django.conf.urls import patterns, include +except ImportError: + from django.conf.urls.defaults import patterns, include + + +urlpatterns = patterns('', + (r'^avatar/', include('avatar.urls')), +)