diff --git a/CHANGES.rst b/CHANGES.rst
index ddb77d5..b9822a0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -7,12 +7,14 @@ Changelog
Breaking changes
++++++++++++++++
-- Removed ``VSEval`` module. Please use DT_Util.EVal now.
+- Remove ``VSEval`` module. Please use DT_Util.EVal now.
+
+- Remove ``DTtestExpr`` module. It contained nothing useful.
Features
++++++++
-- Added support for Python 3.7.
+- Add support for Python 3.7.
Bugfixes
++++++++
@@ -33,6 +35,7 @@ Bugfixes
- Raise proper error if prefix is not simple.
- Fix complex multisort in Python 3.
+ - Fix iteration over list of tuples in Python 3.
3.0b4 (2018-07-12)
diff --git a/src/DocumentTemplate/DT_In.py b/src/DocumentTemplate/DT_In.py
index 059567a..028f500 100644
--- a/src/DocumentTemplate/DT_In.py
+++ b/src/DocumentTemplate/DT_In.py
@@ -341,6 +341,7 @@
from DocumentTemplate.DT_Util import ValidationError, Eval
from DocumentTemplate.DT_Util import simple_name, add_with_prefix
from DocumentTemplate.DT_InSV import sequence_variables, opt
+from zope.sequencesort.ssort import _Smallest
if sys.version_info > (3, 0):
unicode = str
@@ -831,7 +832,7 @@ def sort_sequence(self, sequence, md):
try:
k = k()
except Exception:
- pass
+ k = _Smallest
s.append((k, client))
diff --git a/src/DocumentTemplate/DTtestExpr.py b/src/DocumentTemplate/DTtestExpr.py
deleted file mode 100644
index f3d2918..0000000
--- a/src/DocumentTemplate/DTtestExpr.py
+++ /dev/null
@@ -1,49 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Foundation and Contributors.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
-#
-##############################################################################
-
-from DocumentTemplate import HTML
-
-
-def test1():
- print(HTML(
- 'area code=')(phone='7035551212'))
-
-
-def test2():
- print(HTML(
- 'area code=')(phone='7035551212'))
-
-
-def test3():
- print(HTML(
- 'area code=')(phone='7035551212'))
-
-
-def test4():
- h = HTML(
- """
-
- level was 1
-
- level was 2
-
- level was 3
-
- level was something else
-
- """)
-
- for i in range(4):
- print('-' * 77)
- print('%s%s' % (i, h(level=i)))
- print('-' * 77)
diff --git a/src/DocumentTemplate/pDocumentTemplate.py b/src/DocumentTemplate/pDocumentTemplate.py
index 80cece4..ea7c041 100644
--- a/src/DocumentTemplate/pDocumentTemplate.py
+++ b/src/DocumentTemplate/pDocumentTemplate.py
@@ -13,7 +13,7 @@
"""This module is no longer actively used.
"""
-from DocumentTemplate._DocumentTemplate import ( # NOQA
+from DocumentTemplate._DocumentTemplate import ( # noqa: F401 pragma: nocover
DictInstance,
InstanceDict,
join_unicode,
@@ -25,4 +25,4 @@
import warnings
warnings.warn('pDocumentTemplate is not longer in active use. '
'It remains only as an implementation reference.',
- DeprecationWarning)
+ DeprecationWarning) # pragma: nocover
diff --git a/src/DocumentTemplate/tests/test_DT_In.py b/src/DocumentTemplate/tests/test_DT_In.py
index 35a0944..3c8372c 100644
--- a/src/DocumentTemplate/tests/test_DT_In.py
+++ b/src/DocumentTemplate/tests/test_DT_In.py
@@ -10,9 +10,14 @@ class DummySection(object):
class Dummy(object):
"""Dummy with attribute"""
- def __init__(self, name, number=0):
+ def __init__(self, name, number=0, _callable=0):
self.name = name
self.number = number
+ self._callable = _callable
+
+ @property
+ def maybe_callable(self):
+ return self._callable
class TestIn(unittest.TestCase):
@@ -306,6 +311,53 @@ def test_DT_In__InClass__renderwob__07(self):
'Item 4: alberta , 2')
self.assertEqual(res, expected)
+ def test_DT_In__InClass__renderwob__08(self):
+ """It can iterate over list of tuples."""
+ seq = [('alberta', 3), ('ylberta', 1), ('barnie', 2)]
+ html = self.doc_class(
+ ''
+ 'Item : '
+ ''
+ '')
+ res = html(seq=seq)
+ expected = (
+ 'Item 1: 3'
+ 'Item 2: 1'
+ 'Item 3: 2')
+ self.assertEqual(res, expected)
+ # also sorted
+ html = self.doc_class(
+ ''
+ 'Item : '
+ ''
+ '')
+ res = html(seq=seq)
+ expected = (
+ 'Item 1: 3'
+ 'Item 2: 2'
+ 'Item 3: 1')
+ self.assertEqual(res, expected)
+
+ def test_DT_In__InClass__renderwob__09(self):
+ """It can also contain callables as values."""
+ # It catches errors and treats those as smallest
+ seq = [
+ Dummy('alberta', _callable=lambda: 3),
+ Dummy('ylberta', _callable=lambda: 0),
+ Dummy('barnie', _callable=lambda: [][2]),
+ ]
+ html = self.doc_class(
+ ''
+ 'Item : '
+ ''
+ '')
+ res = html(seq=seq)
+ expected = (
+ 'Item 1: barnie'
+ 'Item 2: ylberta'
+ 'Item 3: alberta')
+ self.assertEqual(res, expected)
+
def test_DT_In__InClass__renderwb__01(self):
"""It does not allow strings as sequence in batch mode."""
html = self.doc_class(
@@ -407,6 +459,48 @@ def test_DT_In__InClass__renderwb__05(self):
'Item 3: alberta')
self.assertEqual(res, expected)
+ def test_DT_In__InClass__renderwb__06(self):
+ """It can access previous and next batch of a sequence."""
+ seq = [Dummy('alberta'), Dummy('berta'), Dummy('barnie')]
+ html = self.doc_class(
+ ''
+ 'Prev index: '
+ ''
+ ''
+ 'Next index: '
+ '')
+ res = html(seq=seq)
+ expected = ('Prev index: 1 '
+ 'Next index: 3')
+ self.assertEqual(res, expected)
+ # Also with else clauses for edges of the sequence
+ html = self.doc_class(
+ ''
+ 'Prev index: '
+ ''
+ 'No prev '
+ ''
+ ''
+ 'Next index: '
+ ''
+ 'No next'
+ '')
+ res = html(seq=seq)
+ expected = ('No prev '
+ 'No next')
+ self.assertEqual(res, expected)
+ # or it renders nothing if no else is given
+ html = self.doc_class(
+ ''
+ 'Prev index: '
+ ''
+ ''
+ 'Next index: '
+ '')
+ res = html(seq=seq)
+ expected = ''
+ self.assertEqual(res, expected)
+
def test_DT_In__make_sortfunction__1(self):
"""It allows two slashes at maximum in sort expression."""
seq = [Dummy('alberta'), Dummy('berta'), Dummy('barnie')]
diff --git a/tox.ini b/tox.ini
index 6368fd8..7cd86f5 100644
--- a/tox.ini
+++ b/tox.ini
@@ -30,7 +30,7 @@ commands =
coverage combine
coverage html
coverage xml
- coverage report --fail-under=68
+ coverage report --fail-under=69.5
[testenv:flake8]
basepython = python3.6