[Python-modules-commits] [django-sitetree] 01/07: Import django-sitetree_1.6.0.orig.tar.gz
Michael Fladischer
fladi at moszumanska.debian.org
Mon Aug 29 20:52:36 UTC 2016
This is an automated email from the git hooks/post-receive script.
fladi pushed a commit to branch master
in repository django-sitetree.
commit cd8603063525b894a17ba00296bd2e743f028905
Author: Michael Fladischer <FladischerMichael at fladi.at>
Date: Mon Aug 29 22:18:59 2016 +0200
Import django-sitetree_1.6.0.orig.tar.gz
---
.travis.yml | 18 ++--
AUTHORS | 2 +
CHANGELOG | 11 +++
LICENSE | 4 +-
docs/source/conf.py | 2 +-
setup.cfg | 5 ++
sitetree/__init__.py | 2 +-
sitetree/admin.py | 12 +--
sitetree/compat.py | 37 ++++++++
sitetree/exceptions.py | 4 +
sitetree/fields.py | 16 +++-
.../management/commands/sitetree_resync_apps.py | 22 +++--
sitetree/management/commands/sitetreedump.py | 31 ++++---
sitetree/management/commands/sitetreeload.py | 52 ++++++-----
sitetree/models.py | 15 +++-
sitetree/runtests.py | 23 ++++-
sitetree/sitetreeapp.py | 41 ++++++---
sitetree/tests.py | 68 +++++++++-----
sitetree/toolbox.py | 7 ++
tox.ini | 100 ++++-----------------
20 files changed, 287 insertions(+), 185 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 9cb83f6..4f1bbed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,10 +5,10 @@ python:
- 3.4
- 3.3
- 2.7
- - 2.6
env:
- - DJANGO="Django>=1.9.0,<1.10"
+ - DJANGO="Django>=1.10,<1.11"
+ - DJANGO="Django>=1.9,<1.10"
- DJANGO="Django>=1.8.6,<1.9"
- DJANGO="Django>=1.7,<1.8"
- DJANGO="Django>=1.6,<1.7"
@@ -33,19 +33,11 @@ matrix:
env: DJANGO="Django>=1.4,<1.5"
- python: 3.3
- env: DJANGO="Django>=1.9.0,<1.10"
+ env: DJANGO="Django>=1.10,<1.11"
+ - python: 3.3
+ env: DJANGO="Django>=1.9,<1.10"
- python: 3.3
env: DJANGO="Django>=1.4,<1.5"
- - python: 2.6
- env: DJANGO="Django>=1.9.0,<1.10"
- - python: 2.6
- env: DJANGO="Django>=1.8.6,<1.9"
- - python: 2.6
- env: DJANGO="Django>=1.7,<1.8"
- - python: 2.6
- env: DJANGO="Django>=1.6,<1.7"
-
-
after_success:
coveralls
diff --git a/AUTHORS b/AUTHORS
index 2f02b1c..e0f0120 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -34,6 +34,8 @@ ibooj <https://github.com/ibooj>
Patrick Altman <https://github.com/paltman>
Ben Cole <https://github.com/wengole>
Vitaliy Ivanov <https://github.com/vit-ivanov>
+Sergey Maranchuk <https://github.com/slav0nic>
+Martey Dodoo <https://github.com/martey>
Translators
diff --git a/CHANGELOG b/CHANGELOG
index bab0799..cee1011 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,17 @@ django-sitetree changelog
=========================
+v1.6.0
+------
++ Prevent TreeItems from being their own parents (see #200).
++ Added `toolbox` module as API single entry point.
++ Added `exceptions` module.
+* Django 1.10 compatibility improvements.
+* Cache.reset() misbehavior fixed (closes #191).
+* Fixed broken delete operation in admin for custom TreeItem (see #190).
+* Reduced number of cache calls (see #194).
+
+
v1.5.1
------
* Django 1.9 compatibility improvements.
diff --git a/LICENSE b/LICENSE
index b80d42c..70e78b9 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2010-2015, django-sitetree project
+Copyright (c) 2010-2016, django-sitetree project
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -11,7 +11,7 @@ are permitted provided that the following conditions are met:
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- 3. Neither the name of the django-sitetree project nor the names of its
+ 3. Neither the name of the django-sitetree nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
diff --git a/docs/source/conf.py b/docs/source/conf.py
index dc83b91..aca3488 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -42,7 +42,7 @@ master_doc = 'index'
# General information about the project.
project = u'django-sitetree'
-copyright = u'2011-2015, Igor \'idle sign\' Starikov'
+copyright = u'2011-2016, Igor \'idle sign\' Starikov'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..8b8c1dc
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[aliases]
+release = clean --all sdist bdist_wheel upload
+
+[wheel]
+universal = 1
diff --git a/sitetree/__init__.py b/sitetree/__init__.py
index 7f8aecb..2d28686 100644
--- a/sitetree/__init__.py
+++ b/sitetree/__init__.py
@@ -1,4 +1,4 @@
-VERSION = (1, 5, 1)
+VERSION = (1, 6, 0)
default_app_config = 'sitetree.config.SitetreeConfig'
diff --git a/sitetree/admin.py b/sitetree/admin.py
index 13970d2..22f4505 100644
--- a/sitetree/admin.py
+++ b/sitetree/admin.py
@@ -107,6 +107,7 @@ class TreeItemAdmin(admin.ModelAdmin):
)
filter_horizontal = ('access_permissions',)
change_form_template = 'admin/sitetree/treeitem/change_form.html'
+ delete_confirmation_template = 'admin/sitetree/treeitem/delete_confirmation.html'
def response_add(self, request, obj, post_url_continue=None, **kwargs):
"""Redirects to the appropriate items' 'continue' page on item add.
@@ -257,18 +258,18 @@ def redirects_handler(*args, **kwargs):
introduced in Django 1.4 by url handling changes.
"""
- referer = args[0].META['HTTP_REFERER']
+ path = args[0].path
shift = '../'
- if 'delete' in referer:
+ if 'delete' in path:
# Weird enough 'delete' is not handled by TreeItemAdmin::response_change().
shift += '../'
- elif 'history' in referer:
+ elif 'history' in path:
if 'item_id' not in kwargs:
# Encountered request from history page to return to tree layout page.
shift += '../'
- return HttpResponseRedirect(referer + shift)
+ return HttpResponseRedirect(path + shift)
class TreeAdmin(admin.ModelAdmin):
@@ -300,8 +301,7 @@ class TreeAdmin(admin.ModelAdmin):
prefix_change = 'change/' if DJANGO_POST_19 else ''
sitetree_urls = [
- # Ignore urls.W002. Leading slash is in the right place.
- url(r'^/$', redirects_handler, name=get_tree_item_url_name('changelist')),
+ url(r'^change/$', redirects_handler, name=get_tree_item_url_name('changelist')),
url(r'^((?P<tree_id>\d+)/)?%sitem_add/$' % prefix_change,
self.admin_site.admin_view(self.tree_admin.item_add), name=get_tree_item_url_name('add')),
diff --git a/sitetree/compat.py b/sitetree/compat.py
new file mode 100644
index 0000000..d494b4e
--- /dev/null
+++ b/sitetree/compat.py
@@ -0,0 +1,37 @@
+from django import VERSION
+
+
+class CommandOption(object):
+ """Command line option wrapper."""
+
+ def __init__(self, *args, **kwargs):
+ self.args = args
+ self.kwargs = kwargs
+
+
+def options_getter(command_options):
+ """Compatibility function to get rid of optparse in management commands after Django 1.10.
+
+ :param tuple command_options: tuple with `CommandOption` objects.
+
+ """
+ def get_options(option_func=None):
+ from optparse import make_option
+ from django.core.management.base import BaseCommand
+
+ func = option_func or make_option
+
+ options = tuple([func(*option.args, **option.kwargs) for option in command_options])
+
+ if option_func is None:
+ if VERSION < (1, 8):
+ result = BaseCommand.option_list + options
+ else:
+ result = []
+
+ else:
+ result = options
+
+ return result
+
+ return get_options
diff --git a/sitetree/exceptions.py b/sitetree/exceptions.py
new file mode 100644
index 0000000..fbfedfc
--- /dev/null
+++ b/sitetree/exceptions.py
@@ -0,0 +1,4 @@
+
+
+class SiteTreeError(Exception):
+ """Exception class for sitetree application."""
diff --git a/sitetree/fields.py b/sitetree/fields.py
index 0dd9c15..05df777 100644
--- a/sitetree/fields.py
+++ b/sitetree/fields.py
@@ -1,3 +1,4 @@
+from django import VERSION
from django import template
from django.template.base import Parser, Token, TOKEN_BLOCK
from django.forms import ChoiceField
@@ -24,10 +25,13 @@ class TreeItemChoiceField(ChoiceField):
root_title = '---------'
def __init__(self, tree, required=True, widget=None, label=None, initial=None, help_text=None, *args, **kwargs):
- super(TreeItemChoiceField, self).__init__(required=required, widget=widget, label=label, initial=initial,
- help_text=help_text, *args, **kwargs)
+ super(TreeItemChoiceField, self).__init__(
+ required=required, widget=widget, label=label, initial=initial,
+ help_text=help_text, *args, **kwargs)
+
if isinstance(tree, MODEL_TREE_CLASS):
tree = tree.alias
+
self.tree = tree
self.choices = self._build_choices()
@@ -35,9 +39,15 @@ class TreeItemChoiceField(ChoiceField):
"""Build choices list runtime using 'sitetree_tree' tag"""
tree_token = u'sitetree_tree from "%s" template "%s"' % (self.tree, self.template)
+ context_kwargs = {'current_app': 'admin'}
+ if VERSION >= (1, 8):
+ context = template.Context(context_kwargs)
+ else:
+ context = template.Context(**context_kwargs)
+
choices_str = sitetree_tree(
Parser(None), Token(token_type=TOKEN_BLOCK, contents=tree_token)
- ).render(template.Context(current_app='admin'))
+ ).render(context)
tree_choices = [('', self.root_title)]
for line in choices_str.splitlines():
diff --git a/sitetree/management/commands/sitetree_resync_apps.py b/sitetree/management/commands/sitetree_resync_apps.py
index b389b32..0a06135 100644
--- a/sitetree/management/commands/sitetree_resync_apps.py
+++ b/sitetree/management/commands/sitetree_resync_apps.py
@@ -1,16 +1,23 @@
-from optparse import make_option
-
from django.core.management.base import BaseCommand
from django.db import DEFAULT_DB_ALIAS
from sitetree.utils import get_tree_model, import_project_sitetree_modules
from sitetree.settings import APP_MODULE_NAME
from sitetree.sitetreeapp import Cache
+from sitetree.compat import CommandOption, options_getter
MODEL_TREE_CLASS = get_tree_model()
+get_options = options_getter((
+ CommandOption(
+ '--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
+ help='Nominates a specific database to place trees and items into. Defaults to the "default" database.'
+ ),
+))
+
+
class Command(BaseCommand):
help = 'Places sitetrees of the project applications (defined in `app_name.sitetree.py`) into DB, ' \
@@ -18,12 +25,11 @@ class Command(BaseCommand):
args = '[app_name app_name ...]'
- option_list = BaseCommand.option_list + (
- make_option(
- '--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
- help='Nominates a specific database to place trees and items into. Defaults to the "default" database.'
- ),
- )
+ option_list = get_options()
+
+ def add_arguments(self, parser):
+ parser.add_argument('args', metavar='app', nargs='+', help='Application names.')
+ get_options(parser.add_argument)
def handle(self, *apps, **options):
using = options.get('database', DEFAULT_DB_ALIAS)
diff --git a/sitetree/management/commands/sitetreedump.py b/sitetree/management/commands/sitetreedump.py
index 321be5e..f077c11 100644
--- a/sitetree/management/commands/sitetreedump.py
+++ b/sitetree/management/commands/sitetreedump.py
@@ -1,30 +1,38 @@
-from optparse import make_option
-
from django.core import serializers
from django.core.management.base import BaseCommand, CommandError
from django.db import DEFAULT_DB_ALIAS
from sitetree.utils import get_tree_model, get_tree_item_model
+from sitetree.compat import CommandOption, options_getter
MODEL_TREE_CLASS = get_tree_model()
MODEL_TREE_ITEM_CLASS = get_tree_item_model()
+get_options = options_getter((
+ CommandOption(
+ '--indent', default=None, dest='indent', type=int,
+ help='Specifies the indent level to use when pretty-printing output.'),
+
+ CommandOption('--items_only', action='store_true', dest='items_only', default=False,
+ help='Export tree items only.'),
+
+ CommandOption('--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
+ help='Nominates a specific database to export fixtures from. Defaults to the "default" database.'),
+))
+
+
class Command(BaseCommand):
- option_list = BaseCommand.option_list + (
- make_option('--indent', default=None, dest='indent', type='int',
- help='Specifies the indent level to use when pretty-printing output.'),
- make_option('--items_only', action='store_true', dest='items_only', default=False,
- help='Export tree items only.'),
- make_option('--database', action='store', dest='database',
- default=DEFAULT_DB_ALIAS, help='Nominates a specific database to export fixtures from. '
- 'Defaults to the "default" database.'),
- )
+ option_list = get_options()
help = 'Output sitetrees from database as a fixture in JSON format.'
args = '[tree_alias tree_alias ...]'
+ def add_arguments(self, parser):
+ parser.add_argument('args', metavar='tree', nargs='?', help='Tree aliases.', default=[])
+ get_options(parser.add_argument)
+
def handle(self, *aliases, **options):
indent = options.get('indent', None)
@@ -46,5 +54,6 @@ class Command(BaseCommand):
try:
return serializers.serialize('json', objects, indent=indent)
+
except Exception as e:
raise CommandError('Unable to serialize sitetree(s): %s' % e)
diff --git a/sitetree/management/commands/sitetreeload.py b/sitetree/management/commands/sitetreeload.py
index 81a90a4..a90c089 100644
--- a/sitetree/management/commands/sitetreeload.py
+++ b/sitetree/management/commands/sitetreeload.py
@@ -1,8 +1,7 @@
import sys
-from optparse import make_option
from collections import defaultdict
-import django
+from django import VERSION
from django.core import serializers
from django.core.management.base import BaseCommand, CommandError
from django.core.management.color import no_style
@@ -10,26 +9,43 @@ from django.db import connections, router, transaction, DEFAULT_DB_ALIAS
from django.core.exceptions import ObjectDoesNotExist
from sitetree.utils import get_tree_model, get_tree_item_model
+from sitetree.compat import CommandOption, options_getter
MODEL_TREE_CLASS = get_tree_model()
MODEL_TREE_ITEM_CLASS = get_tree_item_model()
+VER_LESS_17 = VERSION < (1, 7)
+VER_LESS_18 = VERSION < (1, 8)
+
+
+get_options = options_getter((
+ CommandOption(
+ '--database', action='store', dest='database',
+ default=DEFAULT_DB_ALIAS, help='Nominates a specific database to load fixtures into. '
+ 'Defaults to the "default" database.'),
+
+ CommandOption(
+ '--mode', action='store', dest='mode', default='append',
+ help='Mode to put data into DB. Variants: `replace`, `append`.'),
+
+ CommandOption(
+ '--items_into_tree', action='store', dest='into_tree', default=None,
+ help='Import only tree items data into tree with given alias.'),
+))
+
class Command(BaseCommand):
- option_list = BaseCommand.option_list + (
- make_option('--database', action='store', dest='database',
- default=DEFAULT_DB_ALIAS, help='Nominates a specific database to load fixtures into. '
- 'Defaults to the "default" database.'),
- make_option('--mode', action='store', dest='mode',
- default='append', help='Mode to put data into DB. Variants: `replace`, `append`.'),
- make_option('--items_into_tree', action='store', dest='into_tree',
- default=None, help='Import only tree items data into tree with given alias.'),
- )
+ option_list = get_options()
+
help = 'Loads sitetrees from fixture in JSON format into database.'
args = '[fixture_file fixture_file ...]'
+ def add_arguments(self, parser):
+ parser.add_argument('args', metavar='fixture', nargs='+', help='Fixture files.')
+ get_options(parser.add_argument)
+
def handle(self, *fixture_files, **options):
using = options.get('database', DEFAULT_DB_ALIAS)
@@ -50,17 +66,13 @@ class Command(BaseCommand):
self.style = no_style()
- django_version = django.get_version()
- django_version_less_17 = django_version < '1.7'
- django_version_less_18 = django_version < '1.8'
-
- if django_version_less_17:
+ if VER_LESS_17:
transaction.commit_unless_managed(using=using)
- if django_version_less_18:
+ if VER_LESS_18:
transaction.enter_transaction_management(using=using)
- if django_version_less_17:
+ if VER_LESS_17:
transaction.managed(True, using=using)
loaded_object_count = 0
@@ -164,7 +176,7 @@ class Command(BaseCommand):
import traceback
fixture.close()
- if django_version_less_18:
+ if VER_LESS_18:
transaction.rollback(using=using)
transaction.leave_transaction_management(using=using)
@@ -186,7 +198,7 @@ class Command(BaseCommand):
for line in sequence_sql:
cursor.execute(line)
- if django_version_less_18:
+ if VER_LESS_18:
transaction.commit(using=using)
transaction.leave_transaction_management(using=using)
diff --git a/sitetree/models.py b/sitetree/models.py
index 45bc47c..7304b92 100644
--- a/sitetree/models.py
+++ b/sitetree/models.py
@@ -125,11 +125,22 @@ class TreeItemBase(models.Model):
help_text=_('Item position among other site tree items under the same parent.'), db_index=True, default=0)
def save(self, force_insert=False, force_update=False, **kwargs):
- """We override parent save method to set item's sort order to its' primary
- key value.
+ """Ensure that item is not its own parent and set proper sort order.
"""
+ # Ensure that item is not its own parent, since this breaks
+ # the sitetree (and possibly the entire site).
+ if self.parent == self:
+ self.parent = None
+
+ # Set item's sort order to its primary key.
+ id_ = self.id
+ if id_ and self.sort_order == 0:
+ self.sort_order = id_
+
super(TreeItemBase, self).save(force_insert, force_update, **kwargs)
+
+ # Set item's sort order to its primary key if not already set.
if self.sort_order == 0:
self.sort_order = self.id
self.save()
diff --git a/sitetree/runtests.py b/sitetree/runtests.py
index 90d67bf..27970d5 100755
--- a/sitetree/runtests.py
+++ b/sitetree/runtests.py
@@ -12,15 +12,30 @@ def main():
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
if not settings.configured:
- settings.configure(
+
+ configure_kwargs = dict(
INSTALLED_APPS=('django.contrib.auth', 'django.contrib.contenttypes', APP_NAME),
DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3'}},
- ROOT_URLCONF = 'sitetree.tests',
+ ROOT_URLCONF='sitetree.tests',
MIDDLEWARE_CLASSES=global_settings.MIDDLEWARE_CLASSES, # Prevents Django 1.7 warning.
- TEMPLATE_CONTEXT_PROCESSORS=tuple(global_settings.TEMPLATE_CONTEXT_PROCESSORS) + (
+ )
+
+ try:
+ configure_kwargs['TEMPLATE_CONTEXT_PROCESSORS'] = tuple(global_settings.TEMPLATE_CONTEXT_PROCESSORS) + (
'django.core.context_processors.request',
)
- )
+
+ except AttributeError:
+
+ # Django 1.8+
+ configure_kwargs['TEMPLATES'] = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'APP_DIRS': True,
+ },
+ ]
+
+ settings.configure(**configure_kwargs)
try: # Django 1.7 +
from django import setup
diff --git a/sitetree/sitetreeapp.py b/sitetree/sitetreeapp.py
index 2f79c64..e387106 100644
--- a/sitetree/sitetreeapp.py
+++ b/sitetree/sitetreeapp.py
@@ -26,6 +26,7 @@ from .utils import get_tree_model, get_tree_item_model, import_app_sitetree_modu
from .settings import (
ALIAS_TRUNK, ALIAS_THIS_CHILDREN, ALIAS_THIS_SIBLINGS, ALIAS_THIS_PARENT_SIBLINGS, ALIAS_THIS_ANCESTOR_CHILDREN,
UNRESOLVED_ITEM_MARKER, RAISE_ITEMS_ERRORS_ON_DEBUG, CACHE_TIMEOUT)
+from .exceptions import SiteTreeError
if VERSION >= (1, 9, 0):
@@ -53,6 +54,7 @@ _SITETREE = None
_THREAD_LOCAL = local()
_THREAD_LANG = 'sitetree_lang'
+_THREAD_CACHE = 'sitetree_cache'
def get_sitetree():
@@ -284,7 +286,7 @@ class Cache(object):
Could be used to show up tree changes made in a different process.
"""
- cache.get('sitetrees_reset', True)
+ cache.set('sitetrees_reset', True)
def init(self):
"""Initializes local cache from Django cache."""
@@ -292,10 +294,15 @@ class Cache(object):
# Drop cache flag set by .reset() method.
cache.get('sitetrees_reset') and self.empty()
- cache_ = cache.get('sitetrees')
+ cache_ = getattr(_THREAD_LOCAL, _THREAD_CACHE, None)
if cache_ is None:
- # Init cache dictionary with predefined entries.
- cache_ = {'sitetrees': {}, 'urls': {}, 'parents': {}, 'items_by_ids': {}, 'tree_aliases': {}}
+
+ cache_ = cache.get(
+ # Init cache dictionary with predefined entries.
+ 'sitetrees', {'sitetrees': {}, 'urls': {}, 'parents': {}, 'items_by_ids': {}, 'tree_aliases': {}})
+
+ setattr(_THREAD_LOCAL, _THREAD_CACHE, cache_)
+
self.cache = cache_
def save(self):
@@ -305,6 +312,7 @@ class Cache(object):
def empty(self, **kwargs):
"""Empties cached sitetree data."""
self.cache = None
+ setattr(_THREAD_LOCAL, _THREAD_CACHE, None)
cache.delete('sitetrees')
cache.delete('sitetrees_reset')
@@ -410,9 +418,16 @@ class SiteTree(object):
def current_app_is_admin(self):
"""Returns boolean whether current application is Admin contrib."""
- current_app = (
- getattr(self._global_context.get('request', None), 'current_app',
- self._global_context.current_app))
+ global_context = self._global_context
+
+ current_app = getattr(
+ # Try from request.resolver_match.app_name
+ getattr(global_context.get('request', None), 'resolver_match', None), 'app_name',
+ # Try from global context obj.
+ getattr(global_context, 'current_app', None))
+
+ if current_app is None: # Try from global context dict.
+ current_app = global_context.get('current_app', '')
return current_app == 'admin'
@@ -427,8 +442,6 @@ class SiteTree(object):
get_cache_entry = cache.get_entry
set_cache_entry = cache.set_entry
- cache.init()
-
sitetree_needs_caching = False
if not self.current_app_is_admin():
# We do not need i18n for a tree rendered in Admin dropdown.
@@ -638,11 +651,16 @@ class SiteTree(object):
self.lang_init()
# Resolve tree_alias from the context.
tree_alias = self.resolve_var(tree_alias)
+
+ self.cache.init() # Warm up cache.
+
# Get tree.
tree_alias, sitetree_items = self.get_sitetree(tree_alias)
+
# No items in tree, fail silently.
if not sitetree_items:
return False, False
+
return tree_alias, sitetree_items
def get_current_page_title(self, tree_alias, context):
@@ -856,6 +874,7 @@ class SiteTree(object):
if start_from.inbreadcrumbs and start_from.hidden == False and self.check_access(start_from,
self._global_context):
self.cache_breadcrumbs.append(start_from)
+
if hasattr(start_from, 'parent') and start_from.parent is not None:
self.breadcrumbs_climber(tree_alias, self.get_item_by_id(tree_alias, start_from.parent.id))
@@ -879,7 +898,3 @@ class SiteTree(object):
varname = varname
return varname
-
-
-class SiteTreeError(Exception):
- """Exception class for sitetree application."""
diff --git a/sitetree/tests.py b/sitetree/tests.py
index a38ac17..a857a0c 100644
--- a/sitetree/tests.py
+++ b/sitetree/tests.py
@@ -5,12 +5,13 @@ try:
from StringIO import StringIO
except ImportError:
from io import StringIO
-
+
try:
from unittest import mock
except ImportError:
import mock
+from django import VERSION
from django.conf import settings
from django.utils.translation import activate
from django.template.base import Template, TemplateSyntaxError
@@ -21,26 +22,26 @@ from django.contrib.auth.models import Permission
from django.contrib.admin.sites import site
from django.core.management import call_command
from django.core.exceptions import ImproperlyConfigured
-from django.conf.urls import patterns, url
+from django.conf.urls import url
from sitetree.models import Tree, TreeItem
-from sitetree.forms import TreeItemForm
from sitetree.admin import TreeAdmin, TreeItemAdmin, redirects_handler
-from sitetree.utils import (
- tree, item, get_app_n_model, import_app_sitetree_module, import_project_sitetree_modules, get_model_class
-)
-from sitetree.sitetreeapp import (
- SiteTree, SiteTreeError, register_items_hook, register_i18n_trees, register_dynamic_trees, compose_dynamic_tree,
- get_dynamic_trees
-)
-
+from sitetree.utils import get_app_n_model, get_model_class
+from sitetree.sitetreeapp import SiteTree
+from sitetree.toolbox import TreeItemForm, tree, item, import_app_sitetree_module, import_project_sitetree_modules, \
+ register_items_hook, register_i18n_trees, register_dynamic_trees, compose_dynamic_tree, get_dynamic_trees
+from sitetree.exceptions import SiteTreeError
-urlpatterns = patterns(
- '',
+urlpatterns = [
url(r'articles/', lambda r: None, name='articles_list'),
url(r'articles/(\d+)/', lambda r: None, name='articles_detailed'),
url(r'articles/(?P<id>\d+)_(?P<slug>[\w-]+)/', lambda r: None, name='url'),
-)
+]
+
+if VERSION < (1, 10):
+ from django.conf.urls import patterns
+ urlpatterns.insert(0, '')
+ urlpatterns = patterns(*urlpatterns)
class MockRequest(object):
@@ -70,17 +71,26 @@ class MockUser(object):
return self.permissions
-def get_mock_context(app=None, path=None, user_authorized=False, tree_item=None, put_var=None):
+def get_mock_context(app='', path=None, user_authorized=False, tree_item=None, put_var=None):
+
ctx = Context(
{
'request': MockRequest(path, user_authorized),
't2_root2_title': 'my_real_title', 'art_id': 10, 'tree_item': tree_item,
'somevar_str': 'articles_list', 'somevar_list': ['a', 'b'], 'put_var': put_var
- },
- current_app=app
+ }
)
ctx.template = mock.MagicMock()
ctx.template.engine.string_if_invalid = ''
+
+ if VERSION >= (1, 10):
+ match = mock.MagicMock()
+ match.app_name = app
+ ctx.resolver_match = match
+
+ else:
+ ctx._current_app = app
+
return ctx
@@ -288,6 +298,19 @@ class TreeItemModelTest(SitetreeTest):
ti1.delete()
self.assertIsNone(ti1.id)
+ def test_no_recursive_parents(self):
+ """Verify that treeitems cannot be their own parent."""
+ tree = Tree(alias="mytree")
+ tree.save()
+ tree_item = TreeItem(title="i'm my own grandpa", tree=tree)
+ # This item needs to be saved, otherwise it cannot be set
+ # as a parent.
+ tree_item.save()
+
+ tree_item.parent = tree_item
+ tree_item.save()
+ self.assertNotEqual(tree_item, tree_item.parent)
+
def test_context_proc_required(self):
context = Context()
old_debug = settings.DEBUG
@@ -590,7 +613,9 @@ class TreeTest(SitetreeTest):
self.assertEqual(self.t3_en.get_title(), 'tree3en_title')
def test_children_filtering(self):
- self.sitetree._global_context = get_mock_context(path='/')
+ self.sitetree.cache.init()
+
+ self.sitetree.set_global_context(get_mock_context(path='/'))
self.sitetree.get_sitetree('tree3')
children = self.sitetree.get_children('tree3', self.t3_root)
filtered = self.sitetree.filter_items(children, 'menu')
@@ -602,7 +627,7 @@ class TreeTest(SitetreeTest):
def test_register_i18n_trees(self):
register_i18n_trees(['tree3'])
- self.sitetree._global_context = get_mock_context(path='/the_same_url/')
+ self.sitetree.set_global_context(get_mock_context(path='/the_same_url/'))
activate('en')
self.sitetree.get_sitetree('tree3')
@@ -625,6 +650,8 @@ class DynamicTreeTest(SitetreeTest):
def test_basic_old_and_new(self):
+ self.sitetree.cache.init()
+
# Assert no dynamic attached.
tree_alias, sitetree_items = self.sitetree.get_sitetree('main')
self.assertEqual(len(sitetree_items), 1)
@@ -683,7 +710,8 @@ class DynamicTreeTest(SitetreeTest):
register_dynamic_trees(trees, **kwargs)
mock_context = get_mock_context(path='/the_same_url/')
- self.sitetree._global_context = mock_context
+ self.sitetree.cache.init()
+ self.sitetree.set_global_context(mock_context)
tree_alias, sitetree_items = self.sitetree.get_sitetree('main')
if reset_cache:
diff --git a/sitetree/toolbox.py b/sitetree/toolbox.py
new file mode 100644
index 0000000..d46082f
--- /dev/null
+++ b/sitetree/toolbox.py
@@ -0,0 +1,7 @@
+# Unused imports below are exposed as API.
+from .utils import get_tree_item_model, get_tree_model, tree, item, import_app_sitetree_module, \
+ import_project_sitetree_modules
+from .sitetreeapp import register_i18n_trees, register_items_hook, compose_dynamic_tree, register_dynamic_trees, \
+ get_dynamic_trees
+from .fields import TreeItemChoiceField
+from .forms import TreeItemForm
diff --git a/tox.ini b/tox.ini
index ac713cb..81ce724 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,87 +1,25 @@
[tox]
-envlist =
- py27-django14,
- py27-django15,
- py27-django16,
- py27-django17,
- py27-django18,
- py27-django19,
+envlist = py{27,32,33,34}-django{15,16,17,18,19,110}
+ py{35}-django{18,19,110}
- py3-django15,
- py3-django16,
- py3-django17,
- py3-django18,
- py3-django19
-
-
-[django14]
-deps = Django>=1.4,<1.5
-
-[django15]
-deps = Django>=1.5,<1.6
-
-[django16]
-deps = Django>=1.6,<1.7
-
-[django17]
-deps = Django>=1.7,<1.8
-
-[django18]
-deps = Django>=1.8,<1.9
-
-[django19]
-deps = Django==1.9.0
+install_command = pip install {opts} {packages}
+skip_missing_interpreters = True
[testenv]
-commands = python sitetree/runtests.py
-
-
-[testenv:py27-django14]
-basepython = python2.7
-deps = {[django14]deps}
- mock
+basepython =
+ py27: python2.7
+ py32: python3.2
+ py33: python3.3
+ py34: python3.4
+ py35: python3.5
-[testenv:py27-django15]
-basepython = python2.7
-deps = {[django15]deps}
- mock
-
-[testenv:py27-django16]
-basepython = python2.7
-deps = {[django16]deps}
- mock
-
-[testenv:py27-django17]
-basepython = python2.7
-deps = {[django17]deps}
- mock
-
-[testenv:py27-django18]
-basepython = python2.7
-deps = {[django18]deps}
- mock
-
-[testenv:py27-django19]
-basepython = python2.7
-deps = {[django19]deps}
- mock
-
-[testenv:py3-django15]
-basepython = python3
-deps = {[django15]deps}
-
-[testenv:py3-django16]
-basepython = python3
-deps = {[django16]deps}
-
-[testenv:py3-django17]
-basepython = python3
-deps = {[django17]deps}
-
-[testenv:py3-django18]
-basepython = python3
-deps = {[django18]deps}
+commands = python sitetree/runtests.py
-[testenv:py3-django19]
-basepython = python3
-deps = {[django19]deps}
+deps =
+ mock
+ django15: Django>=1.5,<1.6
+ django16: Django>=1.6,<1.7
+ django17: Django>=1.7,<1.8
+ django18: Django>=1.8,<1.9
+ django19: Django>=1.9,<1.10
+ django110: Django>=1.10,<1.11
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/django-sitetree.git
More information about the Python-modules-commits
mailing list