[Python-modules-commits] [python-django-treebeard] 01/11: Import python-django-treebeard_4.1.2+dfsg.orig.tar.gz

Michael Fladischer fladi at moszumanska.debian.org
Wed Jul 12 20:44:03 UTC 2017


This is an automated email from the git hooks/post-receive script.

fladi pushed a commit to branch master
in repository python-django-treebeard.

commit fa17de54982188d431a9b41c73231cf5392aa235
Author: Michael Fladischer <fladi at debian.org>
Date:   Fri Jun 23 11:35:28 2017 +0200

    Import python-django-treebeard_4.1.2+dfsg.orig.tar.gz
---
 CHANGES                                            |  14 ++
 MANIFEST.in                                        |   1 +
 PKG-INFO                                           |  21 +-
 README.rst                                         |  19 +-
 django_treebeard.egg-info/PKG-INFO                 |  21 +-
 django_treebeard.egg-info/SOURCES.txt              |   5 +
 docs/README.md                                     |  23 ++
 docs/make.bat                                      | 263 +++++++++++++++++++++
 docs/source/_ext/djangodocs.py                     |  10 +
 docs/source/_static/treebeard-admin-advanced.png   | Bin 0 -> 116531 bytes
 docs/source/_static/treebeard-admin-basic.png      | Bin 0 -> 96077 bytes
 docs/source/tutorial.rst                           |  12 +-
 setup.cfg                                          |   1 -
 treebeard/__init__.py                              |   2 +-
 treebeard/mp_tree.py                               |  99 +++++---
 .../templates/admin/tree_change_list_results.html  |  62 ++---
 treebeard/templates/admin/tree_list_results.html   |   1 -
 treebeard/tests/settings.py                        |  13 +
 18 files changed, 494 insertions(+), 73 deletions(-)

diff --git a/CHANGES b/CHANGES
index fa29e61..479918b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,17 @@
+Release 4.1.2 (Jun 22, 2017)
+---------------------------
+
+* Fixed MANIFEST.in for Debian packaging.
+
+
+Release 4.1.1 (May 24, 2017)
+---------------------------
+
+* Removed deprecated templatetag inclusion
+* Added support for Python-3.6
+* Added support for MS-SQL
+
+
 Release 4.1.0 (Nov 24, 2016)
 ---------------------------
 
diff --git a/MANIFEST.in b/MANIFEST.in
index 99ca10d..3a0efcb 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -3,3 +3,4 @@ recursive-include treebeard *.py
 recursive-include treebeard/static *
 recursive-include treebeard/templates *
 recursive-include treebeard/locale *
+recursive-include docs Makefile README.md make.bat *.py *.png *.rst
diff --git a/PKG-INFO b/PKG-INFO
index d165513..f71bd45 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: django-treebeard
-Version: 4.1.0
+Version: 4.1.2
 Summary: Efficient tree implementations for Django
 Home-page: https://github.com/django-treebeard/django-treebeard/
 Author: Gustavo Picon
@@ -11,10 +11,27 @@ Description: ================
         ================
         
         **django-treebeard** is a library that implements efficient tree implementations
-        for the Django Web Framework 1.7 and later.
+        for the Django Web Framework 1.8 and later.
         
         It is written by Gustavo Picón and licensed under the Apache License 2.0.
         
+        Status
+        ------
+        
+        .. image:: https://readthedocs.org/projects/django-treebeard/badge/?version=latest
+            :target: https://readthedocs.org/projects/django-treebeard/
+            
+        .. image:: https://travis-ci.org/django-treebeard/django-treebeard.svg?branch=master
+            :target: https://travis-ci.org/django-treebeard/django-treebeard
+        
+        .. image:: https://ci.appveyor.com/api/projects/status/mwbf062v68lhw05c?svg=true
+            :target: https://ci.appveyor.com/project/mvantellingen/django-treebeard
+        
+        .. image:: https://img.shields.io/pypi/v/django-treebeard.svg
+            :target: https://pypi.python.org/pypi/django-treebeard/
+        
+        Features
+        --------
         django-treebeard is:
         
         - **Flexible**: Includes 3 different tree implementations with the same API:
diff --git a/README.rst b/README.rst
index 0294d14..2d8ad10 100644
--- a/README.rst
+++ b/README.rst
@@ -3,10 +3,27 @@ django-treebeard
 ================
 
 **django-treebeard** is a library that implements efficient tree implementations
-for the Django Web Framework 1.7 and later.
+for the Django Web Framework 1.8 and later.
 
 It is written by Gustavo Picón and licensed under the Apache License 2.0.
 
+Status
+------
+
+.. image:: https://readthedocs.org/projects/django-treebeard/badge/?version=latest
+    :target: https://readthedocs.org/projects/django-treebeard/
+    
+.. image:: https://travis-ci.org/django-treebeard/django-treebeard.svg?branch=master
+    :target: https://travis-ci.org/django-treebeard/django-treebeard
+
+.. image:: https://ci.appveyor.com/api/projects/status/mwbf062v68lhw05c?svg=true
+    :target: https://ci.appveyor.com/project/mvantellingen/django-treebeard
+
+.. image:: https://img.shields.io/pypi/v/django-treebeard.svg
+    :target: https://pypi.python.org/pypi/django-treebeard/
+
+Features
+--------
 django-treebeard is:
 
 - **Flexible**: Includes 3 different tree implementations with the same API:
diff --git a/django_treebeard.egg-info/PKG-INFO b/django_treebeard.egg-info/PKG-INFO
index d165513..f71bd45 100644
--- a/django_treebeard.egg-info/PKG-INFO
+++ b/django_treebeard.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: django-treebeard
-Version: 4.1.0
+Version: 4.1.2
 Summary: Efficient tree implementations for Django
 Home-page: https://github.com/django-treebeard/django-treebeard/
 Author: Gustavo Picon
@@ -11,10 +11,27 @@ Description: ================
         ================
         
         **django-treebeard** is a library that implements efficient tree implementations
-        for the Django Web Framework 1.7 and later.
+        for the Django Web Framework 1.8 and later.
         
         It is written by Gustavo Picón and licensed under the Apache License 2.0.
         
+        Status
+        ------
+        
+        .. image:: https://readthedocs.org/projects/django-treebeard/badge/?version=latest
+            :target: https://readthedocs.org/projects/django-treebeard/
+            
+        .. image:: https://travis-ci.org/django-treebeard/django-treebeard.svg?branch=master
+            :target: https://travis-ci.org/django-treebeard/django-treebeard
+        
+        .. image:: https://ci.appveyor.com/api/projects/status/mwbf062v68lhw05c?svg=true
+            :target: https://ci.appveyor.com/project/mvantellingen/django-treebeard
+        
+        .. image:: https://img.shields.io/pypi/v/django-treebeard.svg
+            :target: https://pypi.python.org/pypi/django-treebeard/
+        
+        Features
+        --------
         django-treebeard is:
         
         - **Flexible**: Includes 3 different tree implementations with the same API:
diff --git a/django_treebeard.egg-info/SOURCES.txt b/django_treebeard.egg-info/SOURCES.txt
index 12b59f6..2854c37 100644
--- a/django_treebeard.egg-info/SOURCES.txt
+++ b/django_treebeard.egg-info/SOURCES.txt
@@ -11,6 +11,8 @@ django_treebeard.egg-info/dependency_links.txt
 django_treebeard.egg-info/requires.txt
 django_treebeard.egg-info/top_level.txt
 docs/Makefile
+docs/README.md
+docs/make.bat
 docs/source/admin.rst
 docs/source/al_tree.rst
 docs/source/api.rst
@@ -25,6 +27,9 @@ docs/source/mp_tree.rst
 docs/source/ns_tree.rst
 docs/source/tests.rst
 docs/source/tutorial.rst
+docs/source/_ext/djangodocs.py
+docs/source/_static/treebeard-admin-advanced.png
+docs/source/_static/treebeard-admin-basic.png
 treebeard/__init__.py
 treebeard/admin.py
 treebeard/al_tree.py
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..6285310
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,23 @@
+This is the documentation source for django-treebeard.
+You can read the documentation on:
+
+http://django-treebeard.readthedocs.io/en/latest/
+
+Or create the documentation yourself by compiling the ReStructured Text files:
+
+If you want to build the docs you'll need the graphviz tool, if you are using a Mac and Brew
+you can install it like this:
+
+$ brew install graphviz
+
+Then you'll need at least Django and Sphinx:
+
+$ pip install Django
+$ pip install Sphinx
+
+To build the docs run:
+
+```bash
+$ cd docs/
+$ make html
+```
\ No newline at end of file
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 0000000..23f696e
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,263 @@
+ at ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
+set I18NSPHINXOPTS=%SPHINXOPTS% source
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  xml        to make Docutils-native XML files
+	echo.  pseudoxml  to make pseudoxml-XML files for display purposes
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	echo.  coverage   to run coverage check of the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+
+REM Check if sphinx-build is available and fallback to Python version if any
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 goto sphinx_python
+goto sphinx_ok
+
+:sphinx_python
+
+set SPHINXBUILD=python -m sphinx.__init__
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+	echo.
+	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+	echo.installed, then set the SPHINXBUILD environment variable to point
+	echo.to the full path of the 'sphinx-build' executable. Alternatively you
+	echo.may add the Sphinx directory to PATH.
+	echo.
+	echo.If you don't have Sphinx installed, grab it from
+	echo.http://sphinx-doc.org/
+	exit /b 1
+)
+
+:sphinx_ok
+
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\django-treebeard.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\django-treebeard.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "latexpdf" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	cd %BUILDDIR%/latex
+	make all-pdf
+	cd %~dp0
+	echo.
+	echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "latexpdfja" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	cd %BUILDDIR%/latex
+	make all-pdf-ja
+	cd %~dp0
+	echo.
+	echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+if "%1" == "coverage" (
+	%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of coverage in the sources finished, look at the ^
+results in %BUILDDIR%/coverage/python.txt.
+	goto end
+)
+
+if "%1" == "xml" (
+	%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The XML files are in %BUILDDIR%/xml.
+	goto end
+)
+
+if "%1" == "pseudoxml" (
+	%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+	goto end
+)
+
+:end
diff --git a/docs/source/_ext/djangodocs.py b/docs/source/_ext/djangodocs.py
new file mode 100644
index 0000000..3b59f3c
--- /dev/null
+++ b/docs/source/_ext/djangodocs.py
@@ -0,0 +1,10 @@
+# taken from:
+# http://reinout.vanrees.org/weblog/2012/12/01/django-intersphinx.html
+
+
+def setup(app):
+    app.add_crossref_type(
+        directivename="setting",
+        rolename="setting",
+        indextemplate="pair: %s; setting",
+    )
diff --git a/docs/source/_static/treebeard-admin-advanced.png b/docs/source/_static/treebeard-admin-advanced.png
new file mode 100644
index 0000000..28e9539
Binary files /dev/null and b/docs/source/_static/treebeard-admin-advanced.png differ
diff --git a/docs/source/_static/treebeard-admin-basic.png b/docs/source/_static/treebeard-admin-basic.png
new file mode 100644
index 0000000..b0d010f
Binary files /dev/null and b/docs/source/_static/treebeard-admin-basic.png differ
diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst
index 86d5756..7a92709 100644
--- a/docs/source/tutorial.rst
+++ b/docs/source/tutorial.rst
@@ -1,22 +1,26 @@
 Tutorial
 ========
 
-Create a basic model for your tree. In this example we'll use a Materialized
-Path tree:
+Create a basic model for your tree. In this example we'll use a Materialized Path tree:
 
 .. code-block:: python
 
     from django.db import models
+    from django.utils.encoding import python_2_unicode_compatible
+
     from treebeard.mp_tree import MP_Node
 
+    @python_2_unicode_compatible
     class Category(MP_Node):
         name = models.CharField(max_length=30)
 
         node_order_by = ['name']
 
-        def __unicode__(self):
-            return 'Category: %s' % self.name
+        def __str__(self):
+            return 'Category: {}'.format(self.name)
 
+This example works on Python 3 as well as on Python 2. If you don't need Python 2 support
+remove the ``@python_2_unicode_compatible`` decorator.
 
 
 Run syncdb:
diff --git a/setup.cfg b/setup.cfg
index 861a9f5..8bfd5a1 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,4 @@
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff --git a/treebeard/__init__.py b/treebeard/__init__.py
index 41458ca..b8edffd 100644
--- a/treebeard/__init__.py
+++ b/treebeard/__init__.py
@@ -17,4 +17,4 @@ Release logic:
 11. git commit -m 'Start with <version>'
 12. git push
 """
-__version__ = '4.1.0'
+__version__ = '4.1.2'
diff --git a/treebeard/mp_tree.py b/treebeard/mp_tree.py
index bc3698f..99753b6 100644
--- a/treebeard/mp_tree.py
+++ b/treebeard/mp_tree.py
@@ -17,6 +17,34 @@ from treebeard.exceptions import InvalidMoveToDescendant, PathOverflow,\
     NodeAlreadySaved
 
 
+# The following functions generate vendor-specific SQL functions
+def sql_concat(*args, **kwargs):
+    vendor = kwargs.pop('vendor', None)
+    if vendor == 'mysql':
+        return 'CONCAT({})'.format(', '.join(args))
+    if vendor == 'microsoft':
+        return ' + '.join(args)
+    return '||'.join(args)
+
+
+def sql_length(field, vendor=None):
+    if vendor == 'microsoft':
+        return 'LEN({})'.format(field)
+    return 'LENGTH({})'.format(field)
+
+
+def sql_substr(field, pos, length=None, **kwargs):
+    vendor = kwargs.pop('vendor', None)
+    function = 'SUBSTR({field}, {pos})'
+    if length:
+        function = 'SUBSTR({field}, {pos}, {length})'
+    if vendor == 'microsoft':
+        if not length:
+            length = 'LEN({})'.format(field)
+        function = 'SUBSTRING({field}, {pos}, {length})'
+    return function.format(field=field, pos=pos, length=length)
+
+
 def get_result_class(cls):
     """
     For the given model class, determine what class we should use for the
@@ -261,7 +289,7 @@ class MP_ComplexAddMoveHandler(MP_AddHandler):
             # http://dev.mysql.com/doc/refman/5.0/en/ansi-mode.html
             sqlpath = "CONCAT(%s, SUBSTR(path, %s))"
         else:
-            sqlpath = "%s||SUBSTR(path, %s)"
+            sqlpath = sql_concat("%s", sql_substr("path", "%s", vendor=vendor), vendor=vendor)
 
         sql2 = ["path=%s" % (sqlpath, )]
         vals = [newpath, len(oldpath) + 1]
@@ -270,7 +298,7 @@ class MP_ComplexAddMoveHandler(MP_AddHandler):
             # done in another query
             # doesn't even work with sql_mode='ANSI,TRADITIONAL'
             # TODO: FIND OUT WHY?!?? right now I'm just blaming mysql
-            sql2.append("depth=LENGTH(%s)/%%s" % (sqlpath, ))
+            sql2.append(("depth=" + sql_length("%s", vendor=vendor) + "/%%s") % (sqlpath, ))
             vals.extend([newpath, len(oldpath) + 1, self.node_cls.steplen])
         sql3 = "WHERE path LIKE %s"
         vals.extend([oldpath + '%'])
@@ -544,7 +572,8 @@ class MP_MoveHandler(MP_ComplexAddMoveHandler):
         :returns: The sql needed to update the depth of all the nodes in a
                   branch.
         """
-        sql = "UPDATE %s SET depth=LENGTH(path)/%%s WHERE path LIKE %%s" % (
+        vendor = self.node_cls.get_database_vendor('write')
+        sql = ("UPDATE %s SET depth=" + sql_length("path", vendor=vendor) + "/%%s WHERE path LIKE %%s") % (
             connection.ops.quote_name(
                 get_result_class(self.node_cls)._meta.db_table), )
         vals = [self.node_cls.steplen, path + '%']
@@ -660,6 +689,7 @@ class MP_Node(Node):
                   5. a list of ids nodes that report a wrong number of children
         """
         cls = get_result_class(cls)
+        vendor = cls.get_database_vendor('write')
 
         evil_chars, bad_steplen, orphans = [], [], []
         wrong_depth, wrong_numchild = [], []
@@ -688,7 +718,7 @@ class MP_Node(Node):
             real_numchild = cls.objects.filter(
                 path__range=cls._get_children_path_interval(node.path)
             ).extra(
-                where=['LENGTH(path)/%d=%d' % (cls.steplen, node.depth + 1)]
+                where=[(sql_length("path", vendor=vendor) + '/%d=%d') % (cls.steplen, node.depth + 1)]
             ).count()
             if real_numchild != node.numchild:
                 wrong_numchild.append(node.pk)
@@ -735,6 +765,7 @@ class MP_Node(Node):
                patches are welcome).
         """
         cls = get_result_class(cls)
+        vendor = cls.get_database_vendor('write')
 
         if destructive:
             dump = cls.dump_bulk(None, True)
@@ -745,10 +776,11 @@ class MP_Node(Node):
 
             # fix the depth field
             # we need the WHERE to speed up postgres
-            sql = "UPDATE %s "\
-                  "SET depth=LENGTH(path)/%%s "\
-                  "WHERE depth!=LENGTH(path)/%%s" % (
-                      connection.ops.quote_name(cls._meta.db_table), )
+            sql = (
+                "UPDATE %s "
+                "SET depth=" + sql_length("path", vendor=vendor) + "/%%s "
+                "WHERE depth!=" + sql_length("path", vendor=vendor) + "/%%s"
+            ) % (connection.ops.quote_name(cls._meta.db_table), )
             vals = [cls.steplen, cls.steplen]
             cursor.execute(sql, vals)
 
@@ -756,18 +788,18 @@ class MP_Node(Node):
             vals = ['_' * cls.steplen]
             # the cake and sql portability are a lie
             if cls.get_database_vendor('read') == 'mysql':
-                sql = "SELECT tbn1.path, tbn1.numchild, ("\
-                      "SELECT COUNT(1) "\
-                      "FROM %(table)s AS tbn2 "\
-                      "WHERE tbn2.path LIKE "\
-                      "CONCAT(tbn1.path, %%s)) AS real_numchild "\
-                      "FROM %(table)s AS tbn1 "\
-                      "HAVING tbn1.numchild != real_numchild" % {
-                          'table': connection.ops.quote_name(
-                              cls._meta.db_table)}
+                sql = (
+                    "SELECT tbn1.path, tbn1.numchild, ("
+                    "SELECT COUNT(1) "
+                    "FROM %(table)s AS tbn2 "
+                    "WHERE tbn2.path LIKE " +
+                    sql_concat("tbn1.path", "%%s", vendor=vendor) + ") AS real_numchild "
+                    "FROM %(table)s AS tbn1 "
+                    "HAVING tbn1.numchild != real_numchild"
+                ) % {'table': connection.ops.quote_name(cls._meta.db_table)}
             else:
                 subquery = "(SELECT COUNT(1) FROM %(table)s AS tbn2"\
-                           " WHERE tbn2.path LIKE tbn1.path||%%s)"
+                           " WHERE tbn2.path LIKE " + sql_concat("tbn1.path", "%%s", vendor=vendor) + ")"
                 sql = ("SELECT tbn1.path, tbn1.numchild, " + subquery +
                        " FROM %(table)s AS tbn1 WHERE tbn1.numchild != " +
                        subquery)
@@ -838,6 +870,7 @@ class MP_Node(Node):
         #~
 
         cls = get_result_class(cls)
+        vendor = cls.get_database_vendor('write')
 
         if parent:
             depth = parent.depth + 1
@@ -848,19 +881,23 @@ class MP_Node(Node):
             params = []
             extrand = ''
 
-        sql = 'SELECT * FROM %(table)s AS t1 INNER JOIN '\
-              ' (SELECT '\
-              '   SUBSTR(path, 1, %(subpathlen)s) AS subpath, '\
-              '   COUNT(1)-1 AS count '\
-              '   FROM %(table)s '\
-              '   WHERE depth >= %(depth)s %(extrand)s'\
-              '   GROUP BY subpath) AS t2 '\
-              ' ON t1.path=t2.subpath '\
-              ' ORDER BY t1.path' % {
-                  'table': connection.ops.quote_name(cls._meta.db_table),
-                  'subpathlen': depth * cls.steplen,
-                  'depth': depth,
-                  'extrand': extrand}
+        subpath = sql_substr("path", "1", "%(subpathlen)s", vendor=vendor)
+
+        sql = (
+            'SELECT * FROM %(table)s AS t1 INNER JOIN '
+            ' (SELECT '
+            '   ' + subpath + ' AS subpath, '
+            '   COUNT(1)-1 AS count '
+            '   FROM %(table)s '
+            '   WHERE depth >= %(depth)s %(extrand)s'
+            '   GROUP BY '+ subpath + ') AS t2 '
+            ' ON t1.path=t2.subpath '
+            ' ORDER BY t1.path'
+        ) % {
+            'table': connection.ops.quote_name(cls._meta.db_table),
+            'subpathlen': depth * cls.steplen,
+            'depth': depth,
+                'extrand': extrand}
         cursor = cls._get_database_cursor('write')
         cursor.execute(sql, params)
 
diff --git a/treebeard/templates/admin/tree_change_list_results.html b/treebeard/templates/admin/tree_change_list_results.html
index 716e6db..4d7d7ae 100644
--- a/treebeard/templates/admin/tree_change_list_results.html
+++ b/treebeard/templates/admin/tree_change_list_results.html
@@ -4,35 +4,37 @@
     </div>
 {% endif %}
 {% if results %}
-    <table cellspacing="0" id="result_list">
-        <thead>
-        <tr>
-            {% for header in result_headers %}
-                <th{{ header.class_attrib }}>
-                {% if header.sortable %}<a href="{{ header.url }}"
-                                           {% if header.tooltip %}title="{{ header.tooltip }}"{% endif %}>{% endif %}
-                {{ header.text|capfirst }}
-                {% if header.sortable %}</a>{% endif %}</th>{% endfor %}
-        </tr>
-        </thead>
-        <tbody>
-        {% for node_id, parent_id, node_level, has_children, result in results %}
-            <tr id="node-{{ node_id }}-id" class="{% cycle 'row1' 'row2' %}"
-                level="{{ node_level }}" children-num="{{ children_num }}"
-                parent="{{ parent_id }}" node="{{ node_id }}">
-                {% for item in result %}
-                    {% if forloop.counter == 1 %}
-                        {% for spacer in item.depth %}<span class="grab"> 
-                            </span>{% endfor %}
-                    {% endif %}
-                    {{ item }}
-                {% endfor %}</tr>
-        {% endfor %}
-        </tbody>
-    </table>
-    <input type="hidden" id="has-filters" value="{{ filtered|yesno:"1,0" }}"/>
-    <script>
-        var MOVE_NODE_ENDPOINT = 'move/';
-    </script>
+    <div class="results">
+        <table cellspacing="0" id="result_list">
+            <thead>
+            <tr>
+                {% for header in result_headers %}
+                    <th{{ header.class_attrib }}>
+                    {% if header.sortable %}<a href="{{ header.url }}"
+                                               {% if header.tooltip %}title="{{ header.tooltip }}"{% endif %}>{% endif %}
+                    {{ header.text|capfirst }}
+                    {% if header.sortable %}</a>{% endif %}</th>{% endfor %}
+            </tr>
+            </thead>
+            <tbody>
+            {% for node_id, parent_id, node_level, has_children, result in results %}
+                <tr id="node-{{ node_id }}-id" class="{% cycle 'row1' 'row2' %}"
+                    level="{{ node_level }}" children-num="{{ children_num }}"
+                    parent="{{ parent_id }}" node="{{ node_id }}">
+                    {% for item in result %}
+                        {% if forloop.counter == 1 %}
+                            {% for spacer in item.depth %}<span class="grab"> 
+                                </span>{% endfor %}
+                        {% endif %}
+                        {{ item }}
+                    {% endfor %}</tr>
+            {% endfor %}
+            </tbody>
+        </table>
+        <input type="hidden" id="has-filters" value="{{ filtered|yesno:"1,0" }}"/>
+        <script>
+            var MOVE_NODE_ENDPOINT = 'move/';
+        </script>
+    </div>
 {% endif %}
 
diff --git a/treebeard/templates/admin/tree_list_results.html b/treebeard/templates/admin/tree_list_results.html
index 69099ee..a4fe2c2 100644
--- a/treebeard/templates/admin/tree_list_results.html
+++ b/treebeard/templates/admin/tree_list_results.html
@@ -1,4 +1,3 @@
-{% load cycle from future  %}
 {% if results %}
     <ul>
         {% for result in results %}
diff --git a/treebeard/tests/settings.py b/treebeard/tests/settings.py
index 876c735..9b26215 100644
--- a/treebeard/tests/settings.py
+++ b/treebeard/tests/settings.py
@@ -36,6 +36,19 @@ def get_db_conf():
             'HOST': '127.0.0.1',
             'PORT': '',
         }
+    elif database_engine == "mssql":
+        return {
+            'ENGINE': 'sql_server.pyodbc',
+            'NAME': 'master',
+            'USER': 'sa',
+            'PASSWORD': 'Password12!',
+            'HOST': '(local)\SQL2016',
+            'PORT': '',
+            'OPTIONS': {
+                'driver': 'SQL Server Native Client 11.0',
+                'MARS_Connection': 'True',
+            },
+        }
 
 DATABASES = {'default': get_db_conf()}
 SECRET_KEY = '7r33b34rd'

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-django-treebeard.git



More information about the Python-modules-commits mailing list