summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Morel <xmo@odoo.com>2017-04-12 09:53:33 +0200
committerXavier Morel <xmo@odoo.com>2017-04-12 13:48:42 +0200
commit76852a2fad05292b8d592b76b37e4732f9c60a2d (patch)
tree89f532e4d594b815b98f0425397b6156888626c3
parent15e17e7b48f89f6e897a28f5031cdd740a887d80 (diff)
[#8530] fix uses of ``reduce`` builtin
Demoted to library in Python 3, see if uses can be replaced by more specific construct, just import functools.reduce otherwise. Futurize fixers: * lib2to3.fixes.fix_reduce
-rw-r--r--addons/account/models/account_invoice.py2
-rw-r--r--addons/product/models/product_template.py21
-rw-r--r--addons/rating/models/rating.py4
-rw-r--r--addons/website_rating_project_issue/controllers/main.py2
-rw-r--r--doc/python3.rst15
-rw-r--r--odoo/addons/base/ir/ir_qweb/qweb.py1
-rw-r--r--odoo/addons/base/res/res_config.py3
-rw-r--r--odoo/modules/graph.py2
-rw-r--r--odoo/tools/parse_version.py10
-rw-r--r--odoo/tools/translate.py2
10 files changed, 43 insertions, 19 deletions
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 87c8677d2a0..29557781875 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -1464,7 +1464,7 @@ class AccountPaymentTerm(models.Model):
next_date += relativedelta(day=31, months=0) # Getting last day of next month
result.append((fields.Date.to_string(next_date), amt))
amount -= amt
- amount = reduce(lambda x, y: x + y[1], result, 0.0)
+ amount = sum(amt for _, amt in result)
dist = round(value - amount, prec)
if dist:
last_date = result and result[-1][0] or fields.Date.today()
diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py
index 5e2bcba48f6..0082bbf7793 100644
--- a/addons/product/models/product_template.py
+++ b/addons/product/models/product_template.py
@@ -383,6 +383,7 @@ class ProductTemplate(models.Model):
@api.multi
def create_variant_ids(self):
Product = self.env["product.product"]
+ AttributeValues = self.env['product.attribute.value']
for tmpl_id in self.with_context(active_test=False):
# adding an attribute with only one value should not recreate product
# write this attribute on every product to make sure we don't lose them
@@ -391,11 +392,21 @@ class ProductTemplate(models.Model):
updated_products = tmpl_id.product_variant_ids.filtered(lambda product: value_id.attribute_id not in product.mapped('attribute_value_ids.attribute_id'))
updated_products.write({'attribute_value_ids': [(4, value_id.id)]})
- # list of values combination
- existing_variants = [set(variant.attribute_value_ids.ids) for variant in tmpl_id.product_variant_ids]
- variant_matrix = itertools.product(*(line.value_ids for line in tmpl_id.attribute_line_ids if line.value_ids and line.value_ids[0].attribute_id.create_variant))
- variant_matrix = map(lambda record_list: reduce(lambda x, y: x+y, record_list, self.env['product.attribute.value']), variant_matrix)
- to_create_variants = filter(lambda rec_set: set(rec_set.ids) not in existing_variants, variant_matrix)
+ # iterator of n-uple of product.attribute.value *ids*
+ variant_matrix = [
+ AttributeValues.browse(value_ids)
+ for value_ids in itertools.product(*(line.value_ids.ids for line in tmpl_id.attribute_line_ids if line.value_ids[:1].attribute_id.create_variant))
+ ]
+
+ # get the value (id) sets of existing variants
+ existing_variants = {frozenset(variant.attribute_value_ids.ids) for variant in tmpl_id.product_variant_ids}
+ # -> for each value set, create a recordset of values to create a
+ # variant for if the value set isn't already a variant
+ to_create_variants = [
+ value_ids
+ for value_ids in variant_matrix
+ if set(value_ids.ids) not in existing_variants
+ ]
# check product
variants_to_activate = self.env['product.product']
diff --git a/addons/rating/models/rating.py b/addons/rating/models/rating.py
index 859d04e8603..3bc5491b6ef 100644
--- a/addons/rating/models/rating.py
+++ b/addons/rating/models/rating.py
@@ -217,8 +217,8 @@ class RatingMixin(models.AbstractModel):
rating_number = sum(values.values())
result = {
'repartition': values,
- 'avg': sum([float(key * values[key]) for key in values]) / rating_number if rating_number > 0 else 0,
- 'total': reduce(lambda x, y: y['rating_count'] + x, data, 0),
+ 'avg': sum(float(key * values[key]) for key in values) / rating_number if rating_number > 0 else 0,
+ 'total': sum(it['rating_count'] for it in data),
}
return result
return values
diff --git a/addons/website_rating_project_issue/controllers/main.py b/addons/website_rating_project_issue/controllers/main.py
index c819b7171c7..63916880880 100644
--- a/addons/website_rating_project_issue/controllers/main.py
+++ b/addons/website_rating_project_issue/controllers/main.py
@@ -45,7 +45,7 @@ class WebsiteRatingProject(http.Controller):
domdate = domain + [('create_date', '<=', yesterday), ('create_date', '>=', todate)]
stats[x] = {1: 0, 5: 0, 10: 0}
rating_stats = request.env['rating.rating'].read_group(domdate, [], ['rating'])
- total = reduce(lambda x, y: y['rating_count'] + x, rating_stats, 0)
+ total = sum(st['rating_count'] for st in rating_stats)
for rate in rating_stats:
stats[x][rate['rating']] = float("%.2f" % (rate['rating_count'] * 100.0 / total))
return {'ratings': ratings, 'stats': stats}
diff --git a/doc/python3.rst b/doc/python3.rst
index 4506fb9d9f1..cb60965eb6c 100644
--- a/doc/python3.rst
+++ b/doc/python3.rst
@@ -99,6 +99,21 @@ Removed Operators
These two operators were long recommended against/deprecated in Python 2,
Python 3 removed them from the language.
+Removed/renamed builtins
+------------------------
+
+``reduce``
+##########
+
+In Python 3, ``reduce`` has been demoted from builtin to ``functools.reduce``.
+However this is because many (if not most) uses of ``reduce`` can be replaced
+by ``sum``, ``all``, ``any`` or a list comprehension for a more readable and
+faster result.
+
+It is easy enough to just add ``from functools import reduce`` to the file
+and compatible with Python 2.6 and later, but consider whether you get better
+code by replacing it with some other method altogether.
+
Removed/renamed methods
-----------------------
diff --git a/odoo/addons/base/ir/ir_qweb/qweb.py b/odoo/addons/base/ir/ir_qweb/qweb.py
index e4b618a47e4..0c69bd90baa 100644
--- a/odoo/addons/base/ir/ir_qweb/qweb.py
+++ b/odoo/addons/base/ir/ir_qweb/qweb.py
@@ -10,6 +10,7 @@ import werkzeug
from werkzeug.utils import escape as _escape
from itertools import chain, izip, tee
import __builtin__
+from functools import reduce
builtin_defaults = {name: getattr(__builtin__, name) for name in dir(__builtin__)}
try:
diff --git a/odoo/addons/base/res/res_config.py b/odoo/addons/base/res/res_config.py
index 73eb71580f1..59764fca1e8 100644
--- a/odoo/addons/base/res/res_config.py
+++ b/odoo/addons/base/res/res_config.py
@@ -458,6 +458,7 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
}
"""
IrModule = self.env['ir.module.module']
+ Groups = self.env['res.groups']
ref = self.env.ref
defaults, groups, modules, others = [], [], [], []
@@ -467,7 +468,7 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
elif name.startswith('group_') and field.type in ('boolean', 'selection') and \
hasattr(field, 'implied_group'):
field_group_xmlids = getattr(field, 'group', 'base.group_user').split(',')
- field_groups = reduce(add, map(ref, field_group_xmlids))
+ field_groups = Groups.concat(*map(ref, field_group_xmlids))
groups.append((name, field_groups, ref(field.implied_group)))
elif name.startswith('module_') and field.type in ('boolean', 'selection'):
module = IrModule.sudo().search([('name', '=', name[7:])], limit=1)
diff --git a/odoo/modules/graph.py b/odoo/modules/graph.py
index aaf90ae8443..48cc0e8a6e1 100644
--- a/odoo/modules/graph.py
+++ b/odoo/modules/graph.py
@@ -91,7 +91,7 @@ class Graph(dict):
deps = info['depends']
# if all dependencies of 'package' are already in the graph, add 'package' in the graph
- if reduce(lambda x, y: x and y in self, deps, True):
+ if all(dep in self for dep in deps):
if not package in current:
packages.pop(0)
continue
diff --git a/odoo/tools/parse_version.py b/odoo/tools/parse_version.py
index 90b1b98e57f..997590f9b35 100644
--- a/odoo/tools/parse_version.py
+++ b/odoo/tools/parse_version.py
@@ -63,12 +63,6 @@ def parse_version(s):
return tuple(parts)
if __name__ == '__main__':
-
- def cmp(a, b):
- msg = '%s < %s == %s' % (a, b, a < b)
- assert a < b, msg
- return b
-
def chk(lst, verbose=False):
pvs = []
for v in lst:
@@ -76,7 +70,9 @@ if __name__ == '__main__':
pvs.append(pv)
if verbose:
print v, pv
- reduce(cmp, pvs)
+
+ for a, b in zip(pvs, pvs[1:]):
+ assert a < b, '%s < %s == %s' % (a, b, a < b)
chk(('0', '4.2', '4.2.3.4', '5.0.0-alpha', '5.0.0-rc1', '5.0.0-rc1.1', '5.0.0_rc2', '5.0.0_rc3', '5.0.0'), False)
chk(('5.0.0-0_rc3', '5.0.0-1dev', '5.0.0-1'), False)
diff --git a/odoo/tools/translate.py b/odoo/tools/translate.py
index b33b356a2f9..850e911d608 100644
--- a/odoo/tools/translate.py
+++ b/odoo/tools/translate.py
@@ -599,7 +599,7 @@ class PoFile(object):
% { 'project': release.description,
'version': release.version,
- 'modules': reduce(lambda s, m: s + "#\t* %s\n" % m, modules, ""),
+ 'modules': ''.join("#\t* %s\n" % m for m in modules),
'now': datetime.utcnow().strftime('%Y-%m-%d %H:%M')+"+0000",
}
)