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:
- Bank: %s
- Account Number: %s
- Account Holder: %s
') %\
(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