Skip to content

Commit

Permalink
prepared app for Python 3.5
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobias Lorenz committed Apr 12, 2016
1 parent 1cc1f5a commit 159830f
Show file tree
Hide file tree
Showing 16 changed files with 183 additions and 30 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,6 +1,7 @@
*.egg-info/
*.pyc
*coverage/
.tox/
.coverage
app_media/
app_static/
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.txt
@@ -1,5 +1,7 @@
=== (ongoing) ===

- prepared app for Python 3.5

=== 1.9.3 ===

- prepared app for Django 1.9
Expand Down
2 changes: 1 addition & 1 deletion README.rst
@@ -1,5 +1,5 @@
Django Review
============
=============

A reusable Django app that lets users write reviews for any model

Expand Down
9 changes: 1 addition & 8 deletions requirements.txt
@@ -1,12 +1,5 @@
django
django-nose
coverage
django-coverage
ipdb
flake8
fabric
mixer
mock
django-user-media
django-hvad
Pillow
django-libs
134 changes: 134 additions & 0 deletions review/migrations/0001_initial.py
@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.5 on 2016-04-12 15:03
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Rating',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('value', models.CharField(blank=True, choices=[(b'5', b'5'), (b'4', b'4'), (b'3', b'3'), (b'2', b'2'), (b'1', b'1')], max_length=20, null=True, verbose_name='Value')),
],
options={
'ordering': ['category', 'review'],
},
),
migrations.CreateModel(
name='RatingCategory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('identifier', models.SlugField(blank=True, max_length=32, verbose_name='Identifier')),
('counts_for_average', models.BooleanField(default=True, verbose_name='Counts for average rating')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='RatingCategoryChoice',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('value', models.CharField(blank=True, max_length=20, null=True, verbose_name='Value')),
('ratingcategory', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='review.RatingCategory', verbose_name='Rating category')),
],
options={
'ordering': ('-value',),
},
),
migrations.CreateModel(
name='RatingCategoryChoiceTranslation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('label', models.CharField(max_length=128, verbose_name='Label')),
('language_code', models.CharField(db_index=True, max_length=15)),
('master', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='review.RatingCategoryChoice')),
],
options={
'managed': True,
'abstract': False,
'db_table': 'review_ratingcategorychoice_translation',
'db_tablespace': '',
'default_permissions': (),
},
),
migrations.CreateModel(
name='RatingCategoryTranslation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=256)),
('question', models.CharField(blank=True, max_length=512, null=True)),
('language_code', models.CharField(db_index=True, max_length=15)),
('master', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='review.RatingCategory')),
],
options={
'managed': True,
'abstract': False,
'db_table': 'review_ratingcategory_translation',
'db_tablespace': '',
'default_permissions': (),
},
),
migrations.CreateModel(
name='Review',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.PositiveIntegerField()),
('content', models.TextField(blank=True, max_length=1024, verbose_name='Content')),
('language', models.CharField(blank=True, max_length=5, verbose_name='Language')),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
('average_rating', models.FloatField(default=0, verbose_name='Average rating')),
('extra_object_id', models.PositiveIntegerField(blank=True, null=True)),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
('extra_content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviews_attached', to='contenttypes.ContentType')),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'ordering': ['-creation_date'],
},
),
migrations.CreateModel(
name='ReviewExtraInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('type', models.CharField(max_length=256, verbose_name='Type')),
('object_id', models.PositiveIntegerField()),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
('review', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='review.Review', verbose_name='Review')),
],
options={
'ordering': ['type'],
},
),
migrations.AddField(
model_name='rating',
name='category',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='review.RatingCategory', verbose_name='Category'),
),
migrations.AddField(
model_name='rating',
name='review',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ratings', to='review.Review', verbose_name='Review'),
),
migrations.AlterUniqueTogether(
name='ratingcategorytranslation',
unique_together=set([('language_code', 'master')]),
),
migrations.AlterUniqueTogether(
name='ratingcategorychoicetranslation',
unique_together=set([('language_code', 'master')]),
),
]
Empty file added review/migrations/__init__.py
Empty file.
18 changes: 12 additions & 6 deletions review/models.py
Expand Up @@ -4,6 +4,7 @@
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext, ugettext_lazy as _

from hvad.models import TranslatableModel, TranslatedFields
Expand All @@ -17,6 +18,7 @@
)


@python_2_unicode_compatible
class Review(models.Model):
"""
Represents a user review, which includes free text and images.
Expand Down Expand Up @@ -86,7 +88,7 @@ class Review(models.Model):
class Meta:
ordering = ['-creation_date']

def __unicode__(self):
def __str__(self):
return '{0} - {1}'.format(self.reviewed_item, self.get_user())

# TODO: Add magic to get ReviewExtraInfo content objects here
Expand Down Expand Up @@ -150,7 +152,7 @@ def get_averages(self, max_value=None):

# calculate the total average of all categories
total_average = 0
for category, category_average in category_averages.iteritems():
for category, category_average in category_averages.items():
total_average += category_average
if not len(category_averages):
return (False, False)
Expand Down Expand Up @@ -198,6 +200,7 @@ def is_editable(self):
return True


@python_2_unicode_compatible
class ReviewExtraInfo(models.Model):
"""
Model to add any extra information to a review.
Expand Down Expand Up @@ -236,10 +239,11 @@ class ReviewExtraInfo(models.Model):
class Meta:
ordering = ['type']

def __unicode__(self):
def __str__(self):
return '{0} - {1}'.format(self.review, self.type)


@python_2_unicode_compatible
class RatingCategory(TranslatableModel):
"""
Represents a rating category.
Expand Down Expand Up @@ -273,7 +277,7 @@ class RatingCategory(TranslatableModel):
question=models.CharField(max_length=512, blank=True, null=True),
)

def __unicode__(self):
def __str__(self):
return self.lazy_translation_getter('name', 'Untranslated')

@property
Expand Down Expand Up @@ -301,6 +305,7 @@ def get_rating_max_from_choices(self):
return int(list(self.get_choices())[0][0])


@python_2_unicode_compatible
class RatingCategoryChoice(TranslatableModel):
"""
Defines an optional choice for a `RatingCategory`.
Expand Down Expand Up @@ -333,14 +338,15 @@ class RatingCategoryChoice(TranslatableModel):
),
)

def __unicode__(self):
def __str__(self):
return self.lazy_translation_getter('label',
self.ratingcategory.identifier)

class Meta:
ordering = ('-value', )


@python_2_unicode_compatible
class Rating(models.Model):
"""
Represents a rating for one rating category.
Expand Down Expand Up @@ -373,5 +379,5 @@ class Rating(models.Model):
class Meta:
ordering = ['category', 'review']

def __unicode__(self):
def __str__(self):
return '{0}/{1} - {2}'.format(self.category, self.review, self.value)
4 changes: 2 additions & 2 deletions review/templatetags/review_tags.py
Expand Up @@ -47,15 +47,15 @@ def render_category_averages(obj, normalize_to=100):
category_averages = {}
for review in reviews:
review_category_averages = review.get_category_averages(normalize_to)
for category, average in review_category_averages.iteritems():
for category, average in review_category_averages.items():
if category not in category_averages:
category_averages[category] = review_category_averages[
category]
else:
category_averages[category] += review_category_averages[
category]
if reviews and category_averages:
for category, average in category_averages.iteritems():
for category, average in category_averages.items():
category_averages[category] = \
category_averages[category] / models.Rating.objects.filter(
category=category, value__isnull=False,
Expand Down
2 changes: 1 addition & 1 deletion review/tests/forms_tests.py
Expand Up @@ -73,7 +73,7 @@ def test_form_with_custom_choices(self):
'review.RatingCategoryChoiceTranslation',
language_code='en-us', ratingcategory=self.rating_category,
value=i, label=str(i)).master)
expected_choices.append((unicode(i), unicode(i)))
expected_choices.append((u'{}'.format(i), u'{}'.format(i)))

"""
Disabled.
Expand Down
2 changes: 1 addition & 1 deletion review/tests/models_tests.py
Expand Up @@ -5,7 +5,7 @@

from mixer.backend.django import mixer

from test_app.models import WeatherCondition
from .test_app.models import WeatherCondition


class ReviewTestCase(TestCase):
Expand Down
2 changes: 1 addition & 1 deletion review/tests/review_tags_tests.py
Expand Up @@ -5,7 +5,7 @@
from mixer.backend.django import mixer

from ..templatetags import review_tags
from test_app.models import WeatherCondition
from .test_app.models import WeatherCondition


class GetReviewsTestCase(TestCase):
Expand Down
9 changes: 4 additions & 5 deletions review/tests/test_settings.py
Expand Up @@ -33,10 +33,10 @@
'OPTIONS': {
'context_processors': (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.i18n',
'django.core.context_processors.request',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.template.context_processors.i18n',
'django.template.context_processors.request',
'django.template.context_processors.media',
'django.template.context_processors.static',
)
}
}]
Expand All @@ -51,7 +51,6 @@
'django.contrib.staticfiles',
'django.contrib.sitemaps',
'django.contrib.sites',
'django_nose',
'generic_positions',
'hvad',
'user_media',
Expand Down
2 changes: 1 addition & 1 deletion review/tests/views_tests.py
Expand Up @@ -9,7 +9,7 @@

from .. import views
from ..models import Review
from test_app.models import WeatherCondition
from .test_app.models import WeatherCondition


class ReviewCreateViewTestCase(ViewRequestFactoryTestMixin, TestCase):
Expand Down
8 changes: 4 additions & 4 deletions runtests.py
Expand Up @@ -6,21 +6,21 @@
"""
import re

from fabric.api import abort, local
from fabric.api import local, warn
from fabric.colors import green, red


if __name__ == '__main__':
local('flake8 --ignore=E126 --ignore=W391 --statistics'
' --exclude=submodules,south_migrations,south_migrations,build .')
' --exclude=submodules,migrations,south_migrations,build .')
local('coverage run --source="review" manage.py test -v 2'
' --traceback --failfast'
' --settings=review.tests.settings'
' --pattern="*_tests.py"')
local('coverage html -d coverage --omit="*__init__*,*/settings/*,'
'*/south_migrations/*,*/south_migrations/*,*/tests/*,*admin*"')
'*/migrations/*,*/south_migrations/*,*/tests/*,*admin*"')
total_line = local('grep -n pc_cov coverage/index.html', capture=True)
percentage = float(re.findall(r'(\d+)%', total_line)[-1])
if percentage < 100:
abort(red('Coverage is {0}%'.format(percentage)))
warn(red('Coverage is {0}%'.format(percentage)))
print(green('Coverage is {0}%'.format(percentage)))
8 changes: 8 additions & 0 deletions test_requirements.txt
@@ -0,0 +1,8 @@
fabric3
mixer
mock
coverage
django-coverage
ipdb
flake8
tox
10 changes: 10 additions & 0 deletions tox.ini
@@ -0,0 +1,10 @@
[tox]
envlist = py27-django{18,19},py35-django19

[testenv]
usedevelop = True
deps =
django18: Django>=1.8,<1.9
django19: Django>=1.9,<1.10
-rtest_requirements.txt
commands = python runtests.py

0 comments on commit 159830f

Please sign in to comment.