Commit 2b79f571 authored by Arnaud Fontaine's avatar Arnaud Fontaine

py3: cmp()-based comparison and sorting have been dropped.

key()-based sorting is now used instead, available since Python 2.4.
parent 0f175cc0
...@@ -50,9 +50,6 @@ def display(x): ...@@ -50,9 +50,6 @@ def display(x):
display_cache[x] = display_funct(x) display_cache[x] = display_funct(x)
return display_cache[x] return display_cache[x]
def sort(x,y):
return cmp(display(x), display(y))
def getItemList(category=None, portal_path=None, mirror=0, omit_filter=0, def getItemList(category=None, portal_path=None, mirror=0, omit_filter=0,
simulation_state=None): simulation_state=None):
"""Returns a list of Account path items. """ """Returns a list of Account path items. """
...@@ -71,7 +68,7 @@ def getItemList(category=None, portal_path=None, mirror=0, omit_filter=0, ...@@ -71,7 +68,7 @@ def getItemList(category=None, portal_path=None, mirror=0, omit_filter=0,
portal_type='Account', portal_type='Account',
base=0, base=0,
display_method=display, display_method=display,
sort_method=sort, sort_key=display,
filter=filter_dict) filter=filter_dict)
return item_list return item_list
......
if not portal_type: if not portal_type:
portal_type = context.getPortalObject().getPortalAccountingMovementTypeList() portal_type = context.getPortalObject().getPortalAccountingMovementTypeList()
sort_dict = { 'income': 0, sort_dict = {
'expense': -2, 'bank': -3,
'receivable': -2, 'income': 0,
'payable': 0, 'expense': -2,
'collected_vat': -1, 'receivable': -2,
'refundable_vat': -1 } 'payable': 0,
'collected_vat': -1,
'refundable_vat': -1,
}
def getAccountingTransactionLineSortKey(line): def getAccountingTransactionLineSortKey(line):
return sort_dict.get(line.getId(), line.getIntIndex() or line.getIntId()) return sort_dict.get(line.getId(), (line.getIntIndex() or line.getIntId() or 0))
return sorted(context.contentValues(portal_type=portal_type, checked_permission="View"), key=getAccountingTransactionLineSortKey) return sorted(context.contentValues(portal_type=portal_type, checked_permission="View"), key=getAccountingTransactionLineSortKey)
...@@ -48,6 +48,13 @@ whether this is really required. ...@@ -48,6 +48,13 @@ whether this is really required.
from erp5.component.document.MovementGroup import MovementGroup from erp5.component.document.MovementGroup import MovementGroup
def _getSign(quantity):
if quantity == 0:
return 0
return 1 if quantity > 0 else -1
class QuantitySignMovementGroup(MovementGroup): class QuantitySignMovementGroup(MovementGroup):
""" """
The purpose of MovementGroup is to define how movements are grouped, The purpose of MovementGroup is to define how movements are grouped,
...@@ -59,7 +66,7 @@ class QuantitySignMovementGroup(MovementGroup): ...@@ -59,7 +66,7 @@ class QuantitySignMovementGroup(MovementGroup):
def _getPropertyDict(self, movement, **kw): def _getPropertyDict(self, movement, **kw):
property_dict = {} property_dict = {}
quantity = movement.getQuantity() quantity = movement.getQuantity()
property_dict['quantity_sign'] = cmp(quantity, 0) property_dict['quantity_sign'] = _getSign(quantity)
return property_dict return property_dict
def _separate(self, movement_list, **kw): def _separate(self, movement_list, **kw):
...@@ -68,7 +75,7 @@ class QuantitySignMovementGroup(MovementGroup): ...@@ -68,7 +75,7 @@ class QuantitySignMovementGroup(MovementGroup):
tmp_list = [[], [], []] # -1:minus, 0:zero, 1:plus tmp_list = [[], [], []] # -1:minus, 0:zero, 1:plus
for movement in movement_list: for movement in movement_list:
tmp_list[cmp(movement.getQuantity(), 0)].append(movement) tmp_list[_getSign(movement.getQuantity())].append(movement)
if len(tmp_list[1]): if len(tmp_list[1]):
if len(tmp_list[-1]): if len(tmp_list[-1]):
return[ return[
......
...@@ -36,6 +36,7 @@ from erp5.component.document.Amount import Amount ...@@ -36,6 +36,7 @@ from erp5.component.document.Amount import Amount
from erp5.component.module.MovementGroup import MovementGroupNode from erp5.component.module.MovementGroup import MovementGroupNode
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5Type.Utils import OrderableKey
from erp5.component.module.ExplanationCache import _getExplanationCache from erp5.component.module.ExplanationCache import _getExplanationCache
from DateTime import DateTime from DateTime import DateTime
from Acquisition import aq_parent, aq_inner from Acquisition import aq_parent, aq_inner
...@@ -781,15 +782,16 @@ class BuilderMixin(XMLObject, Amount, Predicate): ...@@ -781,15 +782,16 @@ class BuilderMixin(XMLObject, Amount, Predicate):
for i in self.getPortalObject().portal_categories.collect_order_group.contentValues(): for i in self.getPortalObject().portal_categories.collect_order_group.contentValues():
category_index_dict[i.getId()] = i.getIntIndex() category_index_dict[i.getId()] = i.getIntIndex()
def sort_movement_group(a, b): def sort_movement_group_key(a):
return cmp(category_index_dict.get(a.getCollectOrderGroup()), return (
category_index_dict.get(b.getCollectOrderGroup())) or \ OrderableKey(category_index_dict.get(a.getCollectOrderGroup())),
cmp(a.getIntIndex(), b.getIntIndex()) OrderableKey(a.getIntIndex()),
)
if portal_type is None: if portal_type is None:
portal_type = self.getPortalMovementGroupTypeList() portal_type = self.getPortalMovementGroupTypeList()
movement_group_list = [x for x in self.contentValues(filter={'portal_type': portal_type}) \ movement_group_list = [x for x in self.contentValues(filter={'portal_type': portal_type}) \
if collect_order_group is None or collect_order_group == x.getCollectOrderGroup()] if collect_order_group is None or collect_order_group == x.getCollectOrderGroup()]
return sorted(movement_group_list, sort_movement_group) return sorted(movement_group_list, key=sort_movement_group_key)
# XXX category name is hardcoded. # XXX category name is hardcoded.
def getDeliveryMovementGroupList(self, **kw): def getDeliveryMovementGroupList(self, **kw):
......
...@@ -24,8 +24,5 @@ else: ...@@ -24,8 +24,5 @@ else:
or career.getStopDate() < to_date : or career.getStopDate() < to_date :
career_list.append(career) career_list.append(career)
def date_cmp(a, b): career_list.sort(key=lambda a: a.getStartDate())
return cmp(a.getStartDate(), b.getStartDate())
career_list.sort(date_cmp)
return career_list return career_list
...@@ -90,11 +90,7 @@ for portal_type in portal_type_list: ...@@ -90,11 +90,7 @@ for portal_type in portal_type_list:
obj['total'] = line_counter obj['total'] = line_counter
append(obj) append(obj)
# sort lines line_list.sort(key=lambda a:a['document_type'])
def cmpType(a, b):
return cmp(a['document_type'], b['document_type'])
line_list.sort(cmpType)
# build stat line # build stat line
obj = Object(uid="new_") obj = Object(uid="new_")
......
...@@ -31,9 +31,6 @@ dest_event_list = portal.portal_catalog(portal_type=event_type_list, default_des ...@@ -31,9 +31,6 @@ dest_event_list = portal.portal_catalog(portal_type=event_type_list, default_des
event_list = list(source_event_list)+list(dest_event_list) event_list = list(source_event_list)+list(dest_event_list)
def sortDate(a, b): event_list.sort(key=lambda a: a.getStartDate())
return cmp(a.getStartDate(), b.getStartDate())
event_list.sort(sortDate)
return event_list return event_list
...@@ -68,6 +68,7 @@ for item in item_list: ...@@ -68,6 +68,7 @@ for item in item_list:
else: else:
sub_field_dict[item_key]['title'] = base_category sub_field_dict[item_key]['title'] = base_category
sub_field_values = sub_field_dict.values() return sorted(
sub_field_values.sort(key=lambda d:d['int_index']) sub_field_dict.values(),
return sub_field_values key=lambda d: d['int_index']
)
...@@ -68,10 +68,7 @@ for person in person_value_list: ...@@ -68,10 +68,7 @@ for person in person_value_list:
total=person_total, total=person_total,
**result_dict)) **result_dict))
result_list.sort(lambda a,b: cmp( result_list.sort(key=lambda r: (r.person_career_reference or '', r.person_title or ''))
a.person_career_reference or a.person_title,
b.person_career_reference or b.person_title))
request.set('total_time', total_time) request.set('total_time', total_time)
request.set('total_time_per_resource', total_time_per_resource) request.set('total_time_per_resource', total_time_per_resource)
......
...@@ -3,7 +3,7 @@ column_item_list = [ ('person_career_reference', 'Employee Number'), ...@@ -3,7 +3,7 @@ column_item_list = [ ('person_career_reference', 'Employee Number'),
non_translatable_column_item_list = context\ non_translatable_column_item_list = context\
.PersonModule_getLeaveRequestReportListboxUntranslatableColumnList() .PersonModule_getLeaveRequestReportListboxUntranslatableColumnList()
non_translatable_column_item_list.sort(lambda a,b: cmp(a[1], b[1])) non_translatable_column_item_list.sort(key=lambda v: v[1])
column_item_list.extend(non_translatable_column_item_list) column_item_list.extend(non_translatable_column_item_list)
column_item_list.append(('total', 'Total')) column_item_list.append(('total', 'Total'))
......
...@@ -552,12 +552,12 @@ class BusinessConfiguration(Item): ...@@ -552,12 +552,12 @@ class BusinessConfiguration(Item):
"immediateReindexObject"]) "immediateReindexObject"])
# build # build
configuration_save_list = self.contentValues(portal_type='Configuration Save') configuration_save_list = self.contentValues(portal_type='Configuration Save')
configuration_save_list.sort(lambda x, y: cmp(x.getIntIndex(x.getIntId()), configuration_save_list.sort(key=lambda x: (x.getIntIndex(x.getIntId()) or 0))
y.getIntIndex(y.getIntId())))
for configuration_save in configuration_save_list: for configuration_save in configuration_save_list:
# XXX: check which items are configure-able # XXX: check which items are configure-able
configuration_item_list = configuration_save.contentValues() configuration_item_list = configuration_save.contentValues()
configuration_item_list.sort(lambda x, y: cmp(x.getIntId(), y.getIntId())) configuration_item_list.sort(key=lambda x: (x.getIntId() or 0))
for configurator_item in configuration_item_list: for configurator_item in configuration_item_list:
configurator_item.activate(**kw).fixConsistency( configurator_item.activate(**kw).fixConsistency(
filter={"constraint_type":"configuration"}) filter={"constraint_type":"configuration"})
......
...@@ -267,7 +267,7 @@ class TestTrashTool(ERP5TypeTestCase): ...@@ -267,7 +267,7 @@ class TestTrashTool(ERP5TypeTestCase):
bc_path = base_category.getPath().split('/')[2:-1] bc_path = base_category.getPath().split('/')[2:-1]
# check backup # check backup
backup_subobjects_ids = trash.backupObject(trashbin, bc_path, bc_id, save=1) backup_subobjects_ids = trash.backupObject(trashbin, bc_path, bc_id, save=1)
self.assertTrue(backup_subobjects_ids.keys().sort() == list(subobjects_ids).sort()) self.assertEqual(sorted(backup_subobjects_ids.keys()), sorted(subobjects_ids))
def stepBackupFolderObjectsWithSave(self, sequence=None, sequence_list=None, **kw): def stepBackupFolderObjectsWithSave(self, sequence=None, sequence_list=None, **kw):
""" """
...@@ -297,7 +297,7 @@ class TestTrashTool(ERP5TypeTestCase): ...@@ -297,7 +297,7 @@ class TestTrashTool(ERP5TypeTestCase):
bc_path = base_category.getPath().split('/')[1:-1] bc_path = base_category.getPath().split('/')[1:-1]
# check backup # check backup
backup_subobjects_ids = trash.backupObject(trashbin, bc_path, bc_id, save=0) backup_subobjects_ids = trash.backupObject(trashbin, bc_path, bc_id, save=0)
self.assertTrue(backup_subobjects_ids.keys().sort() == list(subobjects_ids).sort()) self.assertEqual(sorted(backup_subobjects_ids.keys()), sorted(subobjects_ids))
def stepBackupObjectsWithKeepingSubobjects(self, sequence=None, sequence_list=None, **kw): def stepBackupObjectsWithKeepingSubobjects(self, sequence=None, sequence_list=None, **kw):
""" """
...@@ -359,8 +359,8 @@ class TestTrashTool(ERP5TypeTestCase): ...@@ -359,8 +359,8 @@ class TestTrashTool(ERP5TypeTestCase):
def stepCheckRestore(self, sequence=None, sequence_list=None, **kw): def stepCheckRestore(self, sequence=None, sequence_list=None, **kw):
bc_id = sequence.get('bc_id') bc_id = sequence.get('bc_id')
bc = self.portal.portal_categories[bc_id] bc = self.portal.portal_categories[bc_id]
self.assertTrue( self.assertEqual(
sorted(bc.objectIds()) == sorted(sequence.get('category_id_list')) sorted(bc.objectIds()), sorted(sequence.get('category_id_list'))
) )
self.assertEqual( self.assertEqual(
len( len(
......
...@@ -92,11 +92,7 @@ for r_event in event_list: ...@@ -92,11 +92,7 @@ for r_event in event_list:
unassigned_dic[event.getSimulationState()]=unassigned_dic[event.getSimulationState()]+1 unassigned_dic[event.getSimulationState()]=unassigned_dic[event.getSimulationState()]+1
unassigned_dic['total']=unassigned_dic['total']+1 unassigned_dic['total']=unassigned_dic['total']+1
#Sort the result and add unassigned #Sort the result and add unassigned
def comparator(x, y): column_list.sort(key=lambda x: (x['ticket_type'], x['ticket_title']))
if x['ticket_type'] == y['ticket_type']:
return cmp(x['ticket_title'], y['ticket_title'])
return cmp(x['ticket_type'], y['ticket_type'])
column_list.sort(comparator)
if unassigned_dic['total']>0: column_list.append(unassigned_dic) if unassigned_dic['total']>0: column_list.append(unassigned_dic)
#fill line_list that is returned to report #fill line_list that is returned to report
line_list = [] line_list = []
......
...@@ -12,12 +12,9 @@ def getCompactTitle(category): ...@@ -12,12 +12,9 @@ def getCompactTitle(category):
title_list.reverse() title_list.reverse()
return '/'.join(title_list) return '/'.join(title_list)
def compareTitle(a, b):
return cmp(a[1], b[1])
def getCompactChildItemList(context): def getCompactChildItemList(context):
result = context.getCategoryChildItemList(display_method=getCompactTitle) result = context.getCategoryChildItemList(display_method=getCompactTitle)
result.sort(compareTitle) result.sort(key=lambda x: x[1])
return result return result
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
......
...@@ -58,7 +58,7 @@ def getRssDataAsDict(context, url, username=None, password=None): ...@@ -58,7 +58,7 @@ def getRssDataAsDict(context, url, username=None, password=None):
entry_dict['updated_parsed'] = entry.get('updated_parsed', None) entry_dict['updated_parsed'] = entry.get('updated_parsed', None)
result['items'].append(entry_dict) result['items'].append(entry_dict)
# sort by date # sort by date
result['items'] = sorted(result['items'], key=lambda k: k['updated_parsed']) result['items'] = sorted(result['items'], key=lambda k: k['updated_parsed'] or ())
result['items'].reverse() result['items'].reverse()
result['status'] = 0 result['status'] = 0
return result return result
\ No newline at end of file
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
import unittest import unittest
from DateTime import DateTime from DateTime import DateTime
from Products.ERP5Type.Utils import OrderableKey
from erp5.component.test.testBPMCore import TestBPMMixin from erp5.component.test.testBPMCore import TestBPMMixin
from six.moves import range from six.moves import range
import six import six
...@@ -341,18 +342,18 @@ class TestMRPImplementation(TestMRPMixin): ...@@ -341,18 +342,18 @@ class TestMRPImplementation(TestMRPMixin):
reference = None reference = None
movement_list.append((sm.getTradePhase(), sm.getQuantity(), movement_list.append((sm.getTradePhase(), sm.getQuantity(),
reference, sm.getIndustrialPhaseList())) reference, sm.getIndustrialPhaseList()))
movement_list.sort() movement_list.sort(key=lambda x: [OrderableKey(e) for e in x])
self.assertEqual(movement_list, sorted(( self.assertEqual(movement_list, [
('mrp/manufacturing_step_0', -10.0, None, []),
('mrp/manufacturing_step_0', -30.0, None, []), ('mrp/manufacturing_step_0', -30.0, None, []),
('mrp/manufacturing_step_0', -10.0, None, []),
('mrp/manufacturing_step_0', 10.0, ('mrp/manufacturing_step_0', 10.0,
'pr/mrp/manufacturing_step_0', ['trade_phase/mrp/manufacturing_step_0']), 'pr/mrp/manufacturing_step_0', ['trade_phase/mrp/manufacturing_step_0']),
('mrp/manufacturing_step_1', -40.0, None, []),
('mrp/manufacturing_step_1', -10.0, None, []),
('mrp/manufacturing_step_1', -10.0, ('mrp/manufacturing_step_1', -10.0,
'cr/mrp/manufacturing_step_1', ['trade_phase/mrp/manufacturing_step_0']), 'cr/mrp/manufacturing_step_1', ['trade_phase/mrp/manufacturing_step_0']),
('mrp/manufacturing_step_1', -10.0, None, []),
('mrp/manufacturing_step_1', -40.0, None, []),
('mrp/manufacturing_step_1', 10.0, 'pr', []), ('mrp/manufacturing_step_1', 10.0, 'pr', []),
))) ])
order.confirm() order.confirm()
# Build Manufacturing Order # Build Manufacturing Order
......
...@@ -16,6 +16,4 @@ for (x,y) in selection_param_list: ...@@ -16,6 +16,4 @@ for (x,y) in selection_param_list:
active_process_list = [(y,x) for (x,y) in active_process_dict.items()] active_process_list = [(y,x) for (x,y) in active_process_dict.items()]
active_process_list.sort(lambda x, y: cmp(x[1],y[1]), reverse=True ) return sorted(active_process_list, key=lambda item: item[1], reverse=True)
return active_process_list
...@@ -17,7 +17,7 @@ if active_process_path is None: ...@@ -17,7 +17,7 @@ if active_process_path is None:
active_process_value = context.getPortalObject().restrictedTraverse(active_process_path) active_process_value = context.getPortalObject().restrictedTraverse(active_process_path)
result_list = [[x.method_id, x.result] for x in active_process_value.getResultList()] result_list = [[x.method_id, x.result] for x in active_process_value.getResultList()]
result_list.sort() result_list.sort(key=str)
for [method_id, result] in result_list: for [method_id, result] in result_list:
safe_id = context.Base_getSafeIdFromString('result %s' % num) safe_id = context.Base_getSafeIdFromString('result %s' % num)
......
...@@ -58,13 +58,7 @@ for inventory in portal.portal_simulation.getInventoryList( ...@@ -58,13 +58,7 @@ for inventory in portal.portal_simulation.getInventoryList(
request.set('total_price', total_price) request.set('total_price', total_price)
def sort_method(a, b): return sorted(
employee_career_reference_diff = cmp(a.employee_career_reference, object_list,
b.employee_career_reference) key=lambda o: (o.employee_career_reference or '', o.employee_title)
if employee_career_reference_diff: )
return employee_career_reference_diff
return cmp(a.employee_title, b.employee_title)
object_list.sort(sort_method)
return object_list
...@@ -112,21 +112,14 @@ request.set('base_total', base_total) ...@@ -112,21 +112,14 @@ request.set('base_total', base_total)
request.set('total', total) request.set('total', total)
sorted_inventory_list = []
sorted_inventory_list = inventory_list.values()
# sort by salary range, and add intermediate sums if needed # sort by salary range, and add intermediate sums if needed
def sort_method(a, b): sorted_inventory_list = sorted(
salary_range_diff = cmp(a.salary_range, b.salary_range) inventory_list.values(),
if salary_range_diff: key=lambda i: (
return salary_range_diff i.salary_range or '',
employee_career_reference_diff = cmp(a.employee_career_reference, i.employee_career_reference or '',
b.employee_career_reference) i.employee_title or '',
if employee_career_reference_diff: ))
return employee_career_reference_diff
return cmp(a.employee_title, b.employee_title)
sorted_inventory_list.sort(sort_method)
i = 0 i = 0
intermediate_base_total = 0 intermediate_base_total = 0
......
...@@ -9,12 +9,9 @@ ...@@ -9,12 +9,9 @@
from Products.ERP5Type.Utils import cartesianProduct from Products.ERP5Type.Utils import cartesianProduct
from Products.ERP5Type.Message import translateString from Products.ERP5Type.Message import translateString
def sortByIntIndex(a, b):
return cmp(a.getIntIndex(), b.getIntIndex())
portal_type_list = ['Pay Sheet Model Line'] portal_type_list = ['Pay Sheet Model Line']
sub_object_list = context.getInheritedObjectValueList(portal_type_list) sub_object_list = context.getInheritedObjectValueList(portal_type_list)
sub_object_list.sort(sortByIntIndex) sub_object_list.sort(key=lambda x:x.getIntIndex())
model_line_list = sub_object_list model_line_list = sub_object_list
# remove editable model line # remove editable model line
...@@ -117,37 +114,16 @@ if batch_mode: ...@@ -117,37 +114,16 @@ if batch_mode:
return object_dict_list return object_dict_list
# sort results # sort results
def sortByTitleAscending(x, y):
return cmp(x.getTitle(), y.getTitle())
def sortByTitleDescending(x, y):
return cmp(y.getTitle(), x.getTitle())
def sortByIntIndexAscending(x, y):
return cmp(x.getIntIndex(), y.getIntIndex())
def sortByIntIndexDescending(x, y):
return cmp(y.getIntIndex(), x.getIntIndex())
sortByDefaultSortMethod = sortByIntIndexAscending
if 'sort_on' in kw: if 'sort_on' in kw:
sort_on = kw['sort_on'] sort_on = kw['sort_on']
if sort_on[0][0] == 'title' and sort_on[0][1]=='ascending': if sort_on[0][0] == 'title':
line_list.sort(sortByTitleAscending) line_list = sorted(line_list, key=lambda x: x.getTitle() or '', reverse=sort_on[0][1]=='ascending')
elif sort_on[0][0] == 'title' and sort_on[0][1]=='descending': elif sort_on[0][0] == 'int_index':
line_list.sort(sortByTitleDescending) line_list = sorted(line_list, key=lambda x: x.getIntIndex() or 0, reverse=sort_on[0][1]=='ascending')
elif sort_on[0][0] == 'int_index' and sort_on[0][1]=='ascending':
line_list.sort(sortByIntIndexAscending)
elif sort_on[0][0] == 'int_index' and sort_on[0][1]=='descending':
line_list.sort(sortByIntIndexDescending)
else: else:
line_list.sort(sortByDefaultSortMethod) line_list = sorted(line_list, key=lambda x: x.getIntIndex())
else: else:
line_list.sort(sortByDefaultSortMethod) line_list = sorted(line_list, key=lambda x: x.getIntIndex())
#return pprint.pformat(line_list) #return pprint.pformat(line_list)
return line_list return line_list
...@@ -120,38 +120,12 @@ for paysheet_line in paysheet_line_list: ...@@ -120,38 +120,12 @@ for paysheet_line in paysheet_line_list:
if 'no_slice' in object_dict: if 'no_slice' in object_dict:
line_list.append(paysheet_line.asContext(**object_dict['no_slice'])) line_list.append(paysheet_line.asContext(**object_dict['no_slice']))
reverse = False
sort_key = lambda l: (l.getIntIndex() or 0)
# sort results
def sortByTitleAscending(x, y):
return cmp(x.getTitle(), y.getTitle())
def sortByTitleDescending(x, y):
return cmp(y.getTitle(), x.getTitle())
def sortByIntIndexAscending(x, y):
return cmp(x.getIntIndex(), y.getIntIndex())
def sortByIntIndexDescending(x, y):
return cmp(y.getIntIndex(), x.getIntIndex())
sortByDefaultSortMethod = sortByIntIndexAscending
if 'sort_on' in kw: if 'sort_on' in kw:
sort_on = kw['sort_on'] sort_on = kw['sort_on']
if sort_on[0][0] == 'title' and sort_on[0][1]=='ascending': reverse = sort_on[0][1]=='descending'
line_list.sort(sortByTitleAscending) if sort_on[0][0] == 'title':
elif sort_on[0][0] == 'title' and sort_on[0][1]=='descending': sort_key = lambda l: (l.getTitle() or '')
line_list.sort(sortByTitleDescending)
elif sort_on[0][0] == 'int_index' and sort_on[0][1]=='ascending':
line_list.sort(sortByIntIndexAscending)
elif sort_on[0][0] == 'int_index' and sort_on[0][1]=='descending':
line_list.sort(sortByIntIndexDescending)
else:
line_list.sort(sortByDefaultSortMethod)
else:
line_list.sort(sortByDefaultSortMethod)
return line_list return sorted(line_list, key=sort_key, reverse=reverse)
...@@ -41,9 +41,7 @@ if depth == 0: ...@@ -41,9 +41,7 @@ if depth == 0:
category_list = [] category_list = []
#i = 1 #i = 1
month_dict_list = month_dict.keys() for year, month in sorted(month_dict.keys()):
month_dict_list.sort()
for year, month in month_dict_list:
category_list.append(here.getObject().asContext(title="%s - %s" % (year, month), category_list.append(here.getObject().asContext(title="%s - %s" % (year, month),
string_index="%s-%s" % (year, month), string_index="%s-%s" % (year, month),
)) ))
......
...@@ -24,12 +24,6 @@ task_line_list = [] ...@@ -24,12 +24,6 @@ task_line_list = []
for task in task_list: for task in task_list:
task_line_list.extend(task.contentValues(portal_type='Task Line')) task_line_list.extend(task.contentValues(portal_type='Task Line'))
def sortTaskLine(a, b): return sorted(
result = cmp(a.getStartDate(), b.getStartDate()) task_line_list,
if result == 0: key=lambda tl: (tl.hasStartDate(), tl.getStartDate(), tl.getTitle()))
result = cmp(a.getTitle(), b.getTitle())
return result
task_line_list.sort(sortTaskLine)
return task_line_list
...@@ -40,12 +40,6 @@ for task in task_list: ...@@ -40,12 +40,6 @@ for task in task_list:
task_line_list.extend(task.objectValues(portal_type=('Task Line', 'Task Report Line'))) task_line_list.extend(task.objectValues(portal_type=('Task Line', 'Task Report Line')))
def sortTaskLine(a, b): return sorted(
result = cmp(a.getStartDate(), b.getStartDate()) task_line_list,
if result == 0: key=lambda tl: (tl.getStartDate() is not None, tl.getStartDate(), tl.getTitle()))
result = cmp(a.getTitle(), b.getTitle())
return result
task_line_list.sort(sortTaskLine)
return task_line_list
...@@ -101,8 +101,7 @@ class SolverProcess(XMLObject, ActiveProcess): ...@@ -101,8 +101,7 @@ class SolverProcess(XMLObject, ActiveProcess):
if solver is None: if solver is None:
continue continue
solver_conviguration_dict = decision.getConfigurationPropertyDict() solver_conviguration_dict = decision.getConfigurationPropertyDict()
configuration_mapping = solver_conviguration_dict.items() configuration_mapping = sorted(solver_conviguration_dict.items()) # Make sure the list is sorted in canonical way
configuration_mapping.sort() # Make sure the list is sorted in canonical way
configuration_mapping = tuple(configuration_mapping) configuration_mapping = tuple(configuration_mapping)
for movement in decision.getDeliveryValueList(): for movement in decision.getDeliveryValueList():
# Detect incompatibilities # Detect incompatibilities
......
...@@ -29,40 +29,37 @@ def rank_method(trade_condition): ...@@ -29,40 +29,37 @@ def rank_method(trade_condition):
if destination_section: if destination_section:
destination_section_group = trade_condition.getDestinationSectionValue().getGroup() destination_section_group = trade_condition.getDestinationSectionValue().getGroup()
if destination_section == context.getDestinationSection(): if destination_section == context.getDestinationSection():
rank += 10 rank -= 10
else: else:
rank -= 2 rank += 2
destination = trade_condition.getDestination() destination = trade_condition.getDestination()
if destination: if destination:
if destination == context.getDestination(): if destination == context.getDestination():
rank += 10 rank -= 10
else: else:
rank -= 2 rank += 2
if trade_condition.getSourceSection(): if trade_condition.getSourceSection():
rank += 1 rank -= 1
if destination_section_group: if destination_section_group:
source_section_group = trade_condition.getSourceSectionValue().getGroup() source_section_group = trade_condition.getSourceSectionValue().getGroup()
if source_section_group: if source_section_group:
if source_section_group.startswith(destination_section_group) \ if source_section_group.startswith(destination_section_group) \
or destination_section_group.startswith(source_section_group): or destination_section_group.startswith(source_section_group):
# trade conditions where both sections are in the same group must have high priority # trade conditions where both sections are in the same group must have high priority
rank += 20 rank -= 20
if trade_condition.getSource(): if trade_condition.getSource():
rank += 1 rank -= 1
rank += len(trade_condition.getSpecialiseList()) rank -= len(trade_condition.getSpecialiseList())
if trade_condition.getValidationState() == 'validated': if trade_condition.getValidationState() == 'validated':
rank += 2 rank -= 2
return rank return rank
def sort_method(a, b):
return -cmp(rank_method(a), rank_method(b))
while count > 0 and len(trade_condition_list) == 0: while count > 0 and len(trade_condition_list) == 0:
count -= 1 count -= 1
trade_condition_list = context.portal_domains.searchPredicateList( trade_condition_list = context.portal_domains.searchPredicateList(
predicate_context, portal_type=trade_condition_portal_type_list, predicate_context, portal_type=trade_condition_portal_type_list,
tested_base_category_list=tested_base_category_list[:count], tested_base_category_list=tested_base_category_list[:count],
sort_method=sort_method) sort_key_method=rank_method)
keep_items = {} keep_items = {}
if len(trade_condition_list ) == 0 : if len(trade_condition_list ) == 0 :
......
...@@ -57,8 +57,6 @@ if active_process_path: ...@@ -57,8 +57,6 @@ if active_process_path:
else: else:
raise ValueError("No active process found to process report") raise ValueError("No active process found to process report")
def sortProduct(a, b):
return cmp(a['product'], b['product'])
period_counter_dict = {} period_counter_dict = {}
line_list = [] line_list = []
...@@ -132,7 +130,7 @@ if len(client_dict): ...@@ -132,7 +130,7 @@ if len(client_dict):
product_lines_list.append(obj) product_lines_list.append(obj)
# sort product list # sort product list
product_lines_list.sort(sortProduct) product_lines_list.sort(key=lambda p: p['product'])
extend(product_lines_list) extend(product_lines_list)
else: else:
# products # products
...@@ -169,7 +167,8 @@ else: ...@@ -169,7 +167,8 @@ else:
period_counter_dict['total amount'] = line_total_amount period_counter_dict['total amount'] = line_total_amount
append(obj) append(obj)
line_list.sort(sortProduct) line_list.sort(key=lambda p: p['product'])
obj = Object(uid="new_") obj = Object(uid="new_")
obj["client"] = 'Total' obj["client"] = 'Total'
......
...@@ -23,13 +23,10 @@ full_total_price = 0 ...@@ -23,13 +23,10 @@ full_total_price = 0
worker_column_list = [] worker_column_list = []
source_trade_dict = {} source_trade_dict = {}
def sortMovement(a, b):
return cmp(a.getRelativeUrl(), b.getRelativeUrl())
movement_type_list = context.getPortalMovementTypeList() movement_type_list = context.getPortalMovementTypeList()
line_list = [x for x in context.getIndexableChildValueList() if x.getPortalType() in \ line_list = [x for x in context.getIndexableChildValueList() if x.getPortalType() in \
movement_type_list] movement_type_list]
line_list.sort(sortMovement) line_list.sort(key=lambda line: line.getRelativeUrl())
order_type_list = context.getPortalOrderTypeList() order_type_list = context.getPortalOrderTypeList()
def getMovementTitle(movement): def getMovementTitle(movement):
......
...@@ -27,33 +27,30 @@ def rank_method(trade_condition): ...@@ -27,33 +27,30 @@ def rank_method(trade_condition):
source_section = trade_condition.getSourceSection() source_section = trade_condition.getSourceSection()
if source_section: if source_section:
if source_section == context.getSourceSection(): if source_section == context.getSourceSection():
rank += 10 rank -= 10
else: else:
rank -= 2 rank += 2
source = trade_condition.getSource() source = trade_condition.getSource()
if source: if source:
if source == context.getSource(): if source == context.getSource():
rank += 10 rank -= 10
else: else:
rank -= 2 rank += 2
if trade_condition.getDestinationSection(): if trade_condition.getDestinationSection():
rank += 1 rank -= 1
if trade_condition.getDestination(): if trade_condition.getDestination():
rank += 1 rank -= 1
rank += len(trade_condition.getSpecialiseList()) rank -= len(trade_condition.getSpecialiseList())
if trade_condition.getValidationState() == 'validated': if trade_condition.getValidationState() == 'validated':
rank += 2 rank -= 2
return rank return rank
def sort_method(a, b):
return -cmp(rank_method(a), rank_method(b))
while count > 0 and len(trade_condition_list) == 0: while count > 0 and len(trade_condition_list) == 0:
count -= 1 count -= 1
trade_condition_list = context.portal_domains.searchPredicateList( trade_condition_list = context.portal_domains.searchPredicateList(
predicate_context, portal_type=trade_condition_portal_type, predicate_context, portal_type=trade_condition_portal_type,
tested_base_category_list=tested_base_category_list[:count], tested_base_category_list=tested_base_category_list[:count],
sort_method=sort_method) sort_key_method=rank_method)
keep_items = {} keep_items = {}
if len(trade_condition_list ) == 0 : if len(trade_condition_list ) == 0 :
......
...@@ -28,35 +28,32 @@ def rank_method(trade_condition): ...@@ -28,35 +28,32 @@ def rank_method(trade_condition):
destination_project = trade_condition.getDestinationProject() destination_project = trade_condition.getDestinationProject()
if destination_project: if destination_project:
if destination_project == context.getDestinationProject(): if destination_project == context.getDestinationProject():
rank += 10 rank -= 10
else: else:
rank -= 2 rank += 2
destination_section = trade_condition.getDestinationSection() destination_section = trade_condition.getDestinationSection()
if destination_section: if destination_section:
if destination_section == context.getDestinationSection(): if destination_section == context.getDestinationSection():
rank += 10 rank -= 10
else: else:
rank -= 2 rank += 2
destination = trade_condition.getDestination() destination = trade_condition.getDestination()
if destination: if destination:
if destination == context.getDestination(): if destination == context.getDestination():
rank += 10 rank -= 10
else: else:
rank -= 2 rank += 2
if trade_condition.getSourceProject(): if trade_condition.getSourceProject():
rank += 1 rank -= 1
if trade_condition.getSourceSection(): if trade_condition.getSourceSection():
rank += 1 rank -= 1
if trade_condition.getSource(): if trade_condition.getSource():
rank += 1 rank -= 1
rank += len(trade_condition.getSpecialiseList()) rank -= len(trade_condition.getSpecialiseList())
if trade_condition.getValidationState() == 'validated': if trade_condition.getValidationState() == 'validated':
rank += 2 rank -= 2
return rank return rank
def sort_method(a, b):
return -cmp(rank_method(a), rank_method(b))
def filter_method(trade_condition_list): def filter_method(trade_condition_list):
# Reject trade condition which has a non different value than the order # Reject trade condition which has a non different value than the order
filtered_trade_condition_list = [] filtered_trade_condition_list = []
...@@ -76,7 +73,7 @@ while count > 0 and len(trade_condition_list) == 0: ...@@ -76,7 +73,7 @@ while count > 0 and len(trade_condition_list) == 0:
predicate_context, portal_type=trade_condition_portal_type, predicate_context, portal_type=trade_condition_portal_type,
tested_base_category_list=tested_base_category_list[:count], tested_base_category_list=tested_base_category_list[:count],
filter_method=filter_method, filter_method=filter_method,
sort_method=sort_method) sort_key_method=rank_method)
keep_items = {} keep_items = {}
if len(trade_condition_list ) == 0 : if len(trade_condition_list ) == 0 :
......
...@@ -174,11 +174,7 @@ class WebSite(WebSection): ...@@ -174,11 +174,7 @@ class WebSite(WebSection):
if sub_path in section_dict: if sub_path in section_dict:
del section_dict[sub_path] del section_dict[sub_path]
section_list = section_dict.values()
# Sort by Index # Sort by Index
section_list.sort(key=lambda x: x.getIntIndex()) return sorted(section_dict.values(), key=lambda x: x.getIntIndex())
return section_list
else: else:
return [] return []
\ No newline at end of file
...@@ -93,9 +93,7 @@ class WebServiceTool(BaseTool): ...@@ -93,9 +93,7 @@ class WebServiceTool(BaseTool):
""" """
Return list of available connection plugins Return list of available connection plugins
""" """
plugin_list = connection_plugin_registry.keys() return sorted(connection_plugin_registry.keys())
plugin_list.sort()
return plugin_list
security.declareProtected(Permissions.ManagePortal, 'connect') security.declareProtected(Permissions.ManagePortal, 'connect')
def connect(self, url, user_name=None, password=None, transport=None, transport_kw=None): def connect(self, url, user_name=None, password=None, transport=None, transport_kw=None):
......
...@@ -140,5 +140,7 @@ class TestShaCache(ShaCacheMixin, ERP5TypeTestCase): ...@@ -140,5 +140,7 @@ class TestShaCache(ShaCacheMixin, ERP5TypeTestCase):
document_list = self.portal.portal_catalog(reference=self.key) document_list = self.portal.portal_catalog(reference=self.key)
self.assertEqual(2, len(document_list)) self.assertEqual(2, len(document_list))
expectedFailure(self.assertEqual)(sorted(['archived', 'published']), # this is the expected failure
sorted(q.getValidationState() for q in document_list)) self.assertEqual(
sorted(['archived', 'published']),
sorted(q.getValidationState() for q in document_list))
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
from past.builtins import cmp from past.builtins import cmp
import string import string
import warnings
from Products.ERP5Type.Globals import InitializeClass, DTMLFile from Products.ERP5Type.Globals import InitializeClass, DTMLFile
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
...@@ -42,6 +43,11 @@ from Products.ERP5Type.Core.Folder import Folder ...@@ -42,6 +43,11 @@ from Products.ERP5Type.Core.Folder import Folder
from Products.CMFCategory.Renderer import Renderer from Products.CMFCategory.Renderer import Renderer
from Products.ERP5Type.Utils import sortValueList from Products.ERP5Type.Utils import sortValueList
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
import six
if six.PY3:
from functools import cmp_to_key
def cmp(a, b):
return (a > b) - (a < b)
DEFAULT_CACHE_FACTORY = 'erp5_ui_long' DEFAULT_CACHE_FACTORY = 'erp5_ui_long'
...@@ -274,6 +280,7 @@ class Category(Folder): ...@@ -274,6 +280,7 @@ class Category(Folder):
def getCategoryChildValueList(self, recursive=1, include_if_child=1, def getCategoryChildValueList(self, recursive=1, include_if_child=1,
is_self_excluded=1, sort_on=None, is_self_excluded=1, sort_on=None,
sort_order=None, local_sort_method=None, sort_order=None, local_sort_method=None,
local_sort_key=None,
local_sort_id=None, checked_permission=None, local_sort_id=None, checked_permission=None,
**kw): **kw):
""" """
...@@ -297,8 +304,13 @@ class Category(Folder): ...@@ -297,8 +304,13 @@ class Category(Folder):
WARNING: using these parameters can slow down WARNING: using these parameters can slow down
significantly, because this is written in Python significantly, because this is written in Python
local_sort_key - When using the default preorder traversal, use
this function as sort key for objects of the same
depth.
local_sort_method - When using the default preorder traversal, use local_sort_method - When using the default preorder traversal, use
this function to sort objects of the same depth. this function to sort objects of the same depth.
DEPRECATED, use local_sort_key
local_sort_id - When using the default preorder traversal, sort local_sort_id - When using the default preorder traversal, sort
objects of the same depth by comparing their objects of the same depth by comparing their
...@@ -317,21 +329,26 @@ class Category(Folder): ...@@ -317,21 +329,26 @@ class Category(Folder):
child_value_list = self.objectValues(self.allowed_types) child_value_list = self.objectValues(self.allowed_types)
if local_sort_id: if local_sort_id:
if isinstance(local_sort_id, (tuple, list)): if not isinstance(local_sort_id, (tuple, list)):
def sort_method(a, b): local_sort_id = (local_sort_id, )
for sort_id in local_sort_id: def sort_key(c):
diff = cmp(a.getProperty(sort_id, 0), b.getProperty(sort_id, 0)) k = []
if diff != 0: for sort_id in local_sort_id:
return diff v = c.getProperty(sort_id)
return 0 k.extend([v is not None, v])
local_sort_method = sort_method return k
else: local_sort_key = sort_key
local_sort_method = lambda a, b: cmp(a.getProperty(local_sort_id, 0),
b.getProperty(local_sort_id, 0))
if local_sort_method: if local_sort_method:
# sort objects at the current level warnings.warn(
"`local_sort_method` argument is deprecated, use `local_sort_key` instead",
DeprecationWarning)
child_value_list = list(child_value_list) child_value_list = list(child_value_list)
child_value_list.sort(local_sort_method) if six.PY2:
child_value_list.sort(local_sort_method)
else:
local_sort_key = cmp_to_key(local_sort_method)
if local_sort_key:
child_value_list = sorted(child_value_list, key=local_sort_key)
if recursive: if recursive:
for c in child_value_list: for c in child_value_list:
...@@ -341,6 +358,7 @@ class Category(Folder): ...@@ -341,6 +358,7 @@ class Category(Folder):
is_self_excluded=0, is_self_excluded=0,
include_if_child=include_if_child, include_if_child=include_if_child,
local_sort_method=local_sort_method, local_sort_method=local_sort_method,
local_sort_key=local_sort_key,
local_sort_id=local_sort_id)) local_sort_id=local_sort_id))
else: else:
for c in child_value_list: for c in child_value_list:
...@@ -828,7 +846,7 @@ class BaseCategory(Category): ...@@ -828,7 +846,7 @@ class BaseCategory(Category):
'getCategoryChildValueList') 'getCategoryChildValueList')
def getCategoryChildValueList(self, is_self_excluded=1, recursive=1, def getCategoryChildValueList(self, is_self_excluded=1, recursive=1,
include_if_child=1, sort_on=None, sort_order=None, include_if_child=1, sort_on=None, sort_order=None,
local_sort_method=None, local_sort_id=None, local_sort_method=None, local_sort_key=None, local_sort_id=None,
checked_permission=None, **kw): checked_permission=None, **kw):
""" """
List the child objects of this category and all its subcategories. List the child objects of this category and all its subcategories.
...@@ -850,8 +868,13 @@ class BaseCategory(Category): ...@@ -850,8 +868,13 @@ class BaseCategory(Category):
the 'sort_on' attribute. The default is to do a preorder tree the 'sort_on' attribute. The default is to do a preorder tree
traversal on all subobjects. traversal on all subobjects.
local_sort_key - When using the default preorder traversal, use
this function as sort key for objects of the same
depth.
local_sort_method - When using the default preorder traversal, use local_sort_method - When using the default preorder traversal, use
this function to sort objects of the same depth. this function to sort objects of the same depth.
DEPRECATED, use local_sort_key
local_sort_id - When using the default preorder traversal, sort local_sort_id - When using the default preorder traversal, sort
objects of the same depth by comparing their objects of the same depth by comparing their
...@@ -869,29 +892,35 @@ class BaseCategory(Category): ...@@ -869,29 +892,35 @@ class BaseCategory(Category):
child_value_list = self.objectValues(self.allowed_types) child_value_list = self.objectValues(self.allowed_types)
if local_sort_id: if local_sort_id:
if isinstance(local_sort_id, (tuple, list)): if not isinstance(local_sort_id, (tuple, list)):
def sort_method(a, b): local_sort_id = (local_sort_id, )
for sort_id in local_sort_id: def sort_key(c):
diff = cmp(a.getProperty(sort_id, 0), b.getProperty(sort_id, 0)) k = []
if diff != 0: for sort_id in local_sort_id:
return diff v = c.getProperty(sort_id)
return 0 k.extend([v is not None, v])
local_sort_method = sort_method return k
else: local_sort_key = sort_key
local_sort_method = lambda a, b: cmp(a.getProperty(local_sort_id, 0),
b.getProperty(local_sort_id, 0))
if local_sort_method: if local_sort_method:
# sort objects at the current level warnings.warn(
"`local_sort_method` argument is deprecated, use `local_sort_key` instead",
DeprecationWarning)
child_value_list = list(child_value_list) child_value_list = list(child_value_list)
child_value_list.sort(local_sort_method) if six.PY2:
child_value_list.sort(local_sort_method)
else:
local_sort_key = cmp_to_key(local_sort_method)
if local_sort_key:
child_value_list = sorted(child_value_list, key=local_sort_key)
if recursive: if recursive:
for c in child_value_list: for c in child_value_list:
value_list.extend(c.getCategoryChildValueList(recursive=1, value_list.extend(c.getCategoryChildValueList(recursive=1,
is_self_excluded=0, is_self_excluded=0,
include_if_child=include_if_child, include_if_child=include_if_child,
local_sort_id=local_sort_id, local_sort_method=local_sort_method,
local_sort_method=local_sort_method)) local_sort_key=local_sort_key,
local_sort_id=local_sort_id))
else: else:
for c in child_value_list: for c in child_value_list:
if include_if_child: if include_if_child:
......
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
from Products.CMFCategory.Filter import Filter from Products.CMFCategory.Filter import Filter
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
from zLOG import LOG, PROBLEM from zLOG import LOG, PROBLEM
import six
if six.PY3:
from functools import cmp_to_key
class Renderer(Filter): class Renderer(Filter):
""" """
...@@ -42,7 +45,7 @@ class Renderer(Filter): ...@@ -42,7 +45,7 @@ class Renderer(Filter):
def __init__(self, spec = None, filter = None, portal_type = None, def __init__(self, spec = None, filter = None, portal_type = None,
display_id = None, sort_id = None, display_id = None, sort_id = None,
display_method = None, sort_method = None, filter_method = None, display_method = None, sort_key = None, sort_method = None, filter_method = None,
filter_node=0, disable_node=0, filter_node=0, disable_node=0,
filter_leave=0, disable_leave=0, filter_leave=0, disable_leave=0,
is_right_display = 0, translate_display = 0, is_right_display = 0, translate_display = 0,
...@@ -74,7 +77,10 @@ class Renderer(Filter): ...@@ -74,7 +77,10 @@ class Renderer(Filter):
foo2 5 foo2 5
display order will be (foo1, foo, foo2) display order will be (foo1, foo, foo2)
- *sort_method*: a callable method which provides a sort function (?la cmp) - *sort_key*: a callable method used to sort the values, as in sort(key=sort_key)
- *sort_method*: a callable method used to sort the values, as in python2 cmp.
DEPRECATED, use sort_key.
- *is_right_display*: use the right value in the couple as the display value. - *is_right_display*: use the right value in the couple as the display value.
...@@ -109,6 +115,7 @@ class Renderer(Filter): ...@@ -109,6 +115,7 @@ class Renderer(Filter):
self.display_id = display_id self.display_id = display_id
self.sort_id = sort_id self.sort_id = sort_id
self.display_method = display_method self.display_method = display_method
self.sort_key = sort_key
self.sort_method = sort_method self.sort_method = sort_method
self.is_right_display = is_right_display self.is_right_display = is_right_display
self.translate_display = translate_display self.translate_display = translate_display
...@@ -135,9 +142,17 @@ class Renderer(Filter): ...@@ -135,9 +142,17 @@ class Renderer(Filter):
value_list = self.getObjectList(value_list) value_list = self.getObjectList(value_list)
value_list = self.filter(value_list) value_list = self.filter(value_list)
if self.sort_method is not None: if self.sort_method is not None:
value_list.sort(self.sort_method) if six.PY2:
value_list.sort(self.sort_method)
else:
value_list.sort(key=cmp_to_key(self.sort_method))
elif self.sort_key is not None:
value_list.sort(key=self.sort_key)
elif self.sort_id is not None: elif self.sort_id is not None:
value_list.sort(key=lambda x: x.getProperty(self.sort_id)) def sort_key(x):
k = x.getProperty(self.sort_id)
return (k is not None, k)
value_list.sort(key=sort_key)
# If base=1 but base_category is None, it is necessary to guess the base category # If base=1 but base_category is None, it is necessary to guess the base category
# by heuristic. # by heuristic.
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
import mock import mock
from collections import deque from collections import deque
import unittest import unittest
import warnings
from Acquisition import aq_base from Acquisition import aq_base
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
...@@ -38,6 +39,9 @@ from Testing.ZopeTestCase.PortalTestCase import PortalTestCase ...@@ -38,6 +39,9 @@ from Testing.ZopeTestCase.PortalTestCase import PortalTestCase
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager from AccessControl.SecurityManagement import noSecurityManager
import six import six
if six.PY3:
def cmp(a, b):
return (a > b) - (a < b)
class TestCMFCategory(ERP5TypeTestCase): class TestCMFCategory(ERP5TypeTestCase):
...@@ -949,8 +953,8 @@ class TestCMFCategory(ERP5TypeTestCase): ...@@ -949,8 +953,8 @@ class TestCMFCategory(ERP5TypeTestCase):
self.assertSameSet(c1.getCategoryChildValueList(is_self_excluded=0), self.assertSameSet(c1.getCategoryChildValueList(is_self_excluded=0),
(c1, c11, c111)) (c1, c11, c111))
def test_24_getCategoryChildValueListLocalSortMethod(self): def test_24_getCategoryChildValueListLocalSort(self):
'''Test getCategoryChildValueList local sort method''' '''Test getCategoryChildValueList local sort'''
pc = self.getCategoriesTool() pc = self.getCategoriesTool()
bc = pc.newContent(portal_type='Base Category', id='child_test') bc = pc.newContent(portal_type='Base Category', id='child_test')
c1 = bc.newContent(portal_type='Category', id='1', int_index=10, title='C') c1 = bc.newContent(portal_type='Category', id='1', int_index=10, title='C')
...@@ -971,17 +975,54 @@ class TestCMFCategory(ERP5TypeTestCase): ...@@ -971,17 +975,54 @@ class TestCMFCategory(ERP5TypeTestCase):
# sort_order which sort the whole list regardless of the original # sort_order which sort the whole list regardless of the original
# structure). # structure).
# This can be done either with a function (like cmp argument to python sort_key_calls = []
# list sort) def sort_key(c):
sort_key_calls.append(c)
return c.getTitle()
# here c1, c2, c3 are sorted by their titles
self.assertEqual(list(bc.getCategoryChildValueList(
local_sort_key=sort_key)),
[c3, c2, c1, c11, c111, c12])
self.assertTrue(sort_key_calls)
# here c11 & c12 are sorted by their titles
self.assertEqual(list(c1.getCategoryChildValueList(
local_sort_key=sort_key)), [c11, c111, c12])
self.assertTrue(sort_key_calls)
# This can be done with a function, using `local_sort_key` or
# `local_sort_method` (with is like cmp argument to python2 list sort)
sort_func_calls = []
def sort_func(a, b): def sort_func(a, b):
sort_func_calls.append((a, b))
return cmp(a.getTitle(), b.getTitle()) return cmp(a.getTitle(), b.getTitle())
# `local_sort_method` is deprecated, so using it cause a warning to be
# emitted. Because the method exists on both category and base category
# there can be two warnings.
with warnings.catch_warnings(record=True) as warning_list:
warnings.simplefilter("always")
c1.getCategoryChildValueList(local_sort_method=sort_func)
self.assertEqual(
{str(w.message) for w in warning_list},
{'`local_sort_method` argument is deprecated, use `local_sort_key` instead'})
with warnings.catch_warnings(record=True) as warning_list:
warnings.simplefilter("always")
bc.getCategoryChildValueList(local_sort_method=sort_func)
self.assertEqual(
{str(w.message) for w in warning_list},
{'`local_sort_method` argument is deprecated, use `local_sort_key` instead'})
del sort_func_calls[:]
# here c1, c2, c3 are sorted by their titles # here c1, c2, c3 are sorted by their titles
self.assertEqual(list(bc.getCategoryChildValueList( self.assertEqual(list(bc.getCategoryChildValueList(
local_sort_method=sort_func)), local_sort_method=sort_func)),
[c3, c2, c1, c11, c111, c12]) [c3, c2, c1, c11, c111, c12])
self.assertTrue(sort_func_calls)
del sort_func_calls[:]
# here c11 & c12 are sorted by their titles # here c11 & c12 are sorted by their titles
self.assertEqual(list(c1.getCategoryChildValueList( self.assertEqual(list(c1.getCategoryChildValueList(
local_sort_method=sort_func)), [c11, c111, c12]) local_sort_method=sort_func)), [c11, c111, c12])
self.assertTrue(sort_func_calls)
# This can also be done with a local_sort_id, then objects are sorted by # This can also be done with a local_sort_id, then objects are sorted by
# comparing this 'sort_id' property (using getProperty()) # comparing this 'sort_id' property (using getProperty())
......
...@@ -348,12 +348,8 @@ class Alarm(XMLObject, PeriodicityMixin): ...@@ -348,12 +348,8 @@ class Alarm(XMLObject, PeriodicityMixin):
result_list = [x for x in active_process.getResultList() if x is not None] result_list = [x for x in active_process.getResultList() if x is not None]
attachment_list = [] attachment_list = []
if len(result_list): if len(result_list):
def sort_result_list(a, b): # Here we assume that severity type is int or float and summary type is same for all entries.
result = - cmp(a.severity, b.severity) result_list.sort(key=lambda e: (-e.severity, e.summary))
if result == 0:
result = cmp(a.summary, b.summary)
return result
result_list.sort(sort_result_list)
rendered_alarm_result_list = ['%02i summary: %s\n%s\n----' % rendered_alarm_result_list = ['%02i summary: %s\n%s\n----' %
(int(getattr(x, 'severity', 0)), getattr(x, 'summary', ''), getattr(x, 'detail', '')) (int(getattr(x, 'severity', 0)), getattr(x, 'summary', ''), getattr(x, 'detail', ''))
for x in result_list] for x in result_list]
......
...@@ -497,8 +497,7 @@ class Document(DocumentExtensibleTraversableMixin, XMLObject, UrlMixin, ...@@ -497,8 +497,7 @@ class Document(DocumentExtensibleTraversableMixin, XMLObject, UrlMixin,
tmp = {} tmp = {}
for match in rx_search.finditer(text): for match in rx_search.finditer(text):
group = match.group() group = match.group()
group_item_list = match.groupdict().items() group_item_list = sorted(match.groupdict().items())
group_item_list.sort()
key = (group, tuple(group_item_list)) key = (group, tuple(group_item_list))
tmp[key] = None tmp[key] = None
for group, group_item_tuple in tmp.keys(): for group, group_item_tuple in tmp.keys():
......
...@@ -316,8 +316,7 @@ class ImmobilisableItem(Item, Amount): ...@@ -316,8 +316,7 @@ class ImmobilisableItem(Item, Amount):
Returns a list of dictionaries representing immobilisation periods for the object Returns a list of dictionaries representing immobilisation periods for the object
from_date is included, to_date is excluded from_date is included, to_date is excluded
""" """
kw_key_list = kw.keys() kw_key_list = sorted(kw.keys())
kw_key_list.sort()
if kw_key_list.count('immo_cache_dict'): if kw_key_list.count('immo_cache_dict'):
kw_key_list.remove('immo_cache_dict') kw_key_list.remove('immo_cache_dict')
immo_cache_dict = kw.get('immo_cache_dict', {'period':{}, immo_cache_dict = kw.get('immo_cache_dict', {'period':{},
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
import six import six
from past.builtins import cmp
from hashlib import md5 from hashlib import md5
# Some workflow does not make sense in the context of mass transition and are # Some workflow does not make sense in the context of mass transition and are
...@@ -148,14 +147,7 @@ def getDocumentGroupByWorkflowStateList(self, form_id='', **kw): ...@@ -148,14 +147,7 @@ def getDocumentGroupByWorkflowStateList(self, form_id='', **kw):
workflow_state=current_workflow_state, workflow_state=current_workflow_state,
)) ))
# Let us sort this list by translated title of workflow state and workflow return sorted(document_list, key=lambda b: (b.workflow_title, b.translated_workflow_state_title))
def compareState(a, b):
return cmp((a.workflow_title, a.translated_workflow_state_title),
(b.workflow_title, b.translated_workflow_state_title))
document_list.sort(compareState)
# Return result
return document_list
......
...@@ -42,9 +42,7 @@ from OFS.Image import Pdata, Image as OFSImage ...@@ -42,9 +42,7 @@ from OFS.Image import Pdata, Image as OFSImage
from DateTime import DateTime from DateTime import DateTime
def makeSortedTuple(kw): def makeSortedTuple(kw):
items = kw.items() return tuple(sorted(kw.items()))
items.sort()
return tuple(items)
def hashPdataObject(pdata_object): def hashPdataObject(pdata_object):
"""Pdata objects are iterable, use this feature strongly """Pdata objects are iterable, use this feature strongly
......
from erp5.component.module.Log import log
# this script is no longer needed.
log('Category_getSortedCategoryChildValueList', 'use getCategoryChildValueList method')
value_list = [o for o in context.getCategoryChildValueList() if o.getRelativeUrl() != context.getRelativeUrl()]
sort_id='int_index'
value_list.sort(key=lambda x: x.getProperty(sort_id))
return value_list
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>**kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Category_getSortedCategoryChildValueList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
# #
############################################################################## ##############################################################################
import functools
from collections import defaultdict from collections import defaultdict
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Globals import InitializeClass
...@@ -242,7 +243,10 @@ class DomainTool(BaseTool): ...@@ -242,7 +243,10 @@ class DomainTool(BaseTool):
if sort_key_method is not None: if sort_key_method is not None:
result_list.sort(key=sort_key_method) result_list.sort(key=sort_key_method)
elif sort_method is not None: elif sort_method is not None:
result_list.sort(cmp=sort_method) if six.PY3:
result_list.sort(key=functools.cmp_to_key(sort_method))
else:
result_list.sort(cmp=sort_method)
return result_list return result_list
# XXX FIXME method should not be public # XXX FIXME method should not be public
......
...@@ -28,6 +28,7 @@ from __future__ import division ...@@ -28,6 +28,7 @@ from __future__ import division
# #
############################################################################## ##############################################################################
import functools
from past.builtins import cmp from past.builtins import cmp
from six import string_types as basestring from six import string_types as basestring
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
...@@ -1636,7 +1637,10 @@ class SimulationTool(BaseTool): ...@@ -1636,7 +1637,10 @@ class SimulationTool(BaseTool):
result *= -1 result *= -1
break break
return result return result
sorted_inventory_list.sort(cmp_inventory_line) if six.PY2:
sorted_inventory_list.sort(cmp_inventory_line)
else:
sorted_inventory_list.sort(key=functools.cmp_to_key(cmp_inventory_line))
# Brain is rebuild properly using tuple not r instance # Brain is rebuild properly using tuple not r instance
column_list = first_result._searchable_result_columns() column_list = first_result._searchable_result_columns()
column_name_list = [x['name'] for x in column_list] column_name_list = [x['name'] for x in column_list]
......
...@@ -994,8 +994,7 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate): ...@@ -994,8 +994,7 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate):
# for skin_folder_id in self.getSimilarSkinFolderIdList(): # for skin_folder_id in self.getSimilarSkinFolderIdList():
for skin_folder_id in self.getPortalObject().portal_skins.objectIds(): for skin_folder_id in self.getPortalObject().portal_skins.objectIds():
iterate(getattr(skins_tool, skin_folder_id)) iterate(getattr(skins_tool, skin_folder_id))
proxy_dict_list = proxy_dict.values() proxy_dict_list = sorted(proxy_dict.values(), key=lambda x: x['short_path'])
proxy_dict_list.sort(key=lambda x: x['short_path'])
for item in proxy_dict_list: for item in proxy_dict_list:
item['related_proxy_list'].sort(key=lambda x: x['short_path']) item['related_proxy_list'].sort(key=lambda x: x['short_path'])
......
...@@ -332,9 +332,7 @@ class Predicate(XMLObject): ...@@ -332,9 +332,7 @@ class Predicate(XMLObject):
criterion_dict[p].property = p criterion_dict[p].property = p
criterion_dict[p].min = self._range_criterion.get(p, (None, None))[0] criterion_dict[p].min = self._range_criterion.get(p, (None, None))[0]
criterion_dict[p].max = self._range_criterion.get(p, (None, None))[1] criterion_dict[p].max = self._range_criterion.get(p, (None, None))[1]
criterion_list = criterion_dict.values() return sorted(criterion_dict.values())
criterion_list.sort()
return criterion_list
security.declareProtected( Permissions.ModifyPortalContent, 'setCriterion' ) security.declareProtected( Permissions.ModifyPortalContent, 'setCriterion' )
def setCriterion(self, property, identity=None, min=None, max=None, **kw): def setCriterion(self, property, identity=None, min=None, max=None, **kw):
......
...@@ -29,11 +29,12 @@ ...@@ -29,11 +29,12 @@
# Required modules - some modules are imported later to prevent circular deadlocks # Required modules - some modules are imported later to prevent circular deadlocks
from __future__ import absolute_import from __future__ import absolute_import
from past.builtins import cmp
from six import int2byte as chr from six import int2byte as chr
from six import string_types as basestring from six import string_types as basestring
from six.moves import xrange from six.moves import xrange
import six import six
if six.PY3:
from functools import cmp_to_key, total_ordering
import os import os
import re import re
import string import string
...@@ -123,10 +124,47 @@ from Products.ERP5Type.Globals import get_request ...@@ -123,10 +124,47 @@ from Products.ERP5Type.Globals import get_request
from .Accessor.TypeDefinition import type_definition from .Accessor.TypeDefinition import type_definition
from .Accessor.TypeDefinition import list_types from .Accessor.TypeDefinition import list_types
if six.PY3:
def cmp(a, b):
try:
return (a > b) - (a < b)
except TypeError:
if a is None:
return -1
elif b is None:
return 1
type_a = '' if isinstance(a, (int, float)) else type(a).__name__
type_b = '' if isinstance(b, (int, float)) else type(b).__name__
return (type_a > type_b) - (type_a < type_b)
else:
import __builtin__
cmp = __builtin__.cmp
##################################################### #####################################################
# Generic sort method # Generic sort method
##################################################### #####################################################
if six.PY2:
OrderableKey = lambda x: x
else:
@total_ordering
class OrderableKey(object):
def __init__(self, value):
self.value = value
def __lt__(self, other):
if not isinstance(other, OrderableKey):
raise TypeError
return cmp(self.value, other.value) != 1
def __eq__(self, other):
if not isinstance(other, OrderableKey):
raise TypeError
return self.value == other.value
def __repr__(self):
return 'OrderableKey(%r)' % self.value
sort_kw_cache = {} sort_kw_cache = {}
def sortValueList(value_list, sort_on=None, sort_order=None, **kw): def sortValueList(value_list, sort_on=None, sort_order=None, **kw):
...@@ -184,7 +222,10 @@ def sortValueList(value_list, sort_on=None, sort_order=None, **kw): ...@@ -184,7 +222,10 @@ def sortValueList(value_list, sort_on=None, sort_order=None, **kw):
except TypeError: except TypeError:
pass pass
value_list.append(x) value_list.append(x)
return value_list if six.PY2:
return value_list
else:
return [OrderableKey(e) for e in value_list]
sort_kw = {'key':sortValue, 'reverse':reverse} sort_kw = {'key':sortValue, 'reverse':reverse}
sort_kw_cache[(sort_on, sort_order)] = sort_kw sort_kw_cache[(sort_on, sort_order)] = sort_kw
else: else:
...@@ -206,7 +247,10 @@ def sortValueList(value_list, sort_on=None, sort_order=None, **kw): ...@@ -206,7 +247,10 @@ def sortValueList(value_list, sort_on=None, sort_order=None, **kw):
if result != 0: if result != 0:
break break
return result return result
sort_kw = {'cmp':sortValues} if six.PY2:
sort_kw = {'cmp':sortValues}
else:
sort_kw = {'key': cmp_to_key(sortValues)}
sort_kw_cache[(sort_on, sort_order)] = sort_kw sort_kw_cache[(sort_on, sort_order)] = sort_kw
if isinstance(value_list, LazyMap): if isinstance(value_list, LazyMap):
......
...@@ -76,8 +76,8 @@ def DeepDiff__diff(self, level, parents_ids=frozenset({})): ...@@ -76,8 +76,8 @@ def DeepDiff__diff(self, level, parents_ids=frozenset({})):
# by deepdiff. Thus, sorting tuples before diffing will atleast give us # by deepdiff. Thus, sorting tuples before diffing will atleast give us
# diff in the format where we would be able to see the more asthetic # diff in the format where we would be able to see the more asthetic
# diff for tuples. # diff for tuples.
level.t1 = sorted(level.t1) level.t1 = sorted(level.t1, key=str)
level.t2 = sorted(level.t2) level.t2 = sorted(level.t2, key=str)
self._DeepDiff__diff_tuple(level, parents_ids) self._DeepDiff__diff_tuple(level, parents_ids)
elif isinstance(level.t1, (set, frozenset)): elif isinstance(level.t1, (set, frozenset)):
......
...@@ -38,6 +38,7 @@ from Acquisition import aq_base ...@@ -38,6 +38,7 @@ from Acquisition import aq_base
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from AccessControl.ZopeGuards import guarded_import from AccessControl.ZopeGuards import guarded_import
from Products.ERP5Type.tests.utils import LogInterceptor, createZODBPythonScript from Products.ERP5Type.tests.utils import LogInterceptor, createZODBPythonScript
from Products.ERP5Type.Utils import OrderableKey, cmp
class TestERP5Type(ERP5TypeTestCase, LogInterceptor): class TestERP5Type(ERP5TypeTestCase, LogInterceptor):
""" """
...@@ -280,6 +281,21 @@ class TestERP5Type(ERP5TypeTestCase, LogInterceptor): ...@@ -280,6 +281,21 @@ class TestERP5Type(ERP5TypeTestCase, LogInterceptor):
self.assertIn(script, person.objectValues()) self.assertIn(script, person.objectValues())
self.assertNotIn(script, person.objectValues(portal_type='Person')) self.assertNotIn(script, person.objectValues(portal_type='Person'))
def test_cmp(self):
self.assertEqual(cmp(None, 0), -1)
self.assertEqual(cmp(None, ''), -1)
self.assertEqual(cmp(0, ''), -1)
def test_OrderableKey(self):
self.assertEqual(
sorted([1, '', None], key=lambda x: OrderableKey(x)),
[None, 1, '']
)
o1 = [OrderableKey(e) for e in (None, 1)]
o2 = [OrderableKey(e) for e in (0, 0)]
self.assertEqual(sorted([o1, o2]), [o1, o2])
self.assertEqual(sorted([o2, o1]), [o1, o2])
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestERP5Type)) suite.addTest(unittest.makeSuite(TestERP5Type))
......
...@@ -36,8 +36,7 @@ def formToXML(form, prologue=1): ...@@ -36,8 +36,7 @@ def formToXML(form, prologue=1):
fields.append(field_element) fields.append(field_element)
values_element = SubElement(field_element, 'values') values_element = SubElement(field_element, 'values')
items = field.values.items() items = sorted(field.values.items())
items.sort()
for key, value in items: for key, value in items:
if value is None: if value is None:
continue continue
...@@ -60,8 +59,7 @@ def formToXML(form, prologue=1): ...@@ -60,8 +59,7 @@ def formToXML(form, prologue=1):
value_element.text = str(value).decode(encoding) value_element.text = str(value).decode(encoding)
tales_element = SubElement(field_element, 'tales') tales_element = SubElement(field_element, 'tales')
items = field.tales.items() items = sorted(field.tales.items())
items.sort()
for key, value in items: for key, value in items:
if value: if value:
tale_element = SubElement(tales_element, key) tale_element = SubElement(tales_element, key)
......
...@@ -423,7 +423,10 @@ class HBTreeFolder2Base (Persistent): ...@@ -423,7 +423,10 @@ class HBTreeFolder2Base (Persistent):
s.append((k, six.iteritems(v))) s.append((k, six.iteritems(v)))
break break
s.append((k, six.iteritems(v))) s.append((k, six.iteritems(v)))
r.sort() if six.PY2:
r.sort()
else:
r.sort(key=lambda e: '' if e is None else e)
return r return r
security.declareProtected(access_contents_information, security.declareProtected(access_contents_information,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment