Skip to content

Commit

Permalink
Fix complex multisort in Python 3.
Browse files Browse the repository at this point in the history
  • Loading branch information
sallner committed Oct 5, 2018
1 parent f64436b commit dad81e2
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Expand Up @@ -21,6 +21,7 @@ Changelog
- Fix bugs with ``<dtml-in>``:

- Raise proper error if prefix is not simple.
- Fix complex multisort in Python 3.


3.0b4 (2018-07-12)
Expand Down
3 changes: 2 additions & 1 deletion src/DocumentTemplate/DT_In.py
Expand Up @@ -333,6 +333,7 @@
from operator import itemgetter
import sys
import re
import functools

from DocumentTemplate.DT_Util import ParseError, parse_params, name_param
from DocumentTemplate.DT_Util import str, join_unicode
Expand Down Expand Up @@ -836,7 +837,7 @@ def sort_sequence(self, sequence, md):

if need_sortfunc:
by = SortBy(multsort, sf_list)
s.sort(by)
s.sort(key=functools.cmp_to_key(by))
else:
# In python 3 a key is required when tuples in the list have
# the same sort key to prevent attempting to compare the second
Expand Down
77 changes: 76 additions & 1 deletion src/DocumentTemplate/tests/test_DT_In.py
Expand Up @@ -7,6 +7,13 @@ class DummySection(object):
blocks = ['dummy']


class Dummy(object):
"""Dummy with attribute"""

def __init__(self, name, number=0):
self.name = name
self.number = number

class TestIn(unittest.TestCase):
"""Testing ..DT_in.InClass."""

Expand Down Expand Up @@ -54,4 +61,72 @@ def test_DT_In__InClass____init__1(self):
'<dtml-var sequence-item>'
'</dtml-in>')
with self.assertRaisesRegexp(ParseError, '^prefix is not a simple '):
html(seq=sequence)
html(seq=sequence)

def test_DT_In__InClass__renderwob__06(self):
"""It allows multisort."""
seq = [Dummy('alberta', 2), Dummy('alberta', 1), Dummy('barnie', 1)]
html = self.doc_class(
'<dtml-in seq sort="name,number">'
'Item <dtml-var sequence-number>: '
'<dtml-var sequence-var-name> , <dtml-var sequence-var-number>'
'</dtml-in>')
res = html(seq=seq)
expected = (
'Item 1: alberta , 1'
'Item 2: alberta , 2'
'Item 3: barnie , 1')
self.assertEqual(res, expected)
html = self.doc_class(
'<dtml-in seq sort="number,name">'
'Item <dtml-var sequence-number>: '
'<dtml-var sequence-var-name> , <dtml-var sequence-var-number>'
'</dtml-in>')
res = html(seq=seq)
expected = (
'Item 1: alberta , 1'
'Item 2: barnie , 1'
'Item 3: alberta , 2')
self.assertEqual(res, expected)

def test_DT_In__InClass__renderwob__07(self):
"""It allows complex multisort. Smoke test."""
# This test also covers most of `SortBy`.
seq = [Dummy('alberta', 2), Dummy('alberta', 1), Dummy('barnie', 1)]
html = self.doc_class(
'<dtml-in seq sort="name/nocase/asc,number/cmp/desc">'
'Item <dtml-var sequence-number>: '
'<dtml-var sequence-var-name> , <dtml-var sequence-var-number>'
'</dtml-in>')
res = html(seq=seq)
expected = (
'Item 1: alberta , 2'
'Item 2: alberta , 1'
'Item 3: barnie , 1')
self.assertEqual(res, expected)
# It can sort the other way round
html = self.doc_class(
'<dtml-in seq sort="number/cmp/asc,name/strcoll/desc">'
'Item <dtml-var sequence-number>: '
'<dtml-var sequence-var-name> , <dtml-var sequence-var-number>'
'</dtml-in>')
res = html(seq=seq)
expected = (
'Item 1: barnie , 1'
'Item 2: alberta , 1'
'Item 3: alberta , 2')
self.assertEqual(res, expected)
# It is possible to omit parts of complex sort.
seq.append(Dummy('alberta', 1))
html = self.doc_class(
'<dtml-in seq sort="number,name/strcoll_nocase">'
'Item <dtml-var sequence-number>: '
'<dtml-var sequence-var-name> , <dtml-var sequence-var-number>'
'</dtml-in>')
res = html(seq=seq)
expected = (
'Item 1: alberta , 1'
'Item 2: alberta , 1'
'Item 3: barnie , 1'
'Item 4: alberta , 2')
self.assertEqual(res, expected)

0 comments on commit dad81e2

Please sign in to comment.