[IMP] models: use slots for BaseModel

This restricts the attributes of a BaseModel instance to `env`, `_ids`
and `_prefetch_ids`.  This way, one can only assign fields on a record;
other assignments are programming errors.

This also reduces the memory footprint of records from 168 to 64 bytes
(-62%), and makes their instanciation faster.

closes odoo/odoo#51075

Related: odoo/enterprise#10529
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
Raphael Collet
2020-05-18 09:51:43 +00:00
parent 2e56191c8b
commit ea3e39506a
19 changed files with 51 additions and 75 deletions
@@ -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
@@ -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},
@@ -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):
+1 -1
View File
@@ -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'})
@@ -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
@@ -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 = _('<h3>Please make a payment to: </h3><ul><li>Bank: %s</li><li>Account Number: %s</li><li>Account Holder: %s</li></ul>') %\
(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:
@@ -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,
@@ -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({
+2 -2
View File
@@ -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()
@@ -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
@@ -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'
@@ -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
@@ -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()
-4
View File
@@ -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)
+5
View File
@@ -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 {}