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