diff --git a/categories/__init__.py b/categories/__init__.py
index 035da6a..df598df 100644
--- a/categories/__init__.py
+++ b/categories/__init__.py
@@ -29,4 +29,4 @@ def register():
try:
register()
except Exception as e:
- print e
+ print(e)
diff --git a/categories/admin.py b/categories/admin.py
index c61f26f..26b8949 100644
--- a/categories/admin.py
+++ b/categories/admin.py
@@ -11,7 +11,7 @@ from .settings import MODEL_REGISTRY
class NullTreeNodeChoiceField(forms.ModelChoiceField):
"""A ModelChoiceField for tree nodes."""
- def __init__(self, level_indicator=u'---', *args, **kwargs):
+ def __init__(self, level_indicator='---', *args, **kwargs):
self.level_indicator = level_indicator
super(NullTreeNodeChoiceField, self).__init__(*args, **kwargs)
@@ -20,7 +20,7 @@ class NullTreeNodeChoiceField(forms.ModelChoiceField):
Creates labels which represent the tree level of each node when
generating option labels.
"""
- return u'%s %s' % (self.level_indicator * getattr(
+ return '%s %s' % (self.level_indicator * getattr(
obj, obj._mptt_meta.level_attr), obj)
if RELATION_MODELS:
from .models import CategoryRelation
@@ -68,8 +68,8 @@ class CategoryAdmin(CategoryBaseAdmin):
if REGISTER_ADMIN:
admin.site.register(Category, CategoryAdmin)
-for model, modeladmin in admin.site._registry.items():
- if model in MODEL_REGISTRY.values() and modeladmin.fieldsets:
+for model, modeladmin in list(admin.site._registry.items()):
+ if model in list(MODEL_REGISTRY.values()) and modeladmin.fieldsets:
fieldsets = getattr(modeladmin, 'fieldsets', ())
fields = [cat.split('.')[2] for cat in MODEL_REGISTRY if MODEL_REGISTRY[cat] == model]
# check each field to see if already defined
diff --git a/categories/apps.py b/categories/apps.py
index daab55b..02e70e0 100644
--- a/categories/apps.py
+++ b/categories/apps.py
@@ -26,12 +26,12 @@ def handle_class_prepared(sender, **kwargs):
sender_app = sender._meta.app_label
sender_name = sender._meta.model_name
- for key, val in FK_REGISTRY.items():
+ for key, val in list(FK_REGISTRY.items()):
app_name, model_name = key.split('.')
if app_name == sender_app and sender_name == model_name:
registry.register_model(app_name, sender, 'ForeignKey', val)
- for key, val in M2M_REGISTRY.items():
+ for key, val in list(M2M_REGISTRY.items()):
app_name, model_name = key.split('.')
if app_name == sender_app and sender_name == model_name:
registry.register_model(app_name, sender, 'ManyToManyField', val)
diff --git a/categories/editor/templatetags/admin_tree_list_tags.py b/categories/editor/templatetags/admin_tree_list_tags.py
index a019b2e..a9f4db5 100644
--- a/categories/editor/templatetags/admin_tree_list_tags.py
+++ b/categories/editor/templatetags/admin_tree_list_tags.py
@@ -91,10 +91,10 @@ def items_for_tree_result(cl, result, form):
result_id = repr(force_unicode(value))[1:]
first = False
if django.VERSION[1] < 4:
- yield mark_safe(u'<%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(u'<%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:
@@ -106,9 +106,9 @@ def items_for_tree_result(cl, result, form):
result_repr = mark_safe(force_unicode(bf.errors) + force_unicode(bf))
else:
result_repr = conditional_escape(result_repr)
- yield mark_safe(u'
%s | ' % (row_class, result_repr))
+ yield mark_safe('%s | ' % (row_class, result_repr))
if form and not form[cl.model._meta.pk.name].is_hidden:
- yield mark_safe(u'%s | ' % force_unicode(form[cl.model._meta.pk.name]))
+ yield mark_safe('%s | ' % force_unicode(form[cl.model._meta.pk.name]))
class TreeList(list):
diff --git a/categories/editor/tree_editor.py b/categories/editor/tree_editor.py
index 7df5732..c2769da 100644
--- a/categories/editor/tree_editor.py
+++ b/categories/editor/tree_editor.py
@@ -9,7 +9,7 @@ from django.shortcuts import render_to_response
import django
-import settings
+from . import settings
class TreeEditorQuerySet(QuerySet):
@@ -162,7 +162,7 @@ class TreeEditor(admin.ModelAdmin):
# parameter via the query string. If wacky parameters were given and
# the 'invalid=1' parameter was already in the query string, something
# is screwed up with the database, so display an error page.
- if ERROR_FLAG in request.GET.keys():
+ if ERROR_FLAG in list(request.GET.keys()):
return render_to_response(
'admin/invalid_setup.html', {'title': _('Database error')})
return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')
diff --git a/categories/editor/utils.py b/categories/editor/utils.py
index b8d7e78..11871d1 100644
--- a/categories/editor/utils.py
+++ b/categories/editor/utils.py
@@ -11,6 +11,7 @@ from django.utils.translation import get_date_formats
from django.utils.text import capfirst
from django.utils import dateformat
from django.utils.html import escape
+import collections
def lookup_field(name, obj, model_admin=None):
@@ -20,7 +21,7 @@ def lookup_field(name, obj, model_admin=None):
except models.FieldDoesNotExist:
# For non-field values, the value is either a method, property or
# returned via a callable.
- if callable(name):
+ if isinstance(name, collections.Callable):
attr = name
value = attr(obj)
elif (model_admin is not None and hasattr(model_admin, name) and
@@ -29,7 +30,7 @@ def lookup_field(name, obj, model_admin=None):
value = attr(obj)
else:
attr = getattr(obj, name)
- if callable(attr):
+ if isinstance(attr, collections.Callable):
value = attr()
else:
value = attr
@@ -57,12 +58,12 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
except models.FieldDoesNotExist:
if name == "__unicode__":
label = force_unicode(model._meta.verbose_name)
- attr = unicode
+ attr = str
elif name == "__str__":
label = smart_str(model._meta.verbose_name)
attr = str
else:
- if callable(name):
+ if isinstance(name, collections.Callable):
attr = name
elif model_admin is not None and hasattr(model_admin, name):
attr = getattr(model_admin, name)
@@ -76,7 +77,7 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
if hasattr(attr, "short_description"):
label = attr.short_description
- elif callable(attr):
+ elif isinstance(attr, collections.Callable):
if attr.__name__ == "":
label = "--"
else:
diff --git a/categories/management/commands/drop_category_field.py b/categories/management/commands/drop_category_field.py
index 3163e01..ed9e710 100644
--- a/categories/management/commands/drop_category_field.py
+++ b/categories/management/commands/drop_category_field.py
@@ -21,6 +21,6 @@ class Command(BaseCommand):
from categories.migration import drop_field
if len(args) != 3:
- print "You must specify an Application name, a Model name and a Field name"
+ print("You must specify an Application name, a Model name and a Field name")
drop_field(*args)
diff --git a/categories/management/commands/import_categories.py b/categories/management/commands/import_categories.py
index f0f164e..5599d53 100644
--- a/categories/management/commands/import_categories.py
+++ b/categories/management/commands/import_categories.py
@@ -81,7 +81,7 @@ class Command(BaseCommand):
for file_path in file_paths:
if not os.path.isfile(file_path):
- print "File %s not found." % file_path
+ print("File %s not found." % file_path)
continue
f = file(file_path, 'r')
data = f.readlines()
diff --git a/categories/migration.py b/categories/migration.py
index 77b061b..57b2788 100644
--- a/categories/migration.py
+++ b/categories/migration.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
+
from django.db import connection, transaction
from django.apps import apps
@@ -47,7 +47,7 @@ def migrate_app(sender, *args, **kwargs):
app_name = app_config.label
- fields = [fld for fld in registry._field_registry.keys() if fld.startswith(app_name)]
+ fields = [fld for fld in list(registry._field_registry.keys()) if fld.startswith(app_name)]
sid = transaction.savepoint()
for fld in fields:
diff --git a/categories/migrations/0001_initial.py b/categories/migrations/0001_initial.py
index 207a589..e4e1c59 100644
--- a/categories/migrations/0001_initial.py
+++ b/categories/migrations/0001_initial.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
+
from django.db import models, migrations
import django.core.files.storage
diff --git a/categories/models.py b/categories/models.py
index 7383195..12dfa92 100644
--- a/categories/models.py
+++ b/categories/models.py
@@ -2,6 +2,7 @@ from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import force_unicode
from django.contrib.contenttypes.models import ContentType
+from functools import reduce
try:
from django.contrib.contenttypes.fields import GenericForeignKey
except ImportError:
@@ -141,7 +142,7 @@ class CategoryRelation(models.Model):
objects = CategoryRelationManager()
def __unicode__(self):
- return u"CategoryRelation"
+ return "CategoryRelation"
try:
from south.db import db # South is required for migrating. Need to check for it
diff --git a/categories/registration.py b/categories/registration.py
index 6631f70..61cc1d8 100644
--- a/categories/registration.py
+++ b/categories/registration.py
@@ -2,7 +2,7 @@
These functions handle the adding of fields to other models
"""
from django.db.models import FieldDoesNotExist, ForeignKey, ManyToManyField
-import fields
+from . import fields
# from settings import self._field_registry, self._model_registry
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ImproperlyConfigured
@@ -32,7 +32,7 @@ class Registry(object):
app_label = app
- if isinstance(field_definitions, basestring):
+ if isinstance(field_definitions, str):
field_definitions = [field_definitions]
elif not isinstance(field_definitions, collections.Iterable):
raise ImproperlyConfigured(_('Field configuration for %(app)s should '
@@ -64,7 +64,7 @@ class Registry(object):
extra_params = {'to': 'categories.Category', 'blank': True}
if field_type != 'ManyToManyField':
extra_params['null'] = True
- if isinstance(fld, basestring):
+ if isinstance(fld, str):
field_name = fld
elif isinstance(fld, dict):
if 'name' in fld:
@@ -121,13 +121,13 @@ def _process_registry(registry, call_func):
from django.core.exceptions import ImproperlyConfigured
from django.db.models.loading import get_model
- for key, value in registry.items():
+ for key, value in list(registry.items()):
model = get_model(*key.split('.'))
if model is None:
raise ImproperlyConfigured(_('%(key)s is not a model') % {'key': key})
if isinstance(value, (tuple, list)):
for item in value:
- if isinstance(item, basestring):
+ if isinstance(item, str):
call_func(model, item)
elif isinstance(item, dict):
field_name = item.pop('name')
@@ -135,7 +135,7 @@ def _process_registry(registry, call_func):
else:
raise ImproperlyConfigured(_("%(settings)s doesn't recognize the value of %(key)s") %
{'settings': 'CATEGORY_SETTINGS', 'key': key})
- elif isinstance(value, basestring):
+ elif isinstance(value, str):
call_func(model, value)
elif isinstance(value, dict):
field_name = value.pop('name')
diff --git a/categories/settings.py b/categories/settings.py
index 2d1589d..b3d8d51 100644
--- a/categories/settings.py
+++ b/categories/settings.py
@@ -1,6 +1,7 @@
from django.conf import settings
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
+import collections
DEFAULT_SETTINGS = {
'ALLOW_SLUG_CHANGE': False,
@@ -18,9 +19,9 @@ DEFAULT_SETTINGS = {
DEFAULT_SETTINGS.update(getattr(settings, 'CATEGORIES_SETTINGS', {}))
if DEFAULT_SETTINGS['SLUG_TRANSLITERATOR']:
- if callable(DEFAULT_SETTINGS['SLUG_TRANSLITERATOR']):
+ if isinstance(DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'], collections.Callable):
pass
- elif isinstance(DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'], basestring):
+ elif isinstance(DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'], str):
from django.utils.importlib import import_module
bits = DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'].split(".")
module = import_module(".".join(bits[:-1]))
diff --git a/categories/south_migration.py b/categories/south_migration.py
index 431cbe0..9ce9bcf 100644
--- a/categories/south_migration.py
+++ b/categories/south_migration.py
@@ -11,22 +11,22 @@ def migrate_app(sender, app, created_models=None, verbosity=False, *args, **kwar
from .models import Category
from .registration import registry
import sys
- import StringIO
+ import io
org_stderror = sys.stderr
- sys.stderr = StringIO.StringIO() # south will print out errors to stderr
+ sys.stderr = io.StringIO() # south will print out errors to stderr
try:
from south.db import db
except ImportError:
raise ImproperlyConfigured(_('%(dependency)s must be installed for this command to work') %
{'dependency': 'South'})
# pull the information from the registry
- if isinstance(app, basestring):
+ if isinstance(app, str):
app_name = app
else:
app_name = app.__name__.split('.')[-2]
- fields = [fld for fld in registry._field_registry.keys() if fld.startswith(app_name)]
+ fields = [fld for fld in list(registry._field_registry.keys()) if fld.startswith(app_name)]
# call the south commands to add the fields/tables
for fld in fields:
app_name, model_name, field_name = fld.split('.')
@@ -43,14 +43,14 @@ def migrate_app(sender, app, created_models=None, verbosity=False, *args, **kwar
db.add_column(table_name, field_name, registry._field_registry[fld], keep_default=False)
db.commit_transaction()
if verbosity:
- print (_('Added ForeignKey %(field_name)s to %(model_name)s') %
- {'field_name': field_name, 'model_name': model_name})
- except DatabaseError, e:
+ print((_('Added ForeignKey %(field_name)s to %(model_name)s') %
+ {'field_name': field_name, 'model_name': model_name}))
+ except DatabaseError as e:
db.rollback_transaction()
if "already exists" in str(e):
if verbosity > 1:
- print (_('ForeignKey %(field_name)s to %(model_name)s already exists') %
- {'field_name': field_name, 'model_name': model_name})
+ print((_('ForeignKey %(field_name)s to %(model_name)s already exists') %
+ {'field_name': field_name, 'model_name': model_name}))
else:
sys.stderr = org_stderror
raise e
@@ -66,14 +66,14 @@ def migrate_app(sender, app, created_models=None, verbosity=False, *args, **kwar
db.create_unique(table_name, ['%s_id' % model_name, 'category_id'])
db.commit_transaction()
if verbosity:
- print (_('Added Many2Many table between %(model_name)s and %(category_table)s') %
- {'model_name': model_name, 'category_table': 'category'})
- except DatabaseError, e:
+ print((_('Added Many2Many table between %(model_name)s and %(category_table)s') %
+ {'model_name': model_name, 'category_table': 'category'}))
+ except DatabaseError as e:
db.rollback_transaction()
if "already exists" in str(e):
if verbosity > 1:
- print (_('Many2Many table between %(model_name)s and %(category_table)s already exists') %
- {'model_name': model_name, 'category_table': 'category'})
+ print((_('Many2Many table between %(model_name)s and %(category_table)s already exists') %
+ {'model_name': model_name, 'category_table': 'category'}))
else:
sys.stderr = org_stderror
raise e
@@ -98,23 +98,23 @@ def drop_field(app_name, model_name, field_name):
fld = '%s.%s.%s' % (app_name, model_name, field_name)
if isinstance(registry._field_registry[fld], CategoryFKField):
- print (_('Dropping ForeignKey %(field_name)s from %(model_name)s') %
- {'field_name': field_name, 'model_name': model_name})
+ print((_('Dropping ForeignKey %(field_name)s from %(model_name)s') %
+ {'field_name': field_name, 'model_name': model_name}))
try:
db.start_transaction()
table_name = mdl._meta.db_table
db.delete_column(table_name, field_name)
db.commit_transaction()
- except DatabaseError, e:
+ except DatabaseError as e:
db.rollback_transaction()
raise e
elif isinstance(registry._field_registry[fld], CategoryM2MField):
- print (_('Dropping Many2Many table between %(model_name)s and %(category_table)s') %
- {'model_name': model_name, 'category_table': 'category'})
+ print((_('Dropping Many2Many table between %(model_name)s and %(category_table)s') %
+ {'model_name': model_name, 'category_table': 'category'}))
try:
db.start_transaction()
db.delete_table(table_name, cascade=False)
db.commit_transaction()
- except DatabaseError, e:
+ except DatabaseError as e:
db.rollback_transaction()
raise e
diff --git a/categories/templatetags/category_tags.py b/categories/templatetags/category_tags.py
index f21a42a..8e75f9a 100644
--- a/categories/templatetags/category_tags.py
+++ b/categories/templatetags/category_tags.py
@@ -30,7 +30,7 @@ def get_cat_model(model):
Return a class from a string or class
"""
try:
- if isinstance(model, basestring):
+ if isinstance(model, str):
model_class = get_model(*model.split("."))
elif issubclass(model, CategoryBase):
model_class = model
@@ -119,13 +119,13 @@ def get_category_drilldown(parser, token):
'{%% %(tagname)s category_obj as varname %%}.'
if len(bits) == 4:
if bits[2] != 'as':
- raise template.TemplateSyntaxError, error_str % {'tagname': bits[0]}
+ raise template.TemplateSyntaxError(error_str % {'tagname': bits[0]})
if bits[2] == 'as':
varname = bits[3].strip("'\"")
model = "categories.category"
if len(bits) == 6:
if bits[2] not in ('using', 'as') or bits[4] not in ('using', 'as'):
- raise template.TemplateSyntaxError, error_str % {'tagname': bits[0]}
+ raise template.TemplateSyntaxError(error_str % {'tagname': bits[0]})
if bits[2] == 'as':
varname = bits[3].strip("'\"")
model = bits[5].strip("'\"")
diff --git a/categories/tests/test_templatetags.py b/categories/tests/test_templatetags.py
index 1ec8a80..526157f 100644
--- a/categories/tests/test_templatetags.py
+++ b/categories/tests/test_templatetags.py
@@ -28,40 +28,40 @@ class CategoryTagsTest(TestCase):
Test that we can properly retrieve a category.
"""
# display_path_as_ul
- rock_resp = u''
+ rock_resp = ''
resp = self.render_template('{% load category_tags %}{% display_path_as_ul "/Rock" %}')
resp = re.sub(r'\n$', "", resp)
self.assertEqual(resp, rock_resp)
# display_drilldown_as_ul
- expected_resp = u''
+ expected_resp = ''
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 = u'World > Worldbeat'
+ expected_resp = 'World > Worldbeat'
resp = self.render_template('{% load category_tags %}'
'{% breadcrumbs "/World/Worldbeat" " > " "categories.category" %}')
self.assertEqual(resp, expected_resp)
# get_top_level_categories
- expected_resp = u'Avant-garde|Blues|Country|Easy listening|Electronic|Hip hop/Rap music|Jazz|Latin|Modern folk|Pop|Reggae|Rhythm and blues|Rock|World|'
+ 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 %}'
'{% 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 = u"World|World > Worldbeat|"
+ expected_resp = "World|World > Worldbeat|"
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)
# recursetree
- expected_resp = u''
+ expected_resp = ''
ctxt = {'nodes': Category.objects.filter(name__in=("Worldbeat", "Urban Cowboy"))}
resp = self.render_template('{% load category_tags %}'
'{% recursetree nodes|tree_queryset %}- {{ node.name }}'
diff --git a/categories/views.py b/categories/views.py
index 9d5d383..21311d6 100644
--- a/categories/views.py
+++ b/categories/views.py
@@ -63,14 +63,14 @@ class CategoryDetailView(DetailView):
def get_object(self, **kwargs):
if self.path_field not in self.kwargs:
- raise AttributeError(u"Category detail view %s must be called with "
- u"a %s." % self.__class__.__name__, self.path_field)
+ raise AttributeError("Category detail view %s must be called with "
+ "a %s." % self.__class__.__name__, self.path_field)
if self.queryset is None:
queryset = self.get_queryset()
try:
return get_category_for_path(self.kwargs[self.path_field], self.model.objects.all())
except ObjectDoesNotExist:
- raise Http404(_(u"No %(verbose_name)s found matching the query") %
+ raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name})
def get_template_names(self):
diff --git a/doc_src/conf.py b/doc_src/conf.py
index 51ac114..5773732 100644
--- a/doc_src/conf.py
+++ b/doc_src/conf.py
@@ -40,8 +40,8 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
-project = u'Django Categories'
-copyright = u'2010-2012, Corey Oordt'
+project = 'Django Categories'
+copyright = '2010-2012, Corey Oordt'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -175,8 +175,8 @@ htmlhelp_basename = 'DjangoCategoriesdoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
- ('index', 'DjangoCategories.tex', u'Django Categories Documentation',
- u'CoreyOordt', 'manual'),
+ ('index', 'DjangoCategories.tex', 'Django Categories Documentation',
+ 'CoreyOordt', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
diff --git a/example/simpletext/admin.py b/example/simpletext/admin.py
index 55a5d73..9060c31 100644
--- a/example/simpletext/admin.py
+++ b/example/simpletext/admin.py
@@ -1,4 +1,4 @@
-from models import SimpleText, SimpleCategory
+from .models import SimpleText, SimpleCategory
from django.contrib import admin
from categories.admin import CategoryBaseAdmin, CategoryBaseAdminForm
diff --git a/example/simpletext/tests.py b/example/simpletext/tests.py
index 2247054..c7c4668 100755
--- a/example/simpletext/tests.py
+++ b/example/simpletext/tests.py
@@ -12,7 +12,7 @@ class SimpleTest(TestCase):
"""
Tests that 1 + 1 always equals 2.
"""
- self.failUnlessEqual(1 + 1, 2)
+ self.assertEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.