From bf668b64c13408fdcc419b7c99481441db4a3918 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 9 Aug 2016 14:30:02 +0200 Subject: [PATCH] [IMP] all: clean usage of `safe_eval` Specifically: do not import `safe_eval` as `eval`, keep it explicit instead. --- .../account/wizard/account_invoice_refund.py | 4 +- .../report/report_account_test.py | 4 +- .../anonymization/wizard/anonymize_wizard.py | 4 +- .../models/base_action_rule.py | 22 +++++------ addons/crm/models/crm_team.py | 6 +-- addons/delivery/models/delivery_carrier.py | 4 +- addons/google_drive/models/google_drive.py | 6 +-- addons/hr_payroll/models/hr_payroll.py | 14 +++---- addons/mail/models/mail_alias.py | 4 +- addons/mail/models/mail_channel.py | 4 +- addons/mail/models/mail_mail.py | 4 +- addons/mail/models/mail_thread.py | 6 +-- addons/mail/wizard/mail_compose_message.py | 4 +- .../models/marketing_campaign.py | 6 +-- addons/mass_mailing/models/mass_mailing.py | 4 +- addons/project/models/project.py | 4 +- addons/project_issue/models/project_issue.py | 4 +- addons/report/controllers/main.py | 4 +- addons/report/models/report.py | 4 +- addons/stock/models/product.py | 6 +-- addons/web_diagram/controllers/main.py | 6 +-- .../models/mail_channel.py | 4 +- openerp/addons/base/ir/ir_actions.py | 18 ++++----- openerp/addons/base/ir/ir_cron.py | 4 +- openerp/addons/base/ir/ir_rule.py | 4 +- openerp/addons/base/ir/ir_ui_menu.py | 8 ++-- openerp/addons/base/ir/ir_ui_view.py | 4 +- openerp/addons/base/res/res_lang.py | 6 +-- openerp/models.py | 18 ++++----- openerp/modules/graph.py | 1 - openerp/modules/module.py | 4 +- openerp/osv/orm.py | 6 +-- openerp/report/custom.py | 12 +++--- openerp/report/printscreen/ps_list.py | 4 +- openerp/report/render/rml2pdf/trml2pdf.py | 4 +- openerp/report/render/rml2pdf/utils.py | 14 +++---- openerp/report/render/rml2txt/utils.py | 12 +++--- openerp/report/report_sxw.py | 4 +- openerp/tools/convert.py | 14 +++---- openerp/tools/yaml_import.py | 38 +++++++++---------- openerp/workflow/workitem.py | 4 +- 41 files changed, 153 insertions(+), 154 deletions(-) diff --git a/addons/account/wizard/account_invoice_refund.py b/addons/account/wizard/account_invoice_refund.py index e32d2745a40..e6b071ea801 100644 --- a/addons/account/wizard/account_invoice_refund.py +++ b/addons/account/wizard/account_invoice_refund.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from odoo import models, fields, api, _ -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.exceptions import UserError @@ -117,7 +117,7 @@ class AccountInvoiceRefund(models.TransientModel): refund.message_post(body=body, subject=subject) if xml_id: result = self.env.ref('account.%s' % (xml_id)).read()[0] - invoice_domain = eval(result['domain']) + invoice_domain = safe_eval(result['domain']) invoice_domain.append(('id', 'in', created_inv)) result['domain'] = invoice_domain return result diff --git a/addons/account_test/report/report_account_test.py b/addons/account_test/report/report_account_test.py index 921e79ac541..9b1154dd45a 100644 --- a/addons/account_test/report/report_account_test.py +++ b/addons/account_test/report/report_account_test.py @@ -3,7 +3,7 @@ import datetime from odoo import api, models, _ -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval # # Use period and Journal for selection or resources # @@ -41,7 +41,7 @@ class ReportAssertAccount(models.AbstractModel): 'result': None, # used to store the result of the test 'column_order': None, # used to choose the display order of columns (in case you are returning a list of dict) } - eval(code_exec, localdict, mode="exec", nocopy=True) + safe_eval(code_exec, localdict, mode="exec", nocopy=True) result = localdict['result'] column_order = localdict.get('column_order', None) diff --git a/addons/anonymization/wizard/anonymize_wizard.py b/addons/anonymization/wizard/anonymize_wizard.py index 0575120f1d6..a4fc1442298 100644 --- a/addons/anonymization/wizard/anonymize_wizard.py +++ b/addons/anonymization/wizard/anonymize_wizard.py @@ -14,7 +14,7 @@ from operator import itemgetter from odoo import api, fields, models, _ from odoo.exceptions import UserError from odoo.release import version_info -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.addons.anonymization.models.anonymization import group WIZARD_ANONYMIZATION_STATES = [('clear', 'Clear'), ('anonymized', 'Anonymized'), ('unstable', 'Unstable')] @@ -294,7 +294,7 @@ class IrModelFieldsAnonymizeWizard(models.TransientModel): 'id': line['id'] }) elif query[1] == 'python': - eval(query[0] % line) + safe_eval(query[0] % line) else: raise Exception("Unknown query type '%s'. Valid types are: sql, python." % (query['query_type'], )) diff --git a/addons/base_action_rule/models/base_action_rule.py b/addons/base_action_rule/models/base_action_rule.py index 50cbfced8fb..8cb88149597 100644 --- a/addons/base_action_rule/models/base_action_rule.py +++ b/addons/base_action_rule/models/base_action_rule.py @@ -12,7 +12,7 @@ from dateutil.relativedelta import relativedelta from odoo import api, fields, models, SUPERUSER_ID from odoo.modules.registry import RegistryManager -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -143,7 +143,7 @@ class BaseActionRule(models.Model): def _get_eval_context(self): """ Prepare the context used when evaluating python code - :returns: dict -- evaluation context given to (safe_)eval + :returns: dict -- evaluation context given to safe_eval """ return { 'datetime': datetime, @@ -156,11 +156,11 @@ class BaseActionRule(models.Model): def _filter_pre(self, records): """ Filter the records that satisfy the precondition of action ``self``. """ if self.filter_pre_id and records: - domain = [('id', 'in', records.ids)] + eval(self.filter_pre_id.domain, self._get_eval_context()) - ctx = eval(self.filter_pre_id.context) + domain = [('id', 'in', records.ids)] + safe_eval(self.filter_pre_id.domain, self._get_eval_context()) + ctx = safe_eval(self.filter_pre_id.context) return records.with_context(**ctx).search(domain).with_env(records.env) elif self.filter_pre_domain and records: - domain = [('id', 'in', records.ids)] + eval(self.filter_pre_domain, self._get_eval_context()) + domain = [('id', 'in', records.ids)] + safe_eval(self.filter_pre_domain, self._get_eval_context()) return records.search(domain) else: return records @@ -168,11 +168,11 @@ class BaseActionRule(models.Model): def _filter_post(self, records): """ Filter the records that satisfy the postcondition of action ``self``. """ if self.filter_id and records: - domain = [('id', 'in', records.ids)] + eval(self.filter_id.domain, self._get_eval_context()) - ctx = eval(self.filter_id.context) + domain = [('id', 'in', records.ids)] + safe_eval(self.filter_id.domain, self._get_eval_context()) + ctx = safe_eval(self.filter_id.context) return records.with_context(**ctx).search(domain).with_env(records.env) elif self.filter_domain and records: - domain = [('id', 'in', records.ids)] + eval(self.filter_domain, self._get_eval_context()) + domain = [('id', 'in', records.ids)] + safe_eval(self.filter_domain, self._get_eval_context()) return records.search(domain) else: return records @@ -352,10 +352,10 @@ class BaseActionRule(models.Model): domain = [] context = dict(self._context) if action.filter_domain: - domain = eval(action.filter_domain, eval_context) + domain = safe_eval(action.filter_domain, eval_context) elif action.filter_id: - domain = eval(action.filter_id.domain, eval_context) - context.update(eval(action.filter_id.context)) + domain = safe_eval(action.filter_id.domain, eval_context) + context.update(safe_eval(action.filter_id.context)) if 'lang' not in context: # Filters might be language-sensitive, attempt to reuse creator lang # as we are usually running this as super-user in background diff --git a/addons/crm/models/crm_team.py b/addons/crm/models/crm_team.py index 39ac597ce41..71f5a646400 100644 --- a/addons/crm/models/crm_team.py +++ b/addons/crm/models/crm_team.py @@ -2,7 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval class Team(models.Model): @@ -22,7 +22,7 @@ class Team(models.Model): def get_alias_values(self): has_group_use_lead = self.env.user.has_group('crm.group_use_lead') values = super(Team, self).get_alias_values() - values['alias_defaults'] = defaults = eval(self.alias_defaults or "{}") + values['alias_defaults'] = defaults = safe_eval(self.alias_defaults or "{}") defaults['type'] = 'lead' if has_group_use_lead and self.use_leads else 'opportunity' defaults['team_id'] = self.id return values @@ -61,7 +61,7 @@ class Team(models.Model): if user_team_id: action['help'] += "

As you don't belong to any sales team, Odoo opens the first one by default.

" - action_context = eval(action['context'], {'uid': self.env.uid}) + action_context = safe_eval(action['context'], {'uid': self.env.uid}) if user_team_id: action_context['default_team_id'] = user_team_id diff --git a/addons/delivery/models/delivery_carrier.py b/addons/delivery/models/delivery_carrier.py index 016b3c3a95d..ee2d61753b6 100644 --- a/addons/delivery/models/delivery_carrier.py +++ b/addons/delivery/models/delivery_carrier.py @@ -5,7 +5,7 @@ import logging from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -287,7 +287,7 @@ class DeliveryCarrier(models.Model): criteria_found = False price_dict = {'price': total, 'volume': volume, 'weight': weight, 'wv': volume * weight, 'quantity': quantity} for line in self.price_rule_ids: - test = eval(line.variable + line.operator + str(line.max_value), price_dict) + test = safe_eval(line.variable + line.operator + str(line.max_value), price_dict) if test: price = line.list_base_price + line.list_price * price_dict[line.variable_factor] criteria_found = True diff --git a/addons/google_drive/models/google_drive.py b/addons/google_drive/models/google_drive.py index ffc8c33d2f2..0a65ffb175e 100644 --- a/addons/google_drive/models/google_drive.py +++ b/addons/google_drive/models/google_drive.py @@ -8,7 +8,7 @@ import werkzeug.urls from odoo import api, fields, models from odoo.exceptions import RedirectWarning, UserError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.tools.translate import _ from odoo.addons.google_account.models.google_service import GOOGLE_TOKEN_ENDPOINT, TIMEOUT @@ -165,8 +165,8 @@ class GoogleDrive(models.Model): if config.filter_id.user_id and config.filter_id.user_id.id != self.env.user.id: #Private continue - domain = [('id', 'in', [res_id])] + eval(config.filter_id.domain) - additionnal_context = eval(config.filter_id.context) + domain = [('id', 'in', [res_id])] + safe_eval(config.filter_id.domain) + additionnal_context = safe_eval(config.filter_id.context) google_doc_configs = self.env[config.filter_id.model_id].with_context(**additionnal_context).search(domain) if google_doc_configs: config_values.append({'id': config.id, 'name': config.name}) diff --git a/addons/hr_payroll/models/hr_payroll.py b/addons/hr_payroll/models/hr_payroll.py index 605f1317354..e1ee7f84bdb 100644 --- a/addons/hr_payroll/models/hr_payroll.py +++ b/addons/hr_payroll/models/hr_payroll.py @@ -7,7 +7,7 @@ from dateutil import relativedelta from odoo import api, fields, models, tools, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.addons import decimal_precision as dp @@ -756,19 +756,19 @@ class HrSalaryRule(models.Model): self.ensure_one() if self.amount_select == 'fix': try: - return self.amount_fix, float(eval(self.quantity, localdict)), 100.0 + return self.amount_fix, float(safe_eval(self.quantity, localdict)), 100.0 except: raise UserError(_('Wrong quantity defined for salary rule %s (%s).') % (self.name, self.code)) elif self.amount_select == 'percentage': try: - return (float(eval(self.amount_percentage_base, localdict)), - float(eval(self.quantity, localdict)), + return (float(safe_eval(self.amount_percentage_base, localdict)), + float(safe_eval(self.quantity, localdict)), self.amount_percentage) except: raise UserError(_('Wrong percentage base or quantity defined for salary rule %s (%s).') % (self.name, self.code)) else: try: - eval(self.amount_python_compute, localdict, mode='exec', nocopy=True) + safe_eval(self.amount_python_compute, localdict, mode='exec', nocopy=True) return float(localdict['result']), 'result_qty' in localdict and localdict['result_qty'] or 1.0, 'result_rate' in localdict and localdict['result_rate'] or 100.0 except: raise UserError(_('Wrong python code defined for salary rule %s (%s).') % (self.name, self.code)) @@ -785,13 +785,13 @@ class HrSalaryRule(models.Model): return True elif self.condition_select == 'range': try: - result = eval(self.condition_range, localdict) + result = safe_eval(self.condition_range, localdict) return self.condition_range_min <= result and result <= self.condition_range_max or False except: raise UserError(_('Wrong range condition defined for salary rule %s (%s).') % (self.name, self.code)) else: # python code try: - eval(self.condition_python, localdict, mode='exec', nocopy=True) + safe_eval(self.condition_python, localdict, mode='exec', nocopy=True) return 'result' in localdict and localdict['result'] or False except: raise UserError(_('Wrong python condition defined for salary rule %s (%s).') % (self.name, self.code)) diff --git a/addons/mail/models/mail_alias.py b/addons/mail/models/mail_alias.py index d55a4c6b1c2..6acf894c996 100644 --- a/addons/mail/models/mail_alias.py +++ b/addons/mail/models/mail_alias.py @@ -8,7 +8,7 @@ import unicodedata from odoo import _, api, fields, models from odoo.exceptions import ValidationError from odoo.tools import ustr -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -94,7 +94,7 @@ class Alias(models.Model): @api.constrains('alias_defaults') def _check_alias_defaults(self): try: - dict(eval(self.alias_defaults)) + dict(safe_eval(self.alias_defaults)) except Exception: raise ValidationError(_('Invalid expression, it must be a literal python dictionary definition e.g. "{\'field\': \'value\'}"')) diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index 94582dcf2a1..9bd26851605 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -10,7 +10,7 @@ from odoo import _, api, fields, models, modules, tools from odoo.exceptions import UserError from odoo.osv import expression from odoo.tools import ormcache -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval class ChannelPartner(models.Model): @@ -184,7 +184,7 @@ class Channel(models.Model): headers = {} if res.get('headers'): try: - headers.update(eval(res['headers'])) + headers.update(safe_eval(res['headers'])) except Exception: pass headers['Precedence'] = 'list' diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py index 13280a2a15f..4ad711e09c6 100644 --- a/addons/mail/models/mail_mail.py +++ b/addons/mail/models/mail_mail.py @@ -12,7 +12,7 @@ from email.utils import formataddr from odoo import _, api, fields, models from odoo import tools from odoo.addons.base.ir.ir_mail_server import MailDeliveryException -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -227,7 +227,7 @@ class MailMail(models.Model): headers['Return-Path'] = '%s-%d@%s' % (bounce_alias, mail.id, catchall_domain) if mail.headers: try: - headers.update(eval(mail.headers)) + headers.update(safe_eval(mail.headers)) except Exception: pass diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 728903c070b..3e07a89594b 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -22,7 +22,7 @@ from werkzeug import url_encode from odoo import _, api, exceptions, fields, models, tools from odoo.addons.mail.models.mail_message import decode -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -371,7 +371,7 @@ class MailThread(models.AbstractModel): doc = etree.XML(res['arch']) for node in doc.xpath("//field[@name='message_ids']"): # the 'Log a note' button is employee only - options = eval(node.get('options', '{}')) + options = safe_eval(node.get('options', '{}')) is_employee = self.env.user.has_group('base.group_user') options['display_log_button'] = is_employee # emoji list @@ -1092,7 +1092,7 @@ class MailThread(models.AbstractModel): # user_id = self._message_find_user_id(message) user_id = self._uid _logger.info('No matching user_id for the alias %s', alias.alias_name) - route = (alias.alias_model_id.model, alias.alias_force_thread_id, eval(alias.alias_defaults), user_id, alias) + route = (alias.alias_model_id.model, alias.alias_force_thread_id, safe_eval(alias.alias_defaults), user_id, alias) route = self.message_route_verify( message, message_dict, route, update_author=True, assert_model=True, create_fallback=True) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 5e893c9124b..e60ac5db4e7 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -5,7 +5,7 @@ import base64 import re from odoo import _, api, fields, models, SUPERUSER_ID, tools -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval # main mako-like expression pattern @@ -230,7 +230,7 @@ class MailComposer(models.TransientModel): ActiveModel = ActiveModel.with_context(mail_notify_force_send=False, mail_create_nosubscribe=True) # wizard works in batch mode: [res_id] or active_ids or active_domain if mass_mode and wizard.use_active_domain and wizard.model: - res_ids = self.env[wizard.model].search(eval(wizard.active_domain)).ids + res_ids = self.env[wizard.model].search(safe_eval(wizard.active_domain)).ids elif mass_mode and wizard.model and self._context.get('active_ids'): res_ids = self._context['active_ids'] else: diff --git a/addons/marketing_campaign/models/marketing_campaign.py b/addons/marketing_campaign/models/marketing_campaign.py index ef648fb0c31..df30bf73a94 100644 --- a/addons/marketing_campaign/models/marketing_campaign.py +++ b/addons/marketing_campaign/models/marketing_campaign.py @@ -9,7 +9,7 @@ import re from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval import odoo.addons.decimal_precision as dp @@ -247,7 +247,7 @@ class MarketingCampaignSegment(models.Model): if segment.sync_last_date and segment.sync_mode != 'all': criteria += [(segment.sync_mode, '>', segment.sync_last_date)] if segment.ir_filter_id: - criteria += eval(segment.ir_filter_id.domain) + criteria += safe_eval(segment.ir_filter_id.domain) # XXX TODO: rewrite this loop more efficiently without doing 1 search per record! for record in self.env[segment.object_id.model].search(criteria): @@ -485,7 +485,7 @@ class MarketingCampaignWorkitem(models.Model): condition = activity.condition campaign_mode = self.campaign_id.mode if condition: - if not eval(condition, eval_context): + if not safe_eval(condition, eval_context): if activity.keep_if_condition_not_met: self.write({'state': 'cancelled'}) else: diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py index ee56238eb76..f5138032a11 100644 --- a/addons/mass_mailing/models/mass_mailing.py +++ b/addons/mass_mailing/models/mass_mailing.py @@ -6,7 +6,7 @@ import random from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval class MassMailingTag(models.Model): @@ -540,7 +540,7 @@ class MassMailing(models.Model): def get_recipients(self): if self.mailing_domain: - domain = eval(self.mailing_domain) + domain = safe_eval(self.mailing_domain) res_ids = self.env[self.mailing_model].search(domain).ids else: res_ids = [] diff --git a/addons/project/models/project.py b/addons/project/models/project.py index d49ab24724a..5e7d4989be0 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -5,7 +5,7 @@ from lxml import etree from odoo import api, fields, models, tools, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval class ProjectTaskType(models.Model): @@ -670,7 +670,7 @@ class Task(models.Model): headers = {} if res.get('headers'): try: - headers.update(eval(res['headers'])) + headers.update(safe_eval(res['headers'])) except Exception: pass if self.project_id: diff --git a/addons/project_issue/models/project_issue.py b/addons/project_issue/models/project_issue.py index 7c0598ea54e..0b38b972494 100644 --- a/addons/project_issue/models/project_issue.py +++ b/addons/project_issue/models/project_issue.py @@ -3,7 +3,7 @@ from odoo import api, fields, models, tools, _ from odoo.exceptions import AccessError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval class ProjectIssue(models.Model): @@ -351,7 +351,7 @@ class ProjectIssue(models.Model): headers = {} if res.get('headers'): try: - headers.update(eval(res['headers'])) + headers.update(safe_eval(res['headers'])) except Exception: pass if self.project_id: diff --git a/addons/report/controllers/main.py b/addons/report/controllers/main.py index fbac92a8926..aad5d3a23ea 100644 --- a/addons/report/controllers/main.py +++ b/addons/report/controllers/main.py @@ -11,7 +11,7 @@ from werkzeug.wrappers import BaseResponse from odoo.http import Controller, route, request from odoo.tools import html_escape from odoo.addons.web.controllers.main import _serialize_exception, content_disposition -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval class ReportController(Controller): @@ -105,7 +105,7 @@ class ReportController(Controller): ids = [int(x) for x in docids.split(",")] obj = request.env[report.model].browse(ids) if report.print_report_name and not len(obj) > 1: - filename = eval(report.print_report_name, {'object': obj, 'time': time}) + filename = safe_eval(report.print_report_name, {'object': obj, 'time': time}) response.headers.add('Content-Disposition', content_disposition(filename)) response.set_cookie('fileToken', token) return response diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 78b52a3cd87..e88c5777f1a 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -7,7 +7,7 @@ from odoo.sql_db import TestCursor from odoo.tools import config from odoo.tools.misc import find_in_path from odoo.http import request -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.exceptions import UserError import base64 @@ -327,7 +327,7 @@ class Report(models.Model): @api.model def _attachment_filename(self, records, report): - return dict((record.id, eval(report.attachment, {'object': record, 'time': time})) for record in records) + return dict((record.id, safe_eval(report.attachment, {'object': record, 'time': time})) for record in records) @api.model def _attachment_stored(self, records, report, filenames=None): diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py index 50d07bf1d31..a64d8c5775d 100644 --- a/addons/stock/models/product.py +++ b/addons/stock/models/product.py @@ -4,7 +4,7 @@ from odoo import api, fields, models, _ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.tools.float_utils import float_round @@ -238,7 +238,7 @@ class Product(models.Model): # TODO: Still optimization possible when searching virtual quantities ids = [] for product in self.search([]): - if eval(str(product[field]) + operator + str(value)): + if safe_eval(str(product[field]) + operator + str(value)): ids.append(product.id) return [('id', 'in', ids)] @@ -261,7 +261,7 @@ class Product(models.Model): domain_quant.append(('package_id', '=', package_id)) quants_groupby = self.env['stock.quant'].read_group(domain_quant, ['product_id', 'qty'], ['product_id']) for quant in quants_groupby: - if eval('%s %s %s' % (quant['qty'], operator, value)): + if safe_eval('%s %s %s' % (quant['qty'], operator, value)): product_ids.add(quant['product_id'][0]) return list(product_ids) diff --git a/addons/web_diagram/controllers/main.py b/addons/web_diagram/controllers/main.py index 0b661623e3c..ebc3f4402e5 100644 --- a/addons/web_diagram/controllers/main.py +++ b/addons/web_diagram/controllers/main.py @@ -4,7 +4,7 @@ import odoo import odoo.http as http -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval class DiagramView(http.Controller): @@ -99,11 +99,11 @@ class DiagramView(http.Controller): options={} ) for color, expr in bgcolors.items(): - if eval(expr, act): + if safe_eval(expr, act): n['color'] = color for shape, expr in shapes.items(): - if eval(expr, act): + if safe_eval(expr, act): n['shape'] = shape for i, fld in enumerate(visible_node_fields): diff --git a/addons/website_mail_channel/models/mail_channel.py b/addons/website_mail_channel/models/mail_channel.py index fb1db7ce97b..5cc8163c81c 100644 --- a/addons/website_mail_channel/models/mail_channel.py +++ b/addons/website_mail_channel/models/mail_channel.py @@ -6,7 +6,7 @@ import hmac from urlparse import urljoin from odoo import api, models -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.addons.website.models.website import slug @@ -21,7 +21,7 @@ class MailGroup(models.Model): headers = {} if res.get('headers'): try: - headers = eval(res['headers']) + headers = safe_eval(res['headers']) except Exception: pass headers.update({ diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 922174b8306..c7a68726129 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -12,7 +12,7 @@ import odoo from odoo import api, fields, models, tools, workflow, _ from odoo.exceptions import MissingError, UserError, ValidationError from odoo.report.report_sxw import report_sxw, report_rml -from odoo.tools.safe_eval import safe_eval as eval, test_python_expr +from odoo.tools.safe_eval import safe_eval, test_python_expr _logger = logging.getLogger(__name__) @@ -795,7 +795,7 @@ class IrActionsServer(models.Model): @api.model def run_action_code_multi(self, action, eval_context=None): - eval(action.code.strip(), eval_context, mode="exec", nocopy=True) # nocopy allows to return 'action' + safe_eval(action.code.strip(), eval_context, mode="exec", nocopy=True) # nocopy allows to return 'action' if 'action' in eval_context: return eval_context['action'] @@ -848,7 +848,7 @@ class IrActionsServer(models.Model): ref_id = action.ref_object.id elif action.use_write == 'expression': model = action.crud_model_id.model - ref = eval(action.write_expression, eval_context) + ref = safe_eval(action.write_expression, eval_context) if isinstance(ref, models.BaseModel): ref_id = ref.id else: @@ -897,7 +897,7 @@ class IrActionsServer(models.Model): :param action: the current server action :type action: browse record - :returns: dict -- evaluation context given to (safe_)eval """ + :returns: dict -- evaluation context given to (safe_)safe_eval """ def log(message, level="info"): self._cr.execute(""" INSERT INTO ir_logging(create_date, create_uid, type, dbname, name, level, message, path, line, func) @@ -961,7 +961,7 @@ class IrActionsServer(models.Model): # Void (aka False) conditions are considered as True condition = True if hasattr(self, 'run_action_%s_multi' % action.state): - expr = eval(str(condition), eval_context) + expr = safe_eval(str(condition), eval_context) if not expr: continue # call the multi method @@ -976,7 +976,7 @@ class IrActionsServer(models.Model): # run context dedicated to a particular active_id run_self = self.with_context(active_ids=[active_id], active_id=active_id) eval_context["context"] = run_self._context - expr = eval(str(condition), eval_context) + expr = safe_eval(str(condition), eval_context) if not expr: continue # call the single method related to the action: run_action_ @@ -1004,7 +1004,7 @@ class IrServerObjectLines(models.Model): for line in self: expr = line.value if line.type == 'equation': - expr = eval(line.value, eval_context) + expr = safe_eval(line.value, eval_context) elif line.col1.ttype in ['many2one', 'integer']: try: expr = int(line.value) @@ -1077,7 +1077,7 @@ class IrActionsTodo(models.Model): result.setdefault('context', '{}') # Open a specific record when res_id is provided in the context - ctx = eval(result['context'], {'user': self.env.user}) + ctx = safe_eval(result['context'], {'user': self.env.user}) if ctx.get('res_id'): result['res_id'] = ctx.pop('res_id') @@ -1145,7 +1145,7 @@ class IrActionsActClient(models.Model): def _compute_params(self): self_bin = self.with_context(bin_size=False, bin_size_params_store=False) for record, record_bin in zip(self, self_bin): - record.params = record_bin.params_store and eval(record_bin.params_store, {'uid': self._uid}) + record.params = record_bin.params_store and safe_eval(record_bin.params_store, {'uid': self._uid}) def _inverse_params(self): for record in self: diff --git a/openerp/addons/base/ir/ir_cron.py b/openerp/addons/base/ir/ir_cron.py index d1bb7f62ec9..0e1e26986a4 100644 --- a/openerp/addons/base/ir/ir_cron.py +++ b/openerp/addons/base/ir/ir_cron.py @@ -11,7 +11,7 @@ from dateutil.relativedelta import relativedelta import odoo from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -19,7 +19,7 @@ BASE_VERSION = odoo.modules.load_information_from_description_file('base')['vers def str2tuple(s): - return eval('tuple(%s)' % (s or '')) + return safe_eval('tuple(%s)' % (s or '')) _intervalTypes = { 'work_days': lambda interval: relativedelta(days=interval), diff --git a/openerp/addons/base/ir/ir_rule.py b/openerp/addons/base/ir/ir_rule.py index 5e571c1347b..0ee84016446 100644 --- a/openerp/addons/base/ir/ir_rule.py +++ b/openerp/addons/base/ir/ir_rule.py @@ -6,7 +6,7 @@ from collections import defaultdict from odoo import api, fields, models, tools, SUPERUSER_ID, _ from odoo.exceptions import ValidationError from odoo.osv import expression -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval class IrRule(models.Model): @@ -50,7 +50,7 @@ class IrRule(models.Model): eval_context = self._eval_context() for rule in self: if rule.domain_force: - rule.domain = expression.normalize_domain(eval(rule.domain_force, eval_context)) + rule.domain = expression.normalize_domain(safe_eval(rule.domain_force, eval_context)) else: rule.domain = [] diff --git a/openerp/addons/base/ir/ir_ui_menu.py b/openerp/addons/base/ir/ir_ui_menu.py index fe205eb9307..1f2b746f082 100644 --- a/openerp/addons/base/ir/ir_ui_menu.py +++ b/openerp/addons/base/ir/ir_ui_menu.py @@ -9,7 +9,7 @@ from odoo import api, fields, models, tools, _ from odoo.exceptions import ValidationError from odoo.http import request from odoo.modules import get_module_resource -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval MENU_ITEM_SEPARATOR = "/" NUMBER_PARENS = re.compile(r"\(([0-9]+)\)") @@ -195,7 +195,7 @@ class IrUiMenu(models.Model): with tools.ignore(Exception): # use magical UnquoteEvalContext to ignore undefined client-side variables such as `active_id` eval_ctx = tools.UnquoteEvalContext(self._context) - ctx = eval(menu.action.context, locals_dict=eval_ctx, nocopy=True) or {} + ctx = safe_eval(menu.action.context, locals_dict=eval_ctx, nocopy=True) or {} menu_refs = ctx.get('needaction_menu_ref') if menu_refs: if not isinstance(menu_refs, list): @@ -217,9 +217,9 @@ class IrUiMenu(models.Model): if model._needaction: if menu.action.type == 'ir.actions.act_window': eval_context = self.env['ir.actions.act_window']._get_eval_context() - dom = eval(menu.action.domain or '[]', eval_context) + dom = safe_eval(menu.action.domain or '[]', eval_context) else: - dom = eval(menu.action.params_store or '{}', {'uid': self._uid}).get('domain') + dom = safe_eval(menu.action.params_store or '{}', {'uid': self._uid}).get('domain') res[menu.id]['needaction_enabled'] = model._needaction res[menu.id]['needaction_counter'] = model._needaction_count(dom) return res diff --git a/openerp/addons/base/ir/ir_ui_view.py b/openerp/addons/base/ir/ir_ui_view.py index 03d76a94dc8..ef565dcfb47 100644 --- a/openerp/addons/base/ir/ir_ui_view.py +++ b/openerp/addons/base/ir/ir_ui_view.py @@ -24,7 +24,7 @@ from odoo.osv import orm from odoo.tools import config, graph, ConstantMapping, SKIPPED_ELEMENT_TYPES from odoo.tools.convert import _fix_multiple_roots from odoo.tools.parse_version import parse_version -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.tools.view_validation import valid_view from odoo.tools.translate import encode, xml_translate, TRANSLATED_ATTRS @@ -1091,7 +1091,7 @@ actual arch. tres[str(t['id'])] = (line.id, t[des_node].id) label_string = "" if label: - for lbl in eval(label): + for lbl in safe_eval(label): if tools.ustr(lbl) in t and tools.ustr(t[lbl]) == 'False': label_string += ' ' else: diff --git a/openerp/addons/base/res/res_lang.py b/openerp/addons/base/res/res_lang.py index 0b7d1c4623e..09d5825966f 100644 --- a/openerp/addons/base/res/res_lang.py +++ b/openerp/addons/base/res/res_lang.py @@ -7,7 +7,7 @@ import re from operator import itemgetter from odoo import api, fields, models, tools, _ -from odoo.tools.safe_eval import safe_eval as eval +from odoo.tools.safe_eval import safe_eval from odoo.exceptions import UserError, ValidationError _logger = logging.getLogger(__name__) @@ -69,7 +69,7 @@ class Lang(models.Model): 'Provided as the thousand separator in each case.') for lang in self: try: - if not all(isinstance(x, int) for x in eval(lang.grouping)): + if not all(isinstance(x, int) for x in safe_eval(lang.grouping)): raise ValidationError(warning) except Exception: raise ValidationError(warning) @@ -264,7 +264,7 @@ class Lang(models.Model): # floats and decimal ints need special action! if grouping: lang_grouping, thousands_sep, decimal_point = self._data_get(monetary) - eval_lang_grouping = eval(lang_grouping) + eval_lang_grouping = safe_eval(lang_grouping) if percent[-1] in 'eEfFgG': parts = formatted.split('.') diff --git a/openerp/models.py b/openerp/models.py index 96fbf0a8af8..4a2fc81550c 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -52,7 +52,7 @@ from .tools import frozendict, lazy_property, ormcache, Collector, LastOrderedSe from .tools.config import config from .tools.func import frame_codeinfo from .tools.misc import CountingStream, DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT, pickle -from .tools.safe_eval import safe_eval as eval +from .tools.safe_eval import safe_eval from .tools.translate import _ _logger = logging.getLogger(__name__) @@ -66,7 +66,7 @@ onchange_v7 = re.compile(r"^(\w+)\((.*)\)$") AUTOINIT_RECALCULATE_STORED_FIELDS = 1000 -# base environment for doing a safe eval +# base environment for doing a safe_eval SAFE_EVAL_BASE = { 'datetime': datetime, 'dateutil': dateutil, @@ -75,7 +75,7 @@ SAFE_EVAL_BASE = { def make_compute(text, deps): """ Return a compute function from its code body and dependencies. """ - func = lambda self: eval(text, SAFE_EVAL_BASE, {'self': self}, mode="exec") + func = lambda self: safe_eval(text, SAFE_EVAL_BASE, {'self': self}, mode="exec") deps = [arg.strip() for arg in (deps or "").split(",")] return api.depends(*deps)(func) @@ -770,13 +770,13 @@ class BaseModel(object): attrs['translate'] = bool(field['translate']) attrs['size'] = field['size'] or None elif field['ttype'] in ('selection', 'reference'): - attrs['selection'] = eval(field['selection']) + attrs['selection'] = safe_eval(field['selection']) elif field['ttype'] == 'many2one': if partial and field['relation'] not in self.pool: continue attrs['comodel_name'] = field['relation'] attrs['ondelete'] = field['on_delete'] - attrs['domain'] = eval(field['domain']) if field['domain'] else None + attrs['domain'] = safe_eval(field['domain']) if field['domain'] else None elif field['ttype'] == 'one2many': if partial and not ( field['relation'] in self.pool and ( @@ -786,7 +786,7 @@ class BaseModel(object): continue attrs['comodel_name'] = field['relation'] attrs['inverse_name'] = field['relation_field'] - attrs['domain'] = eval(field['domain']) if field['domain'] else None + attrs['domain'] = safe_eval(field['domain']) if field['domain'] else None elif field['ttype'] == 'many2many': if partial and field['relation'] not in self.pool: continue @@ -795,7 +795,7 @@ class BaseModel(object): attrs['relation'] = field['relation_table'] or rel attrs['column1'] = field['column1'] or col1 attrs['column2'] = field['column2'] or col2 - attrs['domain'] = eval(field['domain']) if field['domain'] else None + attrs['domain'] = safe_eval(field['domain']) if field['domain'] else None # add compute function if given if field['compute']: attrs['compute'] = make_compute(field['compute'], field['depends']) @@ -3477,7 +3477,7 @@ class BaseModel(object): '(a dictionary was expected).' % (fs[0], self._name) for vals in result: # TOCHECK : why got string instend of dict in python2.6 - # if isinstance(res2[vals['id']], str): res2[vals['id']] = eval(res2[vals['id']]) + # if isinstance(res2[vals['id']], str): res2[vals['id']] = safe_eval(res2[vals['id']]) multi_fields = res2.get(vals['id'], {}) if multi_fields: for f in fs: @@ -5965,7 +5965,7 @@ class BaseModel(object): record = self[self._context['field_parent']] global_vars['parent'] = RawRecord(record) field_vars = RawRecord(self) - params = eval("[%s]" % params, global_vars, field_vars, nocopy=True) + params = safe_eval("[%s]" % params, global_vars, field_vars, nocopy=True) # call onchange method with context when possible args = (self._cr, self._uid, self._origin.ids) + tuple(params) diff --git a/openerp/modules/graph.py b/openerp/modules/graph.py index 9b311c666de..f3e7e485031 100644 --- a/openerp/modules/graph.py +++ b/openerp/modules/graph.py @@ -13,7 +13,6 @@ import openerp import openerp.osv as osv import openerp.tools as tools import openerp.tools.osutil as osutil -from openerp.tools.safe_eval import safe_eval as eval from openerp.tools.translate import _ import zipfile diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 43b3f01b93b..abc14bfc841 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -23,7 +23,7 @@ import openerp import openerp.tools as tools import openerp.release as release from openerp import SUPERUSER_ID -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval MANIFEST = '__openerp__.py' README = ['README.rst', 'README.md', 'README.txt'] @@ -318,7 +318,7 @@ def load_information_from_description_file(module, mod_path=None): f = tools.file_open(terp_file) try: - info.update(eval(f.read())) + info.update(safe_eval(f.read())) finally: f.close() diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 7b4c983bcb0..39bd965006b 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -11,7 +11,7 @@ from ..models import ( LOG_ACCESS_COLUMNS, ) -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval # extra definitions for backward compatibility browse_record_list = BaseModel @@ -52,7 +52,7 @@ def transfer_field_to_modifiers(field, modifiers): # For non-tree views, the context shouldn't be given. def transfer_node_to_modifiers(node, modifiers, context=None, in_tree_view=False): if node.get('attrs'): - modifiers.update(eval(node.get('attrs'))) + modifiers.update(safe_eval(node.get('attrs'))) if node.get('states'): if 'invisible' in modifiers and isinstance(modifiers['invisible'], list): @@ -63,7 +63,7 @@ def transfer_node_to_modifiers(node, modifiers, context=None, in_tree_view=False for a in ('invisible', 'readonly', 'required'): if node.get(a): - v = bool(eval(node.get(a), {'context': context or {}})) + v = bool(safe_eval(node.get(a), {'context': context or {}})) if in_tree_view and a == 'invisible': # Invisible in a tree view has a specific meaning, make it a # new key in the modifiers attribute. diff --git a/openerp/report/custom.py b/openerp/report/custom.py index 9cf8fce6ced..4cc3a92cf0a 100644 --- a/openerp/report/custom.py +++ b/openerp/report/custom.py @@ -6,7 +6,7 @@ import time import openerp import openerp.tools as tools -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval import print_xml import render from interface import report_int @@ -52,8 +52,8 @@ class report_custom(report_int): for cond in conditions: if cond and cond[0]: c = cond[0] - temp = c[0](eval('obj.'+c[1],{'obj': obj})) - if not eval('\''+temp+'\''+' '+c[2]+' '+'\''+str(c[3])+'\''): + temp = c[0](safe_eval('obj.'+c[1],{'obj': obj})) + if not safe_eval('\''+temp+'\''+' '+c[2]+' '+'\''+str(c[3])+'\''): tobreak = True if tobreak: break @@ -66,7 +66,7 @@ class report_custom(report_int): row_canvas[i]=False elif len(fields[i])==1: if obj: - row.append(str(eval('obj.'+fields[i][0],{'obj': obj}))) + row.append(str(safe_eval('obj.'+fields[i][0],{'obj': obj}))) else: row.append(None) else: @@ -86,7 +86,7 @@ class report_custom(report_int): else: key = levels.keys() for l in key: - objs = eval('obj.'+l,{'obj': obj}) + objs = safe_eval('obj.'+l,{'obj': obj}) if not isinstance(objs, (BaseModel, list)): objs = [objs] field_new = [] @@ -169,7 +169,7 @@ class report_custom(report_int): def build_tree(obj, level, depth): res = self._row_get(cr, uid,[obj], new_fields, new_cond) level.append(depth) - new_obj = eval('obj.'+report['field_parent'][1],{'obj': obj}) + new_obj = safe_eval('obj.'+report['field_parent'][1],{'obj': obj}) if not isinstance(new_obj, list) : new_obj = [new_obj] for o in new_obj: diff --git a/openerp/report/printscreen/ps_list.py b/openerp/report/printscreen/ps_list.py index b6d68f8f31c..b14f8f36766 100644 --- a/openerp/report/printscreen/ps_list.py +++ b/openerp/report/printscreen/ps_list.py @@ -4,7 +4,7 @@ import openerp from openerp.report.interface import report_int import openerp.tools as tools -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval from lxml import etree from openerp.report import render, report_sxw import locale @@ -25,7 +25,7 @@ class report_printscreen_list(report_int): result = [] for node in root_node: field_name = node.get('name') - if not eval(str(node.attrib.get('invisible',False)),{'context':self.context}): + if not safe_eval(str(node.attrib.get('invisible',False)),{'context':self.context}): if node.tag == 'field': if field_name in self.groupby: continue diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py index 011925bba8c..40925be549e 100644 --- a/openerp/report/render/rml2pdf/trml2pdf.py +++ b/openerp/report/render/rml2pdf/trml2pdf.py @@ -17,7 +17,7 @@ from lxml import etree import base64 from distutils.version import LooseVersion from reportlab.platypus.doctemplate import ActionFlowable -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval from reportlab.lib.units import inch,cm,mm from openerp.tools.misc import file_open from reportlab.pdfbase import pdfmetrics @@ -478,7 +478,7 @@ class _rml_canvas(object): if self.localcontext: res = utils._regex.findall(newtext) for key in res: - newtext = eval(key, {}, self.localcontext) or '' + newtext = safe_eval(key, {}, self.localcontext) or '' image_data = None if newtext: image_data = base64.decodestring(newtext) diff --git a/openerp/report/render/rml2pdf/utils.py b/openerp/report/render/rml2pdf/utils.py index e8179deeb1d..2250bb50026 100644 --- a/openerp/report/render/rml2pdf/utils.py +++ b/openerp/report/render/rml2pdf/utils.py @@ -9,7 +9,7 @@ import re import reportlab import openerp.tools as tools -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval from openerp.tools.misc import ustr _logger = logging.getLogger(__name__) @@ -26,12 +26,12 @@ def _child_get(node, self=None, tagname=None): for n in node: if self and self.localcontext and n.get('rml_loop'): - for ctx in eval(n.get('rml_loop'),{}, self.localcontext): + for ctx in safe_eval(n.get('rml_loop'),{}, self.localcontext): self.localcontext.update(ctx) if (tagname is None) or (n.tag==tagname): if n.get('rml_except', False): try: - eval(n.get('rml_except'), {}, self.localcontext) + safe_eval(n.get('rml_except'), {}, self.localcontext) except GeneratorExit: continue except Exception, e: @@ -39,7 +39,7 @@ def _child_get(node, self=None, tagname=None): continue if n.get('rml_tag'): try: - (tag,attr) = eval(n.get('rml_tag'),{}, self.localcontext) + (tag,attr) = safe_eval(n.get('rml_tag'),{}, self.localcontext) n2 = copy.deepcopy(n) n2.tag = tag n2.attrib.update(attr) @@ -54,7 +54,7 @@ def _child_get(node, self=None, tagname=None): continue if self and self.localcontext and n.get('rml_except'): try: - eval(n.get('rml_except'), {}, self.localcontext) + safe_eval(n.get('rml_except'), {}, self.localcontext) except GeneratorExit: continue except Exception, e: @@ -62,7 +62,7 @@ def _child_get(node, self=None, tagname=None): continue if self and self.localcontext and n.get('rml_tag'): try: - (tag,attr) = eval(n.get('rml_tag'),{}, self.localcontext) + (tag,attr) = safe_eval(n.get('rml_tag'),{}, self.localcontext) n2 = copy.deepcopy(n) n2.tag = tag n2.attrib.update(attr or {}) @@ -99,7 +99,7 @@ def _process_text(self, txt): txt = None try: expr = sps.pop(0) - txt = eval(expr, self.localcontext) + txt = safe_eval(expr, self.localcontext) if txt and isinstance(txt, basestring): txt = tools.ustr(txt) except Exception: diff --git a/openerp/report/render/rml2txt/utils.py b/openerp/report/render/rml2txt/utils.py index f00302fb838..79f8927ea03 100644 --- a/openerp/report/render/rml2txt/utils.py +++ b/openerp/report/render/rml2txt/utils.py @@ -5,7 +5,7 @@ import copy import re import reportlab import reportlab.lib.units -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval _regex = re.compile('\[\[(.+?)\]\]') @@ -13,17 +13,17 @@ def _child_get(node, self=None, tagname=None): for n in node: if self and self.localcontext and n.get('rml_loop', False): oldctx = self.localcontext - for ctx in eval(n.get('rml_loop'),{}, self.localcontext): + for ctx in safe_eval(n.get('rml_loop'),{}, self.localcontext): self.localcontext.update(ctx) if (tagname is None) or (n.tag==tagname): if n.get('rml_except', False): try: - eval(n.get('rml_except'), {}, self.localcontext) + safe_eval(n.get('rml_except'), {}, self.localcontext) except Exception: continue if n.get('rml_tag'): try: - (tag,attr) = eval(n.get('rml_tag'),{}, self.localcontext) + (tag,attr) = safe_eval(n.get('rml_tag'),{}, self.localcontext) n2 = copy.copy(n) n2.tag = tag n2.attrib.update(attr) @@ -36,7 +36,7 @@ def _child_get(node, self=None, tagname=None): continue if self and self.localcontext and n.get('rml_except', False): try: - eval(n.get('rml_except'), {}, self.localcontext) + safe_eval(n.get('rml_except'), {}, self.localcontext) except Exception: continue if (tagname is None) or (n.tag==tagname): @@ -54,7 +54,7 @@ def _process_text(self, txt): result += self.localcontext.get('translate', lambda x:x)(sps.pop(0)) if sps: try: - txt2 = eval(sps.pop(0),self.localcontext) + txt2 = safe_eval(sps.pop(0),self.localcontext) except Exception: txt2 = '' if isinstance(txt2, (int, float)): diff --git a/openerp/report/report_sxw.py b/openerp/report/report_sxw.py index 5ccb8f74185..0dbefe704f3 100644 --- a/openerp/report/report_sxw.py +++ b/openerp/report/report_sxw.py @@ -21,7 +21,7 @@ from openerp import SUPERUSER_ID from openerp.osv.fields import float as float_field, function as function_field, datetime as datetime_field from openerp.tools.translate import _ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -391,7 +391,7 @@ class report_sxw(report_rml, preprocess.report): objs = self.getObjects(cr, uid, ids, context) results = [] for obj in objs: - aname = eval(attach, {'object':obj, 'time':time}) + aname = safe_eval(attach, {'object':obj, 'time':time}) result = False if report_xml.attachment_use and aname and context.get('attachment_use', True): aids = registry['ir.attachment'].search(cr, uid, [('datas_fname','=',aname+'.pdf'),('res_model','=',self.table),('res_id','=',obj.id)]) diff --git a/openerp/tools/convert.py b/openerp/tools/convert.py index 3c687003cb3..14a69be63fa 100644 --- a/openerp/tools/convert.py +++ b/openerp/tools/convert.py @@ -30,7 +30,7 @@ _logger = logging.getLogger(__name__) # almost everywhere, which is ok because it supposedly comes # from trusted data, but at least we make it obvious now. unsafe_eval = eval -from .safe_eval import safe_eval as eval +from .safe_eval import safe_eval class ParseError(Exception): def __init__(self, msg, text, filename, lineno): @@ -293,14 +293,14 @@ form: module.record_id""" % (xml_id,) if rec.get(field): res[dest] = rec.get(field).encode('utf8') if rec.get('auto'): - res['auto'] = eval(rec.get('auto','False')) + res['auto'] = safe_eval(rec.get('auto','False')) if rec.get('sxw'): sxw_content = file_open(rec.get('sxw')).read() res['report_sxw_content'] = sxw_content if rec.get('header'): - res['header'] = eval(rec.get('header','False')) + res['header'] = safe_eval(rec.get('header','False')) - res['multi'] = rec.get('multi') and eval(rec.get('multi','False')) + res['multi'] = rec.get('multi') and safe_eval(rec.get('multi','False')) xml_id = rec.get('id','').encode('utf8') self._test_xml_id(xml_id) @@ -324,12 +324,12 @@ form: module.record_id""" % (xml_id,) id = self.env['ir.model.data']._update("ir.actions.report.xml", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode) self.idref[xml_id] = int(id) - if not rec.get('menu') or eval(rec.get('menu','False')): + if not rec.get('menu') or safe_eval(rec.get('menu','False')): keyword = str(rec.get('keyword', 'client_print_multi')) value = 'ir.actions.report.xml,'+str(id) action = self.env['ir.values'].set_action(res['name'], keyword, res['model'], value) self.env['ir.actions.report.xml'].browse(id).write({'ir_values_id': action.id}) - elif self.mode=='update' and eval(rec.get('menu','False'))==False: + elif self.mode=='update' and safe_eval(rec.get('menu','False'))==False: # Special check for report having attribute menu=False on update value = 'ir.actions.report.xml,'+str(id) self._remove_ir_values(res['name'], value, res['model']) @@ -435,7 +435,7 @@ form: module.record_id""" % (xml_id,) if rec.get('target'): res['target'] = rec.get('target','') if rec.get('multi'): - res['multi'] = eval(rec.get('multi', 'False')) + res['multi'] = safe_eval(rec.get('multi', 'False')) id = self.env['ir.model.data']._update('ir.actions.act_window', self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode) self.idref[xml_id] = int(id) diff --git a/openerp/tools/yaml_import.py b/openerp/tools/yaml_import.py index b78fde496a6..5cc08bce5c3 100644 --- a/openerp/tools/yaml_import.py +++ b/openerp/tools/yaml_import.py @@ -21,7 +21,7 @@ from openerp import SUPERUSER_ID # YAML import needs both safe and unsafe eval, but let's # default to /safe/. unsafe_eval = eval -from .safe_eval import safe_eval as eval +from .safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -173,7 +173,7 @@ class YamlInterpreter(object): def get_context(self, node, eval_dict): context = self.context.copy() if node.context: - context.update(eval(node.context, eval_dict)) + context.update(safe_eval(node.context, eval_dict)) return context def isnoupdate(self, node): @@ -199,7 +199,7 @@ class YamlInterpreter(object): if assertion.id: ids = [self.get_id(assertion.id)] elif assertion.search: - q = eval(assertion.search, self.eval_context) + q = safe_eval(assertion.search, self.eval_context) ids = self.env(context=assertion.context)[assertion.model].search(q) else: raise YamlImportException('Nothing to assert: you must give either an id or a search criteria.') @@ -465,9 +465,9 @@ class YamlInterpreter(object): form_view = get_2many_view(fg, field_name, 'form') ctx['field_parent'] = fg[field_name]['relation_field'] if default and field_elem.get('context'): - ctx.update(eval(field_elem.get('context'), - globals_dict={'parent': dotdict(parent)}, - locals_dict=record_dict)) + ctx.update(safe_eval(field_elem.get('context'), + globals_dict={'parent': dotdict(parent)}, + locals_dict=record_dict)) field_value = self._eval_field(model, field_name, fields[field_name], form_view, parent=record_dict, default=default, context=ctx) record_dict.update(process_vals(fg, {field_name: field_value})) @@ -513,7 +513,7 @@ class YamlInterpreter(object): else: raise YamlImportException('You need to give a model for the search, or a field to infer it.') model = self.env[model_name] - q = eval(node.search, self.eval_context) + q = safe_eval(node.search, self.eval_context) instances = model.search(q) if node.use: value = [inst[node.use] for inst in instances] @@ -530,7 +530,7 @@ class YamlInterpreter(object): return value def process_eval(self, node): - return eval(node.expression, self.eval_context) + return safe_eval(node.expression, self.eval_context) def _eval_field(self, model, field_name, expression, view_info=False, parent={}, default=True, context=None): # TODO this should be refactored as something like model.get_field() in bin/osv @@ -634,7 +634,7 @@ class YamlInterpreter(object): value_model = self.env[value['model']] local_context = {'obj': value_model.browse} local_context.update(self.id_map) - id = eval(value['eval'], self.eval_context, local_context) + id = safe_eval(value['eval'], self.eval_context, local_context) if workflow.uid is not None: uid = workflow.uid @@ -659,13 +659,13 @@ class YamlInterpreter(object): elif isinstance(param, types.DictionaryType): # supports XML syntax param_model = self.env[param.get('model', model)] if 'search' in param: - q = eval(param['search'], self.eval_context) + q = safe_eval(param['search'], self.eval_context) ids = param_model.search(q).ids value = self._get_first_result(ids) elif 'eval' in param: local_context = {'obj': param_model.browse} local_context.update(self.id_map) - value = eval(param['eval'], self.eval_context, local_context) + value = safe_eval(param['eval'], self.eval_context, local_context) else: raise YamlImportException('You must provide either a !ref or at least a "eval" or a "search" to function parameter #%d.' % i) else: @@ -744,7 +744,7 @@ class YamlInterpreter(object): view_id = self.get_id(node.view) if not node.context: node.context={} - context = eval(str(node.context), self.eval_context) + context = safe_eval(str(node.context), self.eval_context) values = { 'name': node.name, 'type': node.type or 'ir.actions.act_window', @@ -781,7 +781,7 @@ class YamlInterpreter(object): assert getattr(node, 'model'), "Attribute %s of delete tag is empty !" % ('model',) if node.model in self.env: if node.search: - records = self.env[node.model].search(eval(node.search, self.eval_context)) + records = self.env[node.model].search(safe_eval(node.search, self.eval_context)) else: records = self.env[node.model].browse(self.get_id(node.id)) if records: @@ -797,7 +797,7 @@ class YamlInterpreter(object): id = self.sudo_env['ir.model.data']._update("ir.actions.act_url", self.module, res, node.id, mode=self.mode) self.id_map[node.id] = int(id) # ir_set - if (not node.menu or eval(node.menu)) and id: + if (not node.menu or safe_eval(node.menu)) and id: keyword = node.keyword or 'client_action_multi' value = 'ir.actions.act_url,%s' % id self.env['ir.values'].sudo().set_action(node.url, action_slot=keyword, model="ir.actions.act_url", action=value, res_id=False) @@ -809,7 +809,7 @@ class YamlInterpreter(object): res = {} for fieldname, expression in fields.items(): if is_eval(expression): - value = eval(expression.expression, self.eval_context) + value = safe_eval(expression.expression, self.eval_context) else: value = expression res[fieldname] = value @@ -832,7 +832,7 @@ class YamlInterpreter(object): if getattr(node, field): values[dest] = getattr(node, field) if node.auto: - values['auto'] = eval(node.auto) + values['auto'] = safe_eval(node.auto) if node.sxw: sxw_file = file_open(node.sxw) try: @@ -841,8 +841,8 @@ class YamlInterpreter(object): finally: sxw_file.close() if node.header: - values['header'] = eval(node.header) - values['multi'] = node.multi and eval(node.multi) + values['header'] = safe_eval(node.header) + values['multi'] = node.multi and safe_eval(node.multi) xml_id = node.id self.validate_xml_id(xml_id) @@ -852,7 +852,7 @@ class YamlInterpreter(object): self.module, values, xml_id, noupdate=self.isnoupdate(node), mode=self.mode) self.id_map[xml_id] = int(id) - if not node.menu or eval(node.menu): + if not node.menu or safe_eval(node.menu): keyword = node.keyword or 'client_print_multi' value = 'ir.actions.report.xml,%s' % id ir_values = self.env['ir.values'] diff --git a/openerp/workflow/workitem.py b/openerp/workflow/workitem.py index 0de16c8aaa3..a2f20195f9b 100644 --- a/openerp/workflow/workitem.py +++ b/openerp/workflow/workitem.py @@ -15,7 +15,7 @@ from openerp.workflow.helpers import WorkflowActivity logger = logging.getLogger(__name__) import openerp -from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.safe_eval import safe_eval class Environment(dict): """ @@ -270,7 +270,7 @@ class WorkflowItem(object): result = False else: env = Environment(self.session, self.record) - result = eval(line, env, nocopy=True) + result = safe_eval(line, env, nocopy=True) return result def wkf_expr_execute_action(self, activity):