diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index 461b40b33e8..7607712215e 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -1252,7 +1252,7 @@ class AccountBankStatementLine(models.Model): # Update the payment date to match the current bank statement line's date. if counterpart_line.payment_id: - counterpart_line.payment_id.payment_date = self.date + counterpart_line.payment_id.date = self.date # ------------------------------------------------------------------------- # BUSINESS METHODS diff --git a/addons/account/tests/test_account_bank_statement.py b/addons/account/tests/test_account_bank_statement.py index 6cca0200e57..3af6a02fa0f 100644 --- a/addons/account/tests/test_account_bank_statement.py +++ b/addons/account/tests/test_account_bank_statement.py @@ -1249,15 +1249,15 @@ class TestAccountBankStatement(TestAccountBankStatementCommon): test_line_1 = test_move.line_ids.filtered(lambda line: line.name == 'test line 1') test_line_2 = test_move.line_ids.filtered(lambda line: line.name == 'test line 2') - def _prepare_reconciliation_with_payments(lines_vals_list): - statement_line_wo_patch = self.env['account.bank.statement.line'].browse(self.statement_line.id) - return statement_line_wo_patch._prepare_reconciliation(lines_vals_list, create_payment_for_invoice=True) + statement_line = self.statement_line + StatementLine_prepare_reconciliation = type(statement_line)._prepare_reconciliation - with patch.object( - self.statement_line, - '_prepare_reconciliation', - lambda *args, **kwargs: _prepare_reconciliation_with_payments(*args) - ): + def _prepare_reconciliation(self, lines_vals_list, create_payment_for_invoice=False): + if self == statement_line: + create_payment_for_invoice = True + return StatementLine_prepare_reconciliation(self, lines_vals_list, create_payment_for_invoice) + + with patch.object(type(statement_line), '_prepare_reconciliation', _prepare_reconciliation): self.statement_line.reconcile([ {'id': test_line_1.id, 'balance': -50.0}, {'id': test_line_2.id}, diff --git a/addons/hr_holidays/report/holidays_summary_report.py b/addons/hr_holidays/report/holidays_summary_report.py index 5047cde9742..74d41d195c1 100644 --- a/addons/hr_holidays/report/holidays_summary_report.py +++ b/addons/hr_holidays/report/holidays_summary_report.py @@ -76,29 +76,27 @@ class HrHolidaySummaryReport(models.AbstractModel): res[(date_from-start_date).days]['color'] = holiday.holiday_status_id.color_name date_from += timedelta(1) count += holiday.number_of_days - self.sum = count - return res + employee = self.env['hr.employee'].browse(empid) + return {'emp': employee.name, 'display': res, 'sum': count} def _get_data_from_report(self, data): res = [] Employee = self.env['hr.employee'] if 'depts' in data: for department in self.env['hr.department'].browse(data['depts']): - res.append({'dept' : department.name, 'data': [], 'color': self._get_day(data['date_from'])}) - for emp in Employee.search([('department_id', '=', department.id)]): - res[len(res)-1]['data'].append({ - 'emp': emp.name, - 'display': self._get_leaves_summary(data['date_from'], emp.id, data['holiday_type']), - 'sum': self.sum - }) - elif 'emp' in data: - res.append({'data':[]}) - for emp in Employee.browse(data['emp']): - res[0]['data'].append({ - 'emp': emp.name, - 'display': self._get_leaves_summary(data['date_from'], emp.id, data['holiday_type']), - 'sum': self.sum + res.append({ + 'dept': department.name, + 'data': [ + self._get_leaves_summary(data['date_from'], emp.id, data['holiday_type']) + for emp in Employee.search([('department_id', '=', department.id)]) + ], + 'color': self._get_day(data['date_from']), }) + elif 'emp' in data: + res.append({'data': [ + self._get_leaves_summary(data['date_from'], emp.id, data['holiday_type']) + for emp in Employee.browse(data['emp']) + ]}) return res def _get_holidays_status(self): diff --git a/addons/l10n_be_edi/tests/test_ubl.py b/addons/l10n_be_edi/tests/test_ubl.py index 2680b7bca52..cbbf385b459 100644 --- a/addons/l10n_be_edi/tests/test_ubl.py +++ b/addons/l10n_be_edi/tests/test_ubl.py @@ -9,7 +9,7 @@ class TestUBL(common.TransactionCase): super(TestUBL, self).setUp() # Force user Belgium country. self.env.user.company_id = self.env['res.company'].create({'name': 'MyCompany'}) - self.env.user.company_id.country = self.env.ref('base.be') + self.env.user.company_id.country_id = self.env.ref('base.be') self.env.ref('l10n_be.l10nbe_chart_template').try_loading() self.partner_id = self.env['res.partner'].create({'name': 'TestUser', 'vat': 'BE0123456789'}) diff --git a/addons/mrp/tests/test_workorder_operation.py b/addons/mrp/tests/test_workorder_operation.py index c1125633bf1..de8b40ae1b4 100644 --- a/addons/mrp/tests/test_workorder_operation.py +++ b/addons/mrp/tests/test_workorder_operation.py @@ -1264,20 +1264,6 @@ class TestWorkOrderProcess(TestWorkOrderProcessCommon): production sooner """ self.workcenter_1.alternative_workcenter_ids = self.wc_alt_1 | self.wc_alt_2 self.env['mrp.workcenter'].search([]).write({'tz': 'UTC'}) # compute all date in UTC - mrp_routing_0 = self.env['mrp.routing'].create({ - 'name': 'Primary Assembly', - }) - mrp_workcenter_3 = self.env['mrp.workcenter'].create({ - 'name': 'Assembly Line 1', - 'resource_calendar_id': self.env.ref('resource.resource_calendar_std').id, - }) - mrp_routing_workcenter_0 = self.env['mrp.routing.workcenter'].create({ - 'routing_id': mrp_routing_0.id, - 'workcenter_id': mrp_workcenter_3.id, - 'name': 'Manual Assembly', - 'time_cycle': 60, - }) - self.planning_bom.routing = mrp_routing_0 mo_form = Form(self.env['mrp.production']) mo_form.product_id = self.product_4 mo_form.bom_id = self.planning_bom diff --git a/addons/payment/wizards/payment_acquirer_onboarding_wizard.py b/addons/payment/wizards/payment_acquirer_onboarding_wizard.py index 40e66bd78c7..5f925e1b47a 100644 --- a/addons/payment/wizards/payment_acquirer_onboarding_wizard.py +++ b/addons/payment/wizards/payment_acquirer_onboarding_wizard.py @@ -31,13 +31,14 @@ class PaymentWizard(models.TransientModel): acc_number = fields.Char("Account Number", default=lambda self: self._get_default_payment_acquirer_onboarding_value('acc_number')) manual_post_msg = fields.Html("Payment Instructions") + _data_fetched = fields.Boolean(store=False) + @api.onchange('journal_name', 'acc_number') def _set_manual_post_msg_value(self): self.manual_post_msg = _('

Please make a payment to:

') %\ (self.journal_name or _("Bank") , self.acc_number or _("Account"), self.env.company.name) _payment_acquirer_onboarding_cache = {} - _data_fetched = False def _get_manual_payment_acquirer(self, env=None): if env is None: diff --git a/addons/point_of_sale/tests/test_anglo_saxon.py b/addons/point_of_sale/tests/test_anglo_saxon.py index d6cf96843ea..aed16559189 100644 --- a/addons/point_of_sale/tests/test_anglo_saxon.py +++ b/addons/point_of_sale/tests/test_anglo_saxon.py @@ -51,7 +51,6 @@ class TestAngloSaxonCommon(common.TransactionCase): self.cash_journal = self.env['account.journal'].create({'name': 'CASH journal', 'type': 'cash', 'code': 'CSH00'}) self.sale_journal = self.env['account.journal'].create({'name': 'SALE journal', 'type': 'sale', 'code': 'INV00'}) self.pos_config.invoice_journal_id = self.sale_journal - self.pos_config.journal_ids = [self.cash_journal.id] self.cash_payment_method = self.env['pos.payment.method'].create({ 'name': 'Cash Test', 'is_cash_count': True, diff --git a/addons/purchase_stock/tests/test_stockvaluation.py b/addons/purchase_stock/tests/test_stockvaluation.py index 4107b7f9418..7f710ac5a33 100644 --- a/addons/purchase_stock/tests/test_stockvaluation.py +++ b/addons/purchase_stock/tests/test_stockvaluation.py @@ -494,8 +494,7 @@ class TestStockValuationWithCOA(AccountTestCommon): }) self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' - self.product1.product_tmpl_id.categ_id.valuation = 'real_time' - + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' # Receive 10@10 ; create the vendor bill po1 = self.env['purchase.order'].create({ diff --git a/addons/stock/tests/test_robustness.py b/addons/stock/tests/test_robustness.py index b53cb44ea7b..ef039188a32 100644 --- a/addons/stock/tests/test_robustness.py +++ b/addons/stock/tests/test_robustness.py @@ -140,9 +140,9 @@ class TestRobustness(SavepointCase): move1._action_confirm() move1._action_assign() - move1.result_package_id = False - + self.assertEqual(move1.move_line_ids.package_id, package) package.unpack() + self.assertEqual(move1.move_line_ids.package_id, self.env['stock.quant.package']) # unreserve move1._do_unreserve() diff --git a/addons/stock_account/tests/test_stockvaluationlayer.py b/addons/stock_account/tests/test_stockvaluationlayer.py index cd9098c0384..451bd2528e4 100644 --- a/addons/stock_account/tests/test_stockvaluationlayer.py +++ b/addons/stock_account/tests/test_stockvaluationlayer.py @@ -108,7 +108,7 @@ class TestStockValuationCommon(SavepointCase): 'picking_type_id': self.picking_type_out.id, }) if unit_cost: - dropshipped.unit_cost = unit_cost + dropshipped.price_unit = unit_cost dropshipped._action_confirm() dropshipped._action_assign() dropshipped.move_line_ids.qty_done = quantity diff --git a/addons/stock_dropshipping/tests/test_stockvaluation.py b/addons/stock_dropshipping/tests/test_stockvaluation.py index 6292cf7b88f..f6988a3b783 100644 --- a/addons/stock_dropshipping/tests/test_stockvaluation.py +++ b/addons/stock_dropshipping/tests/test_stockvaluation.py @@ -183,7 +183,7 @@ class TestStockValuation(StockAccountTestCommon): def test_dropship_fifo_perpetual_continental_ordered(self): self.env.company.anglo_saxon_accounting = False - self.product1.product_tmpl_id.categ_id.proprty_cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' self.product1.product_tmpl_id.standard_price = 10 self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'order' diff --git a/addons/stock_landed_costs/models/stock_landed_cost.py b/addons/stock_landed_costs/models/stock_landed_cost.py index 0b8c3287aca..66f5a6e9a45 100644 --- a/addons/stock_landed_costs/models/stock_landed_cost.py +++ b/addons/stock_landed_costs/models/stock_landed_cost.py @@ -334,8 +334,6 @@ class StockLandedCostLine(models.Model): @api.onchange('product_id') def onchange_product_id(self): - if not self.product_id: - self.quantity = 0.0 self.name = self.product_id.name or '' self.split_method = self.product_id.product_tmpl_id.split_method_landed_cost or self.split_method or 'equal' self.price_unit = self.product_id.standard_price or 0.0 diff --git a/addons/test_mail/tests/test_mail_activity.py b/addons/test_mail/tests/test_mail_activity.py index b75a9b960cc..8e35b3066f5 100644 --- a/addons/test_mail/tests/test_mail_activity.py +++ b/addons/test_mail/tests/test_mail_activity.py @@ -181,9 +181,6 @@ class TestActivityFlow(TestActivityCommon): 'datas': 'testtest', }) - # Adding the attachments to the activity - activity.attachment_ids = attachments - # Checking if the attachment has been forwarded to the message # when marking an activity as "Done" activity.action_feedback() diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py index 8fa24631d26..4b6cd55551b 100644 --- a/addons/website/models/ir_ui_view.py +++ b/addons/website/models/ir_ui_view.py @@ -405,10 +405,6 @@ class View(models.Model): func = getattr(values['main_object'], 'get_backend_menu_id', False) values['backend_menu_id'] = func and func() or self.env.ref('website.menu_website_configuration').id - # Fallback incase main_object dont't inherit 'website.seo.metadata' - if not hasattr(values['main_object'], 'get_website_meta'): - values['main_object'].get_website_meta = lambda: {} - if self._context != new_context: self = self.with_context(new_context) return super(View, self)._render(values, engine=engine, minimal_qcontext=minimal_qcontext) diff --git a/addons/website/models/website.py b/addons/website/models/website.py index e079d6f12d2..41565fb031a 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -1011,3 +1011,8 @@ class BaseModel(models.AbstractModel): return self.website_id._get_http_domain() else: return super(BaseModel, self).get_base_url() + + def get_website_meta(self): + # dummy version of 'get_website_meta' above; this is a graceful fallback + # for models that don't inherit from 'website.seo.metadata' + return {} diff --git a/odoo/addons/base/models/qweb.py b/odoo/addons/base/models/qweb.py index 464cb7a166e..6a099e810bc 100644 --- a/odoo/addons/base/models/qweb.py +++ b/odoo/addons/base/models/qweb.py @@ -234,6 +234,7 @@ class frozendict(dict): class QWeb(object): + __slots__ = () _void_elements = frozenset([ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', diff --git a/odoo/addons/base/models/res_config.py b/odoo/addons/base/models/res_config.py index a03a70a2ec6..1cba371e188 100644 --- a/odoo/addons/base/models/res_config.py +++ b/odoo/addons/base/models/res_config.py @@ -14,6 +14,8 @@ _logger = logging.getLogger(__name__) class ResConfigModuleInstallationMixin(object): + __slots__ = () + @api.model def _install_modules(self, modules): """ Install the requested modules. diff --git a/odoo/addons/test_new_api/tests/test_attributes.py b/odoo/addons/test_new_api/tests/test_attributes.py index 94a048f2554..27853d9a16e 100644 --- a/odoo/addons/test_new_api/tests/test_attributes.py +++ b/odoo/addons/test_new_api/tests/test_attributes.py @@ -1,25 +1,12 @@ # -*- coding: utf-8 -*- from odoo.tests import common -ANSWER_TO_ULTIMATE_QUESTION = 42 class TestAttributes(common.TransactionCase): - def test_we_can_add_attributes(self): + def test_we_cannot_add_attributes(self): Model = self.env['test_new_api.category'] instance = Model.create({'name': 'Foo'}) - # assign an unknown attribute - instance.unknown = ANSWER_TO_ULTIMATE_QUESTION - - # Does the attribute exist in the instance of the model ? - self.assertTrue(hasattr(instance, 'unknown')) - - # Is it the right type ? - self.assertIsInstance(instance.unknown, int) - - # Is it the right value, in case of, we don't know ;-) - self.assertEqual(instance.unknown, ANSWER_TO_ULTIMATE_QUESTION) - - # We are paranoiac ! - self.assertEqual(getattr(instance, 'unknown'), ANSWER_TO_ULTIMATE_QUESTION) + with self.assertRaises(AttributeError): + instance.unknown = 42 diff --git a/odoo/models.py b/odoo/models.py index 43f477fb1c2..15758441afa 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -53,7 +53,7 @@ from . import api from . import tools from .exceptions import AccessError, MissingError, ValidationError, UserError from .osv.query import Query -from .tools import frozendict, lazy_classproperty, lazy_property, ormcache, \ +from .tools import frozendict, lazy_classproperty, ormcache, \ Collector, LastOrderedSet, OrderedSet, IterableGenerator, \ groupby, unique from .tools.config import config @@ -151,6 +151,10 @@ class MetaModel(api.Meta): module_to_models = defaultdict(list) + def __new__(meta, name, bases, attrs): + attrs.setdefault('__slots__', ()) + return super().__new__(meta, name, bases, attrs) + def __init__(self, name, bases, attrs): if not self._register: self._register = True @@ -253,6 +257,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): To create a class that should not be instantiated, the :attr:`~odoo.models.BaseModel._register` attribute may be set to False. """ + __slots__ = ['env', '_ids', '_prefetch_ids'] _auto = False """Whether a database table should be created (default: ``True``). @@ -5607,7 +5612,7 @@ Record ids: %(records)s # Cache and recomputation management # - @lazy_property + @property def _cache(self): """ Return the cache of ``self``, mapping field names to values. """ return RecordCache(self) @@ -6226,6 +6231,8 @@ collections.Sequence.register(BaseModel) class RecordCache(MutableMapping): """ A mapping from field names to values, to read and update the cache of a record. """ + __slots__ = ['_record'] + def __init__(self, record): assert len(record) == 1, "Unexpected RecordCache(%s)" % record self._record = record