diff --git a/.travis.yml b/.travis.yml index 8310e44..8bd20d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ branches: - master env: + - TOXENV=py27-lint - TOXENV=py27-django18 - TOXENV=py27-django19 - TOXENV=py34-django18 diff --git a/categories/__init__.py b/categories/__init__.py index df598df..be4f387 100644 --- a/categories/__init__.py +++ b/categories/__init__.py @@ -21,6 +21,7 @@ __version__ = get_version() default_app_config = 'categories.apps.CategoriesConfig' + def register(): from categories import settings from categories.registration import (_process_registry, registry) diff --git a/categories/admin.py b/categories/admin.py index 26b8949..1789150 100644 --- a/categories/admin.py +++ b/categories/admin.py @@ -20,8 +20,8 @@ class NullTreeNodeChoiceField(forms.ModelChoiceField): Creates labels which represent the tree level of each node when generating option labels. """ - return '%s %s' % (self.level_indicator * getattr( - obj, obj._mptt_meta.level_attr), obj) + return '%s %s' % (self.level_indicator * getattr(obj, obj._mptt_meta.level_attr), obj) + if RELATION_MODELS: from .models import CategoryRelation @@ -50,7 +50,7 @@ class CategoryAdmin(CategoryBaseAdmin): }), (_('Meta Data'), { 'fields': ('alternate_title', 'alternate_url', 'description', - 'meta_keywords', 'meta_extra'), + 'meta_keywords', 'meta_extra'), 'classes': ('collapse',), }), (_('Advanced'), { diff --git a/categories/base.py b/categories/base.py index ff16f8e..7305cf8 100644 --- a/categories/base.py +++ b/categories/base.py @@ -35,7 +35,8 @@ class CategoryBase(MPTTModel): This base model includes the absolute bare bones fields and methods. One could simply subclass this model and do nothing else and it should work. """ - parent = TreeForeignKey('self', + parent = TreeForeignKey( + 'self', blank=True, null=True, related_name='children', @@ -99,9 +100,7 @@ class CategoryBaseAdminForm(forms.ModelForm): kwargs['parent__isnull'] = True else: kwargs['parent__pk'] = int(self.cleaned_data['parent'].id) - this_level_slugs = [c['slug'] for c in opts.model.objects.filter( - **kwargs).values('id', 'slug' - ) if c['id'] != self.instance.id] + this_level_slugs = [c['slug'] for c in opts.model.objects.filter(**kwargs).values('id', 'slug') if c['id'] != self.instance.id] if self.cleaned_data['slug'] in this_level_slugs: raise forms.ValidationError(_('The slug must be unique among ' 'the items at its level.')) diff --git a/categories/editor/models.py b/categories/editor/models.py index 8a93c30..3542496 100644 --- a/categories/editor/models.py +++ b/categories/editor/models.py @@ -1 +1 @@ -# Placeholder for Django \ No newline at end of file +# Placeholder for Django diff --git a/categories/editor/settings.py b/categories/editor/settings.py index 399142b..af293e5 100644 --- a/categories/editor/settings.py +++ b/categories/editor/settings.py @@ -4,7 +4,7 @@ import django DJANGO10_COMPAT = django.VERSION[0] < 1 or (django.VERSION[0] == 1 and django.VERSION[1] < 1) STATIC_URL = getattr(settings, 'STATIC_URL', settings.MEDIA_URL) -if STATIC_URL == None: +if STATIC_URL is None: STATIC_URL = settings.MEDIA_URL MEDIA_PATH = getattr(settings, 'EDITOR_MEDIA_PATH', '%seditor/' % STATIC_URL) diff --git a/categories/editor/templatetags/admin_tree_list_tags.py b/categories/editor/templatetags/admin_tree_list_tags.py index efd29f3..0e9a245 100644 --- a/categories/editor/templatetags/admin_tree_list_tags.py +++ b/categories/editor/templatetags/admin_tree_list_tags.py @@ -3,9 +3,9 @@ from django.db import models from django.template import Library from django.contrib.admin.templatetags.admin_list import result_headers, _boolean_icon try: - from django.contrib.admin.utils import lookup_field, display_for_field, label_for_field + from django.contrib.admin.utils import lookup_field, display_for_field except ImportError: - from categories.editor.utils import lookup_field, display_for_field, label_for_field + from categories.editor.utils import lookup_field, display_for_field from django.core.exceptions import ObjectDoesNotExist from django.utils.encoding import smart_text, force_text from django.utils.html import escape, conditional_escape @@ -99,10 +99,12 @@ def items_for_tree_result(cl, result, form): result_id = repr(force_text(value))[1:] first = False if django.VERSION[1] < 4: - yield mark_safe('<%s%s>%s%s%s>' % \ + yield mark_safe( + '<%s%s>%s%s%s>' % (table_tag, row_class, checkbox_value, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), conditional_escape(result_repr), table_tag)) else: - yield mark_safe('<%s%s>%s%s>' % \ + yield mark_safe( + '<%s%s>%s%s>' % (table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), conditional_escape(result_repr), table_tag)) else: @@ -151,9 +153,11 @@ def result_tree_list(cl): Displays the headers and data list together """ import django - result = {'cl': cl, - 'result_headers': list(result_headers(cl)), - 'results': list(tree_results(cl))} + result = { + 'cl': cl, + 'result_headers': list(result_headers(cl)), + 'results': list(tree_results(cl)) + } if django.VERSION[1] > 2: from django.contrib.admin.templatetags.admin_list import result_hidden_fields result['result_hidden_fields'] = list(result_hidden_fields(cl)) diff --git a/categories/editor/tree_editor.py b/categories/editor/tree_editor.py index 821f6a6..a450977 100644 --- a/categories/editor/tree_editor.py +++ b/categories/editor/tree_editor.py @@ -38,8 +38,7 @@ class TreeEditorQuerySet(QuerySet): # will already be in include_pages when they are checked, thus not # trigger additional queries. for p in super(TreeEditorQuerySet, self.order_by('rght')).iterator(): - if p.parent_id and p.parent_id not in include_pages and \ - p.id not in include_pages: + if p.parent_id and p.parent_id not in include_pages and p.id not in include_pages: ancestor_id_list = p.get_ancestors().values_list('id', flat=True) include_pages.update(ancestor_id_list) @@ -145,12 +144,14 @@ class TreeEditor(admin.ModelAdmin): try: if django.VERSION[1] < 4: - params = (request, self.model, list_display, + params = ( + request, self.model, list_display, self.list_display_links, self.list_filter, self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self) else: - params = (request, self.model, list_display, + params = ( + request, self.model, list_display, self.list_display_links, self.list_filter, self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_max_show_all, @@ -244,8 +245,7 @@ class TreeEditor(admin.ModelAdmin): if django.VERSION[1] < 4: context['root_path'] = self.admin_site.root_path else: - selection_note_all = ungettext('%(total_count)s selected', - 'All %(total_count)s selected', cl.result_count) + selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', cl.result_count) context.update({ 'module_name': force_text(opts.verbose_name_plural), diff --git a/categories/editor/utils.py b/categories/editor/utils.py index 6664c65..c4c8ba4 100644 --- a/categories/editor/utils.py +++ b/categories/editor/utils.py @@ -24,8 +24,7 @@ def lookup_field(name, obj, model_admin=None): if isinstance(name, collections.Callable): attr = name value = attr(obj) - elif (model_admin is not None and hasattr(model_admin, name) and - not name == '__str__' and not name == '__unicode__'): + elif (model_admin is not None and hasattr(model_admin, name) and not name == '__str__' and not name == '__unicode__'): attr = getattr(model_admin, name) value = attr(obj) else: diff --git a/categories/genericcollection.py b/categories/genericcollection.py index 88eb416..daa03dc 100644 --- a/categories/genericcollection.py +++ b/categories/genericcollection.py @@ -1,6 +1,7 @@ from django.contrib import admin from django.contrib.contenttypes.models import ContentType + class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): ct_field = "content_type" ct_fk_field = "object_id" @@ -17,6 +18,7 @@ class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): result.ct_fk_field = self.ct_fk_field return result + class GenericCollectionTabularInline(GenericCollectionInlineModelAdmin): template = 'admin/edit_inline/gen_coll_tabular.html' diff --git a/categories/management/commands/__init__.py b/categories/management/commands/__init__.py index 0721d7c..6b58348 100644 --- a/categories/management/commands/__init__.py +++ b/categories/management/commands/__init__.py @@ -1,7 +1,7 @@ try: - from south.db import db - from django.db.models.signals import post_syncdb - from categories.migration import migrate_app + from south.db import db # noqa + from django.db.models.signals import post_syncdb # noqa + from categories.migration import migrate_app # noqa post_syncdb.connect(migrate_app) except ImportError: diff --git a/categories/management/commands/add_category_fields.py b/categories/management/commands/add_category_fields.py index 2ef3070..53daf58 100644 --- a/categories/management/commands/add_category_fields.py +++ b/categories/management/commands/add_category_fields.py @@ -14,11 +14,6 @@ class Command(BaseCommand): """ Alter the tables """ - from django.core.exceptions import ImproperlyConfigured - try: - from south.db import db - except ImportError: - raise ImproperlyConfigured("South must be installed for this command to work") from categories.migration import migrate_app from categories.settings import MODEL_REGISTRY diff --git a/categories/management/commands/drop_category_field.py b/categories/management/commands/drop_category_field.py index ed9e710..c9adddb 100644 --- a/categories/management/commands/drop_category_field.py +++ b/categories/management/commands/drop_category_field.py @@ -14,10 +14,6 @@ class Command(BaseCommand): """ Alter the tables """ - try: - from south.db import db - except ImportError: - raise ImproperlyConfigured("South must be installed for this command to work") from categories.migration import drop_field if len(args) != 3: diff --git a/categories/management/commands/import_categories.py b/categories/management/commands/import_categories.py index fe75b23..a899e50 100644 --- a/categories/management/commands/import_categories.py +++ b/categories/management/commands/import_categories.py @@ -35,7 +35,7 @@ class Command(BaseCommand): cat = Category( name=string.strip(), slug=slugify(SLUG_TRANSLITERATOR(string.strip()))[:49], - #parent=parent, + # arent=parent, order=order ) cat._tree_manager.insert_node(cat, parent, 'last-child', True) diff --git a/categories/models.py b/categories/models.py index 1921cfe..a10675c 100644 --- a/categories/models.py +++ b/categories/models.py @@ -11,8 +11,7 @@ from django.core.files.storage import get_storage_class from django.utils.translation import ugettext_lazy as _ -from .settings import (RELATION_MODELS, RELATIONS, THUMBNAIL_UPLOAD_PATH, - THUMBNAIL_STORAGE) +from .settings import (RELATION_MODELS, RELATIONS, THUMBNAIL_UPLOAD_PATH, THUMBNAIL_STORAGE) from .base import CategoryBase @@ -133,7 +132,8 @@ class CategoryRelation(models.Model): ContentType, limit_choices_to=CATEGORY_RELATION_LIMITS, verbose_name=_('content type')) object_id = models.PositiveIntegerField(verbose_name=_('object id')) content_object = GenericForeignKey('content_type', 'object_id') - relation_type = models.CharField(verbose_name=_('relation type'), + relation_type = models.CharField( + verbose_name=_('relation type'), max_length=200, blank=True, null=True, @@ -145,7 +145,7 @@ class CategoryRelation(models.Model): return "CategoryRelation" try: - from south.db import db # South is required for migrating. Need to check for it + from south.db import db # noqa, South is required for migrating. Need to check for it from django.db.models.signals import post_syncdb from categories.migration import migrate_app post_syncdb.connect(migrate_app) diff --git a/categories/registration.py b/categories/registration.py index ad307cd..5eb8105 100644 --- a/categories/registration.py +++ b/categories/registration.py @@ -35,8 +35,7 @@ class Registry(object): if isinstance(field_definitions, str): field_definitions = [field_definitions] elif not isinstance(field_definitions, collections.Iterable): - raise ImproperlyConfigured(_('Field configuration for %(app)s should ' - 'be a string or iterable') % {'app': app}) + raise ImproperlyConfigured(_('Field configuration for %(app)s should be a string or iterable') % {'app': app}) if field_type not in ('ForeignKey', 'ManyToManyField'): raise ImproperlyConfigured(_('`field_type` must be either `"ForeignKey"` or `"ManyToManyField"`.')) @@ -73,8 +72,8 @@ class Registry(object): continue extra_params.update(fld) else: - raise ImproperlyConfigured(_("%(settings)s doesn't recognize the " - "value of %(app)s.%(model)s") % { + raise ImproperlyConfigured( + _("%(settings)s doesn't recognize the value of %(app)s.%(model)s") % { 'settings': 'CATEGORY_SETTINGS', 'app': app, 'model': model_name}) diff --git a/categories/settings.py b/categories/settings.py index b3d8d51..bf77d66 100644 --- a/categories/settings.py +++ b/categories/settings.py @@ -5,7 +5,6 @@ import collections DEFAULT_SETTINGS = { 'ALLOW_SLUG_CHANGE': False, - 'RELATION_MODELS': [], 'M2M_REGISTRY': {}, 'FK_REGISTRY': {}, 'THUMBNAIL_UPLOAD_PATH': 'uploads/categories/thumbnails', @@ -37,7 +36,7 @@ else: # Add all the keys/values to the module's namespace globals().update(DEFAULT_SETTINGS) -RELATIONS = [Q(app_label=al, model=m) for al, m in [x.split('.') for x in RELATION_MODELS]] +RELATIONS = [Q(app_label=al, model=m) for al, m in [x.split('.') for x in DEFAULT_SETTINGS['RELATION_MODELS']]] # The field registry keeps track of the individual fields created. # {'app.model.field': Field(**extra_params)} diff --git a/categories/templatetags/category_tags.py b/categories/templatetags/category_tags.py index 1617b26..1db869f 100644 --- a/categories/templatetags/category_tags.py +++ b/categories/templatetags/category_tags.py @@ -54,8 +54,7 @@ def get_category(category_string, model=Category): if len(cat_list) == 0: return None try: - categories = model_class.objects.filter(name=cat_list[-1], - level=len(cat_list) - 1) + categories = model_class.objects.filter(name=cat_list[-1], level=len(cat_list) - 1) if len(cat_list) == 1 and len(categories) > 1: return None # If there is only one, use it. If there is more than one, check @@ -265,8 +264,7 @@ def get_top_level_categories(parser, token): return TopLevelCategoriesNode(varname, model) -def get_latest_objects_by_category(category, app_label, model_name, set_name, - date_field='pub_date', num=15): +def get_latest_objects_by_category(category, app_label, model_name, set_name, date_field='pub_date', num=15): m = apps.get_model(app_label, model_name) if not isinstance(category, CategoryBase): category = Category.objects.get(slug=str(category)) @@ -304,8 +302,7 @@ class LatestObjectsNode(Node): date_field = resolve(self.date_field, context) num = resolve(self.num, context) - result = get_latest_objects_by_category(category, app_label, model_name, - set_name, date_field, num) + result = get_latest_objects_by_category(category, app_label, model_name, set_name, date_field, num) context[self.var_name] = result return '' @@ -339,8 +336,7 @@ def do_get_latest_objects_by_category(parser, token): num = FilterExpression(bits[6], parser) else: num = FilterExpression(None, parser) - return LatestObjectsNode(var_name, category, app_label, model_name, set_name, - date_field, num) + return LatestObjectsNode(var_name, category, app_label, model_name, set_name, date_field, num) register.tag("get_latest_objects_by_category", do_get_latest_objects_by_category) @@ -369,8 +365,7 @@ def tree_queryset(value): # will already be in include_pages when they are checked, thus not # trigger additional queries. for p in qs2.order_by('rght').iterator(): - if p.parent_id and p.parent_id not in include_pages and \ - p.id not in include_pages: + if p.parent_id and p.parent_id not in include_pages and p.id not in include_pages: ancestor_id_list = p.get_ancestors().values_list('id', flat=True) include_pages.update(ancestor_id_list) diff --git a/categories/tests/test_category_import.py b/categories/tests/test_category_import.py index 8384add..4ecde46 100644 --- a/categories/tests/test_category_import.py +++ b/categories/tests/test_category_import.py @@ -9,8 +9,6 @@ from categories.models import Category from categories.management.commands.import_categories import Command from django.core.management.base import CommandError -from categories.registration import _process_registry, registry - @override_settings(INSTALLED_APPS=(app for app in settings.INSTALLED_APPS if app != 'django.contrib.flatpages')) class CategoryImportTest(TestCase): diff --git a/categories/tests/test_registration.py b/categories/tests/test_registration.py index c4259d0..842baec 100644 --- a/categories/tests/test_registration.py +++ b/categories/tests/test_registration.py @@ -54,5 +54,3 @@ class Categorym2mTest(TestCase): _process_registry(M2M_REGISTRY, registry.register_m2m) from django.contrib.flatpages.models import FlatPage self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) - - diff --git a/categories/tests/test_templatetags.py b/categories/tests/test_templatetags.py index 526157f..f099715 100644 --- a/categories/tests/test_templatetags.py +++ b/categories/tests/test_templatetags.py @@ -35,27 +35,31 @@ class CategoryTagsTest(TestCase): # display_drilldown_as_ul expected_resp = '
' - resp = self.render_template('{% load category_tags %}' + resp = self.render_template( + '{% load category_tags %}' '{% display_drilldown_as_ul "/World/Worldbeat" "categories.category" %}') resp = re.sub(r'\n$', "", resp) self.assertEqual(resp, expected_resp) # breadcrumbs expected_resp = 'World > Worldbeat' - resp = self.render_template('{% load category_tags %}' + resp = self.render_template( + '{% load category_tags %}' '{% breadcrumbs "/World/Worldbeat" " > " "categories.category" %}') self.assertEqual(resp, expected_resp) # get_top_level_categories expected_resp = 'Avant-garde|Blues|Country|Easy listening|Electronic|Hip hop/Rap music|Jazz|Latin|Modern folk|Pop|Reggae|Rhythm and blues|Rock|World|' - resp = self.render_template('{% load category_tags %}' + resp = self.render_template( + '{% load category_tags %}' '{% get_top_level_categories using "categories.category" as varname %}' '{% for item in varname %}{{ item }}|{% endfor %}') self.assertEqual(resp, expected_resp) # get_category_drilldown expected_resp = "World|World > Worldbeat|" - resp = self.render_template('{% load category_tags %}' + resp = self.render_template( + '{% load category_tags %}' '{% get_category_drilldown "/World" using "categories.category" as var %}' '{% for item in var %}{{ item }}|{% endfor %}') self.assertEqual(resp, expected_resp) @@ -63,7 +67,8 @@ class CategoryTagsTest(TestCase): # recursetree expected_resp = '