diff --git a/.travis.yml b/.travis.yml index 4c59281..f258b85 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,8 @@ env: - DJANGO='django17' CMS='cms30' - DJANGO='django17' CMS='cms31' - DJANGO='django17' CMS='cms32' + - TOXENV='pep8' + - TOXENV='isort' # command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors @@ -27,9 +29,10 @@ install: - "if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then export PYVER=py27; fi" - "if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then export PYVER=py33; fi" - "if [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then export PYVER=py34; fi" + - "if [[ ${DJANGO}z != 'z' ]]; then export TOXENV=$PYVER-$DJANGO-$CMS; fi" # command to run tests, e.g. python setup.py test -script: COMMAND='coverage run' tox -e"$PYVER-$DJANGO-$CMS" +script: COMMAND='coverage run' tox -e$TOXENV after_success: coveralls diff --git a/Makefile b/Makefile index f71f11b..b02d1d3 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ clean-pyc: find . -name '*~' -exec rm -f {} + lint: - flake8 djangocms_blog + flake8 djangocms_blog tests djangocms-helper djangocms_blog pyflakes --cms test: diff --git a/cms_helper.py b/cms_helper.py index 17d6bce..0ba692e 100755 --- a/cms_helper.py +++ b/cms_helper.py @@ -1,16 +1,16 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - import sys from tempfile import mkdtemp + gettext = lambda s: s -HELPER_SETTINGS = { - 'NOSE_ARGS': [ +HELPER_SETTINGS = dict( + NOSE_ARGS=[ '-s', ], - 'ROOT_URLCONF': 'tests.test_utils.urls', - 'INSTALLED_APPS': [ + ROOT_URLCONF='tests.test_utils.urls', + INSTALLED_APPS=[ 'admin_enhancer', 'filer', 'parler', @@ -22,13 +22,13 @@ HELPER_SETTINGS = { 'cmsplugin_filer_image', 'taggit_autosuggest', ], - 'LANGUAGE_CODE': 'en', - 'LANGUAGES': ( + LANGUAGE_CODE='en', + LANGUAGES=( ('en', gettext('English')), ('fr', gettext('French')), ('it', gettext('Italiano')), ), - 'CMS_LANGUAGES': { + CMS_LANGUAGES={ 1: [ { 'code': 'en', @@ -57,7 +57,7 @@ HELPER_SETTINGS = { 'hide_untranslated': False, }, }, - 'PARLER_LANGUAGES': { + PARLER_LANGUAGES={ 1: ( {'code': 'en'}, {'code': 'it'}, @@ -71,31 +71,32 @@ HELPER_SETTINGS = { 'hide_untranslated': False, } }, - 'MIGRATION_MODULES': { + MIGRATION_MODULES={ 'cmsplugin_filer_image': 'cmsplugin_filer_image.migrations_django', }, - 'META_SITE_PROTOCOL': 'http', - 'META_SITE_DOMAIN': 'example.com', - 'META_USE_OG_PROPERTIES': True, - 'META_USE_TWITTER_PROPERTIES': True, - 'META_USE_GOOGLEPLUS_PROPERTIES': True, - 'THUMBNAIL_PROCESSORS': ( + META_SITE_PROTOCOL='http', + META_SITE_DOMAIN='example.com', + META_USE_OG_PROPERTIES=True, + META_USE_TWITTER_PROPERTIES=True, + META_USE_GOOGLEPLUS_PROPERTIES=True, + THUMBNAIL_PROCESSORS=( 'easy_thumbnails.processors.colorspace', 'easy_thumbnails.processors.autocrop', 'filer.thumbnail_processors.scale_and_crop_with_subject_location', 'easy_thumbnails.processors.filters', ), - 'FILE_UPLOAD_TEMP_DIR': mkdtemp(), - 'SITE_ID': 1 -} -if 'test' in sys.argv: + FILE_UPLOAD_TEMP_DIR=mkdtemp(), + SITE_ID=1 +) +if 'test' in sys.argv or len(sys.argv) == 1: HELPER_SETTINGS['INSTALLED_APPS'].append('django_nose') def run(): from djangocms_helper import runner - sys.argv.append('--nose-runner') + if 'test' in sys.argv or len(sys.argv) == 1: + sys.argv.append('--nose-runner') runner.cms('djangocms_blog') if __name__ == "__main__": - run() \ No newline at end of file + run() diff --git a/djangocms_blog/admin.py b/djangocms_blog/admin.py index accf360..f74de80 100755 --- a/djangocms_blog/admin.py +++ b/djangocms_blog/admin.py @@ -2,14 +2,14 @@ from copy import deepcopy from admin_enhancer.admin import EnhancedModelAdminMixin -from cms.admin.placeholderadmin import PlaceholderAdminMixin, FrontendEditableAdminMixin +from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin from django import forms from django.conf import settings from django.contrib import admin from django.contrib.auth import get_user_model from parler.admin import TranslatableAdmin -from .models import Post, BlogCategory +from .models import BlogCategory, Post from .settings import get_setting diff --git a/djangocms_blog/cms_app.py b/djangocms_blog/cms_app.py index fd9a38d..2a6243b 100644 --- a/djangocms_blog/cms_app.py +++ b/djangocms_blog/cms_app.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- from cms.app_base import CMSApp from cms.apphook_pool import apphook_pool -from django.utils.translation import ugettext_lazy as _, get_language +from django.utils.translation import ugettext_lazy as _ + from .menu import BlogCategoryMenu diff --git a/djangocms_blog/cms_plugins.py b/djangocms_blog/cms_plugins.py index c52d0de..0af4eff 100644 --- a/djangocms_blog/cms_plugins.py +++ b/djangocms_blog/cms_plugins.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- -from django.utils.translation import ugettext_lazy as _ - from cms.models.pluginmodel import CMSPlugin from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool +from django.utils.translation import ugettext_lazy as _ -from .models import AuthorEntriesPlugin, LatestPostsPlugin, Post, BlogCategory from .forms import LatestEntriesForm +from .models import AuthorEntriesPlugin, BlogCategory, LatestPostsPlugin, Post from .settings import get_setting diff --git a/djangocms_blog/cms_toolbar.py b/djangocms_blog/cms_toolbar.py index 741f174..ac79239 100644 --- a/djangocms_blog/cms_toolbar.py +++ b/djangocms_blog/cms_toolbar.py @@ -4,7 +4,6 @@ from cms.toolbar_pool import toolbar_pool from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ - from .models import BLOG_CURRENT_POST_IDENTIFIER @@ -32,7 +31,7 @@ class BlogToolbar(CMSToolbar): if current_post and self.request.user.has_perm('djangocms_blog.change_post'): # pragma: no cover # removing page meta menu, if present, to avoid confusion try: # pragma: no cover - import djangocms_page_meta + import djangocms_page_meta # NOQA menu = self.request.toolbar.get_or_create_menu('page') pagemeta = menu.get_or_create_menu('pagemeta', 'meta') menu.remove_item(pagemeta) @@ -40,7 +39,7 @@ class BlogToolbar(CMSToolbar): pass # removing page tags menu, if present, to avoid confusion try: # pragma: no cover - import djangocms_page_tags + import djangocms_page_tags # NOQA menu = self.request.toolbar.get_or_create_menu('page') pagetags = menu.get_or_create_menu('pagetags', 'tags') menu.remove_item(pagetags) diff --git a/djangocms_blog/compat.py b/djangocms_blog/compat.py index e573006..7a2405d 100644 --- a/djangocms_blog/compat.py +++ b/djangocms_blog/compat.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -from operator import itemgetter from heapq import nlargest -from itertools import repeat, ifilter +from itertools import ifilter, repeat +from operator import itemgetter class Counter(dict): diff --git a/djangocms_blog/managers.py b/djangocms_blog/managers.py index cc728cd..0d8ae02 100644 --- a/djangocms_blog/managers.py +++ b/djangocms_blog/managers.py @@ -1,16 +1,14 @@ # -*- coding: utf-8 -*- -import django -from django.contrib.sites.models import Site -from django.db.models import Q - try: from collections import Counter except ImportError: from .compat import Counter +import django +from django.contrib.sites.models import Site from django.db import models from django.utils.timezone import now -from parler.managers import TranslationManager, TranslatableQuerySet +from parler.managers import TranslatableQuerySet, TranslationManager class TaggedFilterItem(object): @@ -78,7 +76,8 @@ class GenericDateQuerySet(TranslatableQuerySet): publish_field = 'publish' def on_site(self): - return self.filter(Q(sites__isnull=True) | Q(sites=Site.objects.get_current().pk)) + return self.filter(models.Q(sites__isnull=True) | + models.Q(sites=Site.objects.get_current().pk)) def published(self): queryset = self.published_future() diff --git a/djangocms_blog/menu.py b/djangocms_blog/menu.py index 3650b27..aa14975 100644 --- a/djangocms_blog/menu.py +++ b/djangocms_blog/menu.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- from cms.menu_bases import CMSAttachMenu +from django.db.models.signals import post_delete, post_save +from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import get_language from menus.base import Modifier, NavigationNode from menus.menu_pool import menu_pool -from django.db.models.signals import post_save, post_delete -from django.utils.translation import ugettext_lazy as _, get_language + from .models import BlogCategory @@ -34,7 +36,8 @@ class BlogNavModifier(Modifier): a corresponding category is selected in menu """ def modify(self, request, nodes, namespace, root_id, post_cut, breadcrumb): - if post_cut: return nodes + if post_cut: + return nodes if not hasattr(request, 'toolbar'): return nodes models = ('djangocms_blog.post', 'djangocms_blog.blogcategory') @@ -45,7 +48,8 @@ class BlogNavModifier(Modifier): cat = request.toolbar.obj else: cat = request.toolbar.obj.categories.first() - if not cat: return nodes + if not cat: + return nodes for node in nodes: if (node.namespace.startswith(BlogCategoryMenu.__name__) and @@ -57,6 +61,7 @@ class BlogNavModifier(Modifier): menu_pool.register_modifier(BlogNavModifier) + def clear_menu_cache(**kwargs): menu_pool.clear(all=True) diff --git a/djangocms_blog/migrations/0007_auto_20150719_0933.py b/djangocms_blog/migrations/0007_auto_20150719_0933.py new file mode 100644 index 0000000..7b62d62 --- /dev/null +++ b/djangocms_blog/migrations/0007_auto_20150719_0933.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import filer.fields.image +import django.utils.timezone +from django.conf import settings +import djangocms_text_ckeditor.fields +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_blog', '0006_auto_20150214_1907'), + ] + + operations = [ + migrations.AlterModelOptions( + name='blogcategorytranslation', + options={'managed': True, 'verbose_name': 'blog category Translation', 'default_permissions': ()}, + ), + migrations.AlterModelOptions( + name='posttranslation', + options={'managed': True, 'verbose_name': 'blog article Translation', 'default_permissions': ()}, + ), + migrations.AlterField( + model_name='authorentriesplugin', + name='authors', + field=models.ManyToManyField(verbose_name='authors', to=settings.AUTH_USER_MODEL), + preserve_default=True, + ), + migrations.AlterField( + model_name='authorentriesplugin', + name='latest_posts', + field=models.IntegerField(help_text='The number of author articles to be displayed.', verbose_name='articles', default=5), + preserve_default=True, + ), + migrations.AlterField( + model_name='blogcategorytranslation', + name='language_code', + field=models.CharField(db_index=True, verbose_name='Language', max_length=15), + preserve_default=True, + ), + migrations.AlterField( + model_name='latestpostsplugin', + name='categories', + field=models.ManyToManyField(blank=True, help_text='Show only the blog articles tagged with chosen categories.', verbose_name='filter by category', to='djangocms_blog.BlogCategory'), + preserve_default=True, + ), + migrations.AlterField( + model_name='latestpostsplugin', + name='latest_posts', + field=models.IntegerField(help_text='The number of latests articles to be displayed.', verbose_name='articles', default=5), + preserve_default=True, + ), + migrations.AlterField( + model_name='latestpostsplugin', + name='tags', + field=models.ManyToManyField(blank=True, help_text='Show only the blog articles tagged with chosen tags.', verbose_name='filter by tag', to='taggit.Tag'), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='author', + field=models.ForeignKey(blank=True, verbose_name='author', to=settings.AUTH_USER_MODEL, related_name='djangocms_blog_post_author', null=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='date_created', + field=models.DateTimeField(auto_now_add=True, verbose_name='created'), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='date_modified', + field=models.DateTimeField(auto_now=True, verbose_name='last modified'), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='date_published', + field=models.DateTimeField(verbose_name='published Since', default=django.utils.timezone.now), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='date_published_end', + field=models.DateTimeField(blank=True, verbose_name='published Until', null=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='enable_comments', + field=models.BooleanField(verbose_name='enable comments on post', default=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='main_image', + field=filer.fields.image.FilerImageField(on_delete=django.db.models.deletion.SET_NULL, blank=True, verbose_name='main image', to='filer.Image', related_name='djangocms_blog_post_image', null=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='main_image_full', + field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, verbose_name='main image full', to='cmsplugin_filer_image.ThumbnailOption', related_name='djangocms_blog_post_full', null=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='main_image_thumbnail', + field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, verbose_name='main image thumbnail', to='cmsplugin_filer_image.ThumbnailOption', related_name='djangocms_blog_post_thumbnail', null=True), + preserve_default=True, + ), + migrations.AlterField( + model_name='post', + name='publish', + field=models.BooleanField(verbose_name='publish', default=False), + preserve_default=True, + ), + migrations.AlterField( + model_name='posttranslation', + name='abstract', + field=djangocms_text_ckeditor.fields.HTMLField(verbose_name='abstract'), + preserve_default=True, + ), + migrations.AlterField( + model_name='posttranslation', + name='language_code', + field=models.CharField(db_index=True, verbose_name='Language', max_length=15), + preserve_default=True, + ), + migrations.AlterField( + model_name='posttranslation', + name='meta_description', + field=models.TextField(blank=True, verbose_name='post meta description', default=''), + preserve_default=True, + ), + migrations.AlterField( + model_name='posttranslation', + name='meta_keywords', + field=models.TextField(blank=True, verbose_name='post meta keywords', default=''), + preserve_default=True, + ), + migrations.AlterField( + model_name='posttranslation', + name='meta_title', + field=models.CharField(blank=True, help_text='used in title tag and social sharing', verbose_name='post meta title', max_length=255, default=''), + preserve_default=True, + ), + migrations.AlterField( + model_name='posttranslation', + name='post_text', + field=djangocms_text_ckeditor.fields.HTMLField(blank=True, verbose_name='text', default=''), + preserve_default=True, + ), + migrations.AlterField( + model_name='posttranslation', + name='title', + field=models.CharField(verbose_name='title', max_length=255), + preserve_default=True, + ), + ] diff --git a/djangocms_blog/models.py b/djangocms_blog/models.py index ba6a63a..8124109 100644 --- a/djangocms_blog/models.py +++ b/djangocms_blog/models.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from cms.models import PlaceholderField, CMSPlugin +from cms.models import CMSPlugin, PlaceholderField from cmsplugin_filer_image.models import ThumbnailOption from django.conf import settings as dj_settings from django.contrib.sites.models import Site @@ -7,18 +7,19 @@ from django.core.urlresolvers import reverse from django.db import models from django.utils import timezone from django.utils.encoding import force_text, python_2_unicode_compatible -from django.utils.html import strip_tags, escape +from django.utils.html import escape, strip_tags from django.utils.text import slugify -from django.utils.translation import ugettext_lazy as _, get_language +from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import get_language from djangocms_text_ckeditor.fields import HTMLField from filer.fields.image import FilerImageField from meta_mixin.models import ModelMeta -from parler.models import TranslatableModel, TranslatedFields from parler.managers import TranslationManager +from parler.models import TranslatableModel, TranslatedFields from taggit_autosuggest.managers import TaggableManager -from .settings import get_setting from .managers import GenericDateTaggedManager +from .settings import get_setting BLOG_CURRENT_POST_IDENTIFIER = 'djangocms_post_current' @@ -76,33 +77,33 @@ class Post(ModelMeta, TranslatableModel): Blog post """ author = models.ForeignKey(dj_settings.AUTH_USER_MODEL, - verbose_name=_('Author'), null=True, blank=True, + verbose_name=_(u'author'), null=True, blank=True, related_name='djangocms_blog_post_author') - date_created = models.DateTimeField(auto_now_add=True) - date_modified = models.DateTimeField(auto_now=True) - date_published = models.DateTimeField(_('Published Since'), + date_created = models.DateTimeField(_(u'created'), auto_now_add=True) + date_modified = models.DateTimeField(_(u'last modified'), auto_now=True) + date_published = models.DateTimeField(_(u'published Since'), default=timezone.now) - date_published_end = models.DateTimeField(_('Published Until'), null=True, + date_published_end = models.DateTimeField(_(u'published Until'), null=True, blank=True) - publish = models.BooleanField(_('Publish'), default=False) - categories = models.ManyToManyField(BlogCategory, verbose_name=_('category'), + publish = models.BooleanField(_(u'publish'), default=False) + categories = models.ManyToManyField(BlogCategory, verbose_name=_(u'category'), related_name='blog_posts',) - main_image = FilerImageField(verbose_name=_('Main image'), blank=True, null=True, + main_image = FilerImageField(verbose_name=_(u'main image'), blank=True, null=True, on_delete=models.SET_NULL, related_name='djangocms_blog_post_image') main_image_thumbnail = models.ForeignKey(ThumbnailOption, - verbose_name=_('Main image thumbnail'), + verbose_name=_(u'main image thumbnail'), related_name='djangocms_blog_post_thumbnail', on_delete=models.SET_NULL, blank=True, null=True) main_image_full = models.ForeignKey(ThumbnailOption, - verbose_name=_('Main image full'), + verbose_name=_(u'main image full'), related_name='djangocms_blog_post_full', on_delete=models.SET_NULL, blank=True, null=True) enable_comments = models.BooleanField( - verbose_name=_(u'Enable comments on post'), + verbose_name=_(u'enable comments on post'), default=get_setting('ENABLE_COMMENTS') ) sites = models.ManyToManyField(Site, verbose_name=_(u'Site(s)'), blank=True, @@ -113,18 +114,18 @@ class Post(ModelMeta, TranslatableModel): ) translations = TranslatedFields( - title=models.CharField(_('Title'), max_length=255), - slug=models.SlugField(_('slug'), blank=True, db_index=True), - abstract=HTMLField(_('Abstract'), blank=True, default=''), - meta_description=models.TextField(verbose_name=_(u'Post meta description'), + title=models.CharField(_(u'title'), max_length=255), + slug=models.SlugField(_(u'slug'), blank=True, db_index=True), + abstract=HTMLField(_(u'abstract'), blank=True, default=''), + meta_description=models.TextField(verbose_name=_(u'post meta description'), blank=True, default=''), - meta_keywords=models.TextField(verbose_name=_(u'Post meta keywords'), + meta_keywords=models.TextField(verbose_name=_(u'post meta keywords'), blank=True, default=''), - meta_title=models.CharField(verbose_name=_(u'Post meta title'), + meta_title=models.CharField(verbose_name=_(u'post meta title'), help_text=_(u'used in title tag and social sharing'), max_length=255, blank=True, default=''), - post_text=HTMLField(_('Text'), default='', blank=True), + post_text=HTMLField(_(u'text'), default='', blank=True), meta={'unique_together': (('language_code', 'slug'),)} ) content = PlaceholderField('post_content', related_name='post_content') @@ -159,6 +160,34 @@ class Post(ModelMeta, TranslatableModel): 'url': 'get_absolute_url', } + class Meta: + verbose_name = _('blog article') + verbose_name_plural = _('blog articles') + ordering = ('-date_published', '-date_created') + get_latest_by = 'date_published' + + def __str__(self): + return self.safe_translation_getter('title') + + def get_absolute_url(self): + kwargs = {'year': self.date_published.year, + 'month': '%02d' % self.date_published.month, + 'day': '%02d' % self.date_published.day, + 'slug': self.safe_translation_getter('slug', + language_code=get_language(), + any_language=True)} + return reverse('djangocms_blog:post-detail', kwargs=kwargs) + + def save(self, *args, **kwargs): + super(Post, self).save(*args, **kwargs) + main_lang = self.get_current_language() + for lang in self.get_available_languages(): + self.set_current_language(lang) + if not self.slug and self.title: + self.slug = slugify(self.title) + self.set_current_language(main_lang) + self.save_translations() + def get_title(self): title = self.safe_translation_getter('meta_title', any_language=True) if not title: @@ -186,34 +215,6 @@ class Post(ModelMeta, TranslatableModel): def get_author(self): return self.author - class Meta: - verbose_name = _('blog article') - verbose_name_plural = _('blog articles') - ordering = ('-date_published', '-date_created') - get_latest_by = 'date_published' - - def __str__(self): - return self.safe_translation_getter('title') - - def save(self, *args, **kwargs): - super(Post, self).save(*args, **kwargs) - main_lang = self.get_current_language() - for lang in self.get_available_languages(): - self.set_current_language(lang) - if not self.slug and self.title: - self.slug = slugify(self.title) - self.set_current_language(main_lang) - self.save_translations() - - def get_absolute_url(self): - kwargs = {'year': self.date_published.year, - 'month': '%02d' % self.date_published.month, - 'day': '%02d' % self.date_published.day, - 'slug': self.safe_translation_getter('slug', - language_code=get_language(), - any_language=True)} - return reverse('djangocms_blog:post-detail', kwargs=kwargs) - def thumbnail_options(self): if self.main_image_thumbnail_id: return self.main_image_thumbnail.as_dict @@ -244,20 +245,20 @@ class BasePostPlugin(CMSPlugin): return posts def __str__(self): - return unicode(self.latest_posts) + return force_text(self.latest_posts) class LatestPostsPlugin(BasePostPlugin): - latest_posts = models.IntegerField(_(u'Articles'), default=get_setting('LATEST_POSTS'), - help_text=_('The number of latests articles to be displayed.')) - tags = models.ManyToManyField('taggit.Tag', blank=True, - help_text=_('Show only the blog articles tagged with chosen tags.')) - categories = models.ManyToManyField('BlogCategory', blank=True, - help_text=_('Show only the blog articles tagged with chosen categories.')) + latest_posts = models.IntegerField(_(u'articles'), default=get_setting('LATEST_POSTS'), + help_text=_(u'The number of latests articles to be displayed.')) + tags = models.ManyToManyField('taggit.Tag', blank=True, verbose_name=_(u'filter by tag'), + help_text=_(u'Show only the blog articles tagged with chosen tags.')) + categories = models.ManyToManyField('BlogCategory', blank=True, verbose_name=_(u'filter by category'), + help_text=_(u'Show only the blog articles tagged with chosen categories.')) def __str__(self): - return u'%s latest articles by tag' % self.latest_posts + return _(u'%s latest articles by tag') % self.latest_posts def copy_relations(self, oldinstance): self.tags = oldinstance.tags.all() @@ -273,16 +274,16 @@ class LatestPostsPlugin(BasePostPlugin): class AuthorEntriesPlugin(BasePostPlugin): authors = models.ManyToManyField( - dj_settings.AUTH_USER_MODEL, verbose_name=_('Authors'), + dj_settings.AUTH_USER_MODEL, verbose_name=_('authors'), limit_choices_to={'djangocms_blog_post_author__publish': True} ) latest_posts = models.IntegerField( - _(u'Articles'), default=get_setting('LATEST_POSTS'), - help_text=_('The number of author articles to be displayed.') + _(u'articles'), default=get_setting('LATEST_POSTS'), + help_text=_(u'The number of author articles to be displayed.') ) def __str__(self): - return u'%s latest articles by author' % self.latest_posts + return _(u'%s latest articles by author') % self.latest_posts def copy_relations(self, oldinstance): self.authors = oldinstance.authors.all() diff --git a/djangocms_blog/urls.py b/djangocms_blog/urls.py index 41cf7a4..02ceb0b 100644 --- a/djangocms_blog/urls.py +++ b/djangocms_blog/urls.py @@ -1,10 +1,9 @@ # -*- coding: utf-8 -*- from django.conf.urls import patterns, url -from .views import (PostListView, PostDetailView, TaggedListView, - AuthorEntriesView, PostArchiveView, CategoryEntriesView) from .feeds import LatestEntriesFeed, TagFeed - +from .views import (AuthorEntriesView, CategoryEntriesView, PostArchiveView, PostDetailView, + PostListView, TaggedListView) urlpatterns = patterns( '', diff --git a/djangocms_blog/views.py b/djangocms_blog/views.py index fdecf5f..5751aba 100644 --- a/djangocms_blog/views.py +++ b/djangocms_blog/views.py @@ -3,11 +3,10 @@ from django.contrib.auth import get_user_model from django.core.urlresolvers import resolve from django.utils.timezone import now from django.utils.translation import get_language -from django.views.generic import ListView, DetailView +from django.views.generic import DetailView, ListView +from parler.views import TranslatableSlugMixin, ViewUrlMixin -from parler.views import ViewUrlMixin, TranslatableSlugMixin - -from .models import Post, BlogCategory, BLOG_CURRENT_POST_IDENTIFIER +from .models import BLOG_CURRENT_POST_IDENTIFIER, BlogCategory, Post from .settings import get_setting User = get_user_model() diff --git a/setup.cfg b/setup.cfg index f3c0451..d388d4d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,14 @@ +[flake8] +exclude = .git,*.egg-info,build,dist,.tox,djangocms_blog/migrations/*,djangocms_blog/south_migrations/* +ignore = E501 +max-line-length = 99 + +[metadata] +license-file = LICENSE + [wheel] universal = 1 -[flake8] -max-line-length = 100 -ignore = E501 -exclude = djangocms_blog/migrations/* \ No newline at end of file +[isort] +line_length = 99 +skip = migrations, south_migrations \ No newline at end of file diff --git a/setup.py b/setup.py index 1b62f97..5095967 100755 --- a/setup.py +++ b/setup.py @@ -15,9 +15,9 @@ version = djangocms_blog.__version__ if sys.argv[-1] == 'publish': os.system('python setup.py sdist upload') - print("You probably want to also tag the version now:") - print(" git tag -a %s -m 'version %s'" % (version, version)) - print(" git push --tags") + print('You probably want to also tag the version now:') + print(' git tag -a %s -m "version %s"' % (version, version)) + print(' git push --tags') sys.exit() readme = open('README.rst').read() @@ -50,7 +50,7 @@ setup( 'django-meta>=0.2', 'django-meta-mixin>=0.1.1', ], - license="BSD", + license='BSD', zip_safe=False, keywords='djangocms-blog, blog, django, wordpress, multilingual', test_suite='cms_helper.run', @@ -63,9 +63,10 @@ setup( 'Framework :: Django', 'Framework :: Django :: 1.6', 'Framework :: Django :: 1.7', - "Programming Language :: Python :: 2", + 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', ], diff --git a/tests/__init__.py b/tests/__init__.py index eae2eda..7df385f 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -22,6 +22,7 @@ from djangocms_blog.models import BlogCategory, Post User = get_user_model() + def _get_cat_pk(lang, name): return lambda: BlogCategory.objects.translated(lang, name=name).get().pk diff --git a/tests/test_menu.py b/tests/test_menu.py index 4e76c15..8f4b6ee 100644 --- a/tests/test_menu.py +++ b/tests/test_menu.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- import copy + from django.utils.translation import activate +from djangocms_blog.views import CategoryEntriesView, PostDetailView from menus.menu_pool import menu_pool from parler.utils.context import switch_language -from djangocms_blog.views import PostDetailView, CategoryEntriesView + from . import BaseTest diff --git a/tests/test_models.py b/tests/test_models.py index 20872d1..5cfd873 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- +from copy import deepcopy + +import parler from cms.api import add_plugin from cms.utils.copy_plugins import copy_plugins_to from cms.utils.plugins import downcast_plugins -from copy import deepcopy from django.contrib import admin from django.contrib.auth.models import AnonymousUser from django.contrib.messages.middleware import MessageMiddleware @@ -10,15 +12,13 @@ from django.contrib.sites.models import Site from django.core.urlresolvers import reverse from django.utils.timezone import now from django.utils.translation import get_language, override -import parler -from taggit.models import Tag - from djangocms_blog.models import Post from djangocms_blog.settings import get_setting +from taggit.models import Tag +from djangocms_helper.utils import CMS_30 from . import BaseTest -from djangocms_helper.utils import CMS_30 class AdminTest(BaseTest): @@ -199,7 +199,7 @@ class ModelsTest(BaseTest): self.assertEqual(len(Post.objects.available()), 1) # If post is published but publishing date is in the future - post2.date_published = now().replace(year=now().year+1, month=now().month, day=1) + post2.date_published = now().replace(year=now().year + 1, month=now().month, day=1) post2.publish = True post2.save() self.assertEqual(len(Post.objects.available()), 2) @@ -207,15 +207,15 @@ class ModelsTest(BaseTest): self.assertEqual(len(Post.objects.archived()), 0) # If post is published but end publishing date is in the past - post2.date_published = now().replace(year=now().year-2, month=now().month, day=1) - post2.date_published_end = now().replace(year=now().year-1, month=now().month, day=1) + post2.date_published = now().replace(year=now().year - 2, month=now().month, day=1) + post2.date_published_end = now().replace(year=now().year - 1, month=now().month, day=1) post2.save() self.assertEqual(len(Post.objects.available()), 2) self.assertEqual(len(Post.objects.published()), 1) self.assertEqual(len(Post.objects.archived()), 1) # counting with language fallback enabled - post = self._get_post(self.data['it'][0], post1, 'it') + self._get_post(self.data['it'][0], post1, 'it') self.assertEqual(len(Post.objects.filter_by_language('it')), 2) # No fallback @@ -264,7 +264,7 @@ class ModelsTest(BaseTest): def test_plugin_latest(self): post1 = self._get_post(self.data['en'][0]) - post2 = self._get_post(self.data['en'][1]) + self._get_post(self.data['en'][1]) post1.tags.add('tag 1') post1.save() request = self.get_page_request('/', AnonymousUser(), r'/en/blog/', edit=False) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index a5e6f11..5543ba7 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- import re + from cms.api import add_plugin from django.core.urlresolvers import reverse from django.template import RequestContext from django.utils.timezone import now +from djangocms_blog.models import BlogCategory from taggit.models import Tag from . import BaseTest -from djangocms_blog.models import BlogCategory class PluginTest(BaseTest): @@ -33,7 +34,6 @@ class PluginTest(BaseTest): self.assertTrue(rendered.find('
-1) self.assertTrue(rendered.find(post1.get_absolute_url()) > -1) - category_2 = BlogCategory.objects.create(name=u'category 2') category_2.set_current_language('it', initialize=True) category_2.name = u'categoria 2' diff --git a/tests/test_toolbar.py b/tests/test_toolbar.py index d493e8f..f29465c 100644 --- a/tests/test_toolbar.py +++ b/tests/test_toolbar.py @@ -3,7 +3,6 @@ from cms.toolbar.items import ModalItem from django.core.urlresolvers import reverse from djangocms_blog.models import BLOG_CURRENT_POST_IDENTIFIER - from . import BaseTest @@ -24,4 +23,3 @@ class ToolbarTest(BaseTest): self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_changelist'))), 1) self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_add'))), 1) self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_change', args=(post.pk,)))), 1) - diff --git a/tests/test_utils/__init__.py b/tests/test_utils/__init__.py index 82d1ac7..40a96af 100644 --- a/tests/test_utils/__init__.py +++ b/tests/test_utils/__init__.py @@ -1,2 +1 @@ # -*- coding: utf-8 -*- -from django.utils.translation import ugettext_lazy as _ \ No newline at end of file diff --git a/tests/test_utils/urls.py b/tests/test_utils/urls.py index ea19448..080855a 100644 --- a/tests/test_utils/urls.py +++ b/tests/test_utils/urls.py @@ -1,28 +1,28 @@ +# -*- coding: utf-8 -*- from cms.utils.conf import get_cms_setting from django.conf import settings -from django.conf.urls import patterns, include, url -from django.contrib import admin +from django.conf.urls import include, patterns, url from django.conf.urls.i18n import i18n_patterns - - +from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns admin.autodiscover() -urlpatterns = patterns('', - #(r'', include('django.contrib.staticfiles.urls')), +urlpatterns = patterns( + '', url(r'^media/(?P.*)$', 'django.views.static.serve', - {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), + {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), url(r'^media/cms/(?P.*)$', 'django.views.static.serve', - {'document_root': get_cms_setting('MEDIA_ROOT'), 'show_indexes': True}), + {'document_root': get_cms_setting('MEDIA_ROOT'), 'show_indexes': True}), url(r'^jsi18n/(?P\S+?)/$', 'django.views.i18n.javascript_catalog'), url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')), ) urlpatterns += staticfiles_urlpatterns() -urlpatterns += i18n_patterns('', +urlpatterns += i18n_patterns( + '', url(r'^admin/', include(admin.site.urls)), url(r'^blog/', include('djangocms_blog.urls', namespace='djangocms_blog')), url(r'^', include('cms.urls')), -) \ No newline at end of file +) diff --git a/tests/test_views.py b/tests/test_views.py index fb85bba..f5023c9 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,16 +1,15 @@ # -*- coding: utf-8 -*- from django.contrib.auth.models import AnonymousUser from django.http import Http404 -from django.utils.translation import activate from django.utils.timezone import now +from django.utils.translation import activate +from djangocms_blog.feeds import LatestEntriesFeed, TagFeed +from djangocms_blog.sitemaps import BlogSitemap +from djangocms_blog.views import (AuthorEntriesView, CategoryEntriesView, PostArchiveView, + PostDetailView, PostListView, TaggedListView) from parler.tests.utils import override_parler_settings from parler.utils.conf import add_default_language_settings from parler.utils.context import switch_language -from djangocms_blog.feeds import LatestEntriesFeed, TagFeed -from djangocms_blog.sitemaps import BlogSitemap -from djangocms_blog.views import (PostListView, PostDetailView, - PostArchiveView, CategoryEntriesView, - AuthorEntriesView, TaggedListView) from . import BaseTest @@ -68,7 +67,7 @@ class ViewTest(BaseTest): 1: ( {'code': 'en'}, {'code': 'it'}, - {'code': 'fr', 'hide_untranslated': True,}, + {'code': 'fr', 'hide_untranslated': True}, ), 'default': { 'fallback': 'en', @@ -82,7 +81,7 @@ class ViewTest(BaseTest): view_obj.request = request view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() - context = view_obj.get_context_data(object_list=view_obj.object_list) + view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(view_obj.get_queryset().count(), 2) PARLER_FALLBACK = add_default_language_settings(PARLER_FALLBACK) @@ -94,7 +93,7 @@ class ViewTest(BaseTest): view_obj.request = request view_obj.kwargs = {} view_obj.object_list = view_obj.get_queryset() - context = view_obj.get_context_data(object_list=view_obj.object_list) + view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(view_obj.get_queryset().count(), 0) def test_post_detail_view(self): @@ -147,7 +146,7 @@ class ViewTest(BaseTest): view_obj.object_list = qs context = view_obj.get_context_data(object_list=view_obj.object_list) self.assertEqual(context['archive_date'].date(), now().replace(year=now().year, month=now().month, day=1).date()) - + def test_category_entries_view(self): page1, page2 = self.get_pages() post1, post2 = self.get_posts() @@ -247,7 +246,7 @@ class ViewTest(BaseTest): feed = TagFeed() self.assertEqual(list(feed.items('tag-2')), [post1]) - + def test_sitemap(self): post1, post2 = self.get_posts() post1.tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4') @@ -256,7 +255,7 @@ class ViewTest(BaseTest): post2.publish = True post2.save() post1.set_current_language('en') - + sitemap = BlogSitemap() self.assertEqual(sitemap.items().count(), 2) for item in sitemap.items(): diff --git a/tox.ini b/tox.ini index 148cb72..2390c82 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{26}-django{16}-cms{30,31,32},py{27,33,34}-django{16,17}-cms{30,31,32} +envlist = py{26}-django{16}-cms{30,31,32},py{27,33,34}-django{16,17}-cms{30,31,32},isort,pep8 [testenv] commands = {env:COMMAND:python} setup.py test @@ -12,3 +12,11 @@ deps = cms32: https://github.com/divio/django-cms/archive/develop.zip py26: unittest2 -r{toxinidir}/requirements-test.txt + +[testenv:isort] +deps = isort +commands = isort -c -rc djangocms_blog tests + +[testenv:pep8] +deps = flake8 +commands = flake8