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("""
""" %
- (avatar.avatar_url(size), unicode(avatar), size, size))
+ return mark_safe('
' %
+ (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')),
+)