[FIX] *: cache consistency

In module mail, invalidating 'message_ids' on a mail thread also
invalidates its inverse field 'res_id' on messages.  If you haven't
flushed it before, your cache will be inconsistent, as shown by the test
/mail:TestMailgateway.test_message_process_bounce_records_channel.

In module purchase_stock, add depends on report.stock.quantity.  This
ensures that when the model is queried after changes in other models,
the data on which the SQL view depends is flushed to the database before
querying that model's table.

closes odoo/odoo#66938

Related: odoo/enterprise#16722
Signed-off-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Vincent Schippefilt <vsc@odoo.com>
This commit is contained in:
Raphael Collet
2022-07-05 11:35:01 +02:00
co-authored by Vincent Schippefilt
parent 9c3b9a4926
commit eb67feb590
26 changed files with 105 additions and 74 deletions
+3 -3
View File
@@ -61,7 +61,7 @@ class TestAccountAccount(AccountTestInvoicingCommon):
# Set the account as reconcile and fully reconcile something.
account.reconcile = True
self.env['account.move.line'].invalidate_model()
self.env.invalidate_all()
self.assertRecordValues(move.line_ids, [
{'reconciled': False, 'amount_residual': 100.0, 'amount_residual_currency': 200.0},
@@ -77,7 +77,7 @@ class TestAccountAccount(AccountTestInvoicingCommon):
# Set back to a not reconcile account and check the journal items.
move.line_ids.remove_move_reconcile()
account.reconcile = False
self.env['account.move.line'].invalidate_model()
self.env.invalidate_all()
self.assertRecordValues(move.line_ids, [
{'reconciled': False, 'amount_residual': 0.0, 'amount_residual_currency': 0.0},
@@ -119,7 +119,7 @@ class TestAccountAccount(AccountTestInvoicingCommon):
# Set the account as reconcile and partially reconcile something.
account.reconcile = True
self.env['account.move.line'].invalidate_model()
self.env.invalidate_all()
move.line_ids.filtered(lambda line: line.account_id == account).reconcile()
@@ -15,6 +15,10 @@ class AlarmManager(models.AbstractModel):
_description = 'Event Alarm Manager'
def _get_next_potential_limit_alarm(self, alarm_type, seconds=None, partners=None):
# flush models before making queries
for model_name in ('calendar.alarm', 'calendar.event', 'calendar.recurrence'):
self.env[model_name].flush_model()
result = {}
delta_request = """
SELECT
+1
View File
@@ -161,6 +161,7 @@ class TestCalendar(SavepointCaseWithUserDemo):
'stop_date': "2018-10-18",
'allday': True,
})
self.env.invalidate_all()
self.assertEqual(str(event.start), '2018-10-16 08:00:00')
self.assertEqual(str(event.stop), '2018-10-18 18:00:00')
+7
View File
@@ -191,6 +191,9 @@ class TestCRMPLS(TransactionCase):
# rebuild frequencies table and recompute automated_probability for all leads.
Lead._cron_update_automated_probabilities()
# As the cron is computing and writing in SQL queries, we need to invalidate the cache
self.env.invalidate_all()
self.assertEqual(tools.float_compare(leads[3].automated_probability, 33.49, 2), 0)
self.assertEqual(tools.float_compare(leads[8].automated_probability, 7.74, 2), 0)
lead_13_team_3_proba = leads[13].automated_probability
@@ -403,6 +406,7 @@ class TestCRMPLS(TransactionCase):
# Force recompute - A priori, no need to do this as, for each won / lost, we increment tag frequency.
Lead._cron_update_automated_probabilities()
self.env.invalidate_all()
lead_tag_1 = leads_with_tags[30]
lead_tag_2 = leads_with_tags[90]
@@ -440,6 +444,7 @@ class TestCRMPLS(TransactionCase):
leads.filtered(lambda lead: lead.id % 2 == 0).email_state = 'correct'
leads.filtered(lambda lead: lead.id % 2 == 1).email_state = 'incorrect'
Lead._cron_update_automated_probabilities()
self.env.invalidate_all()
self.assertEqual(tools.float_compare(leads[3].automated_probability, 4.21, 2), 0)
self.assertEqual(tools.float_compare(leads[8].automated_probability, 0.23, 2), 0)
@@ -447,6 +452,7 @@ class TestCRMPLS(TransactionCase):
# remove all pls fields
self.env['ir.config_parameter'].sudo().set_param("crm.pls_fields", False)
Lead._cron_update_automated_probabilities()
self.env.invalidate_all()
self.assertEqual(tools.float_compare(leads[3].automated_probability, 34.38, 2), 0)
self.assertEqual(tools.float_compare(leads[8].automated_probability, 50.0, 2), 0)
@@ -454,6 +460,7 @@ class TestCRMPLS(TransactionCase):
# check if the probabilities are the same with the old param
self.env['ir.config_parameter'].sudo().set_param("crm.pls_fields", "country_id,state_id,email_state,phone_state,source_id")
Lead._cron_update_automated_probabilities()
self.env.invalidate_all()
self.assertEqual(tools.float_compare(leads[3].automated_probability, 4.21, 2), 0)
self.assertEqual(tools.float_compare(leads[8].automated_probability, 0.23, 2), 0)
+1 -1
View File
@@ -45,10 +45,10 @@ class TestDeliveryCost(common.TransactionCase):
# as the tests hereunder assume all the prices in USD, we must ensure
# that the company actually uses USD
# We do an invalidation so the cache is aware of it too.
self.env.company.invalidate_recordset()
self.env.cr.execute(
"UPDATE res_company SET currency_id = %s WHERE id = %s",
[self.env.ref('base.USD').id, self.env.company.id])
self.env.company.invalidate_recordset()
self.pricelist.currency_id = self.env.ref('base.USD').id
def test_00_delivery_cost(self):
+9 -4
View File
@@ -181,10 +181,15 @@ class HrEmployeePrivate(models.Model):
if self.check_access_rights('read', raise_exception=False):
return super(HrEmployeePrivate, self)._read(fields)
res = self.env['hr.employee.public'].browse(self.ids).read(fields)
for r in res:
record = self.browse(r['id'])
record._update_cache({k:v for k,v in r.items() if k in fields}, validate=False)
# HACK: retrieve publicly available values from hr.employee.public and
# copy them to the cache of self; non-public data will be missing from
# cache, and interpreted as an access error
self.flush_recordset(fields)
public = self.env['hr.employee.public'].browse(self._ids)
public._read(fields)
for fname in fields:
values = self.env.cache.get_values(public, public._fields[fname])
self.env.cache.update(self, self._fields[fname], values)
@api.model
def _cron_check_work_permit_validity(self):
@@ -158,17 +158,16 @@ class TestWorkEntryLeave(TestWorkEntryHolidaysBase):
'date_to': datetime(2022, 3, 25, 20),
'number_of_days': 4,
})
can_cancel_field = leave._fields['can_cancel']
leave.with_user(SUPERUSER_ID).action_validate()
# No work entries exist yet
self.assertTrue(leave.can_cancel, "The leave should still be cancellable")
# can not create in the future
self.richard_emp.contract_ids._generate_work_entries(datetime(2022, 3, 21, 6), datetime(2022, 3, 25, 20))
work_entries = self.env['hr.work.entry'].search([('employee_id', '=', self.richard_emp.id)])
self.env.cache.invalidate([(can_cancel_field, leave.ids)])
leave.invalidate_recordset(['can_cancel'])
# Work entries exist but are not locked yet
self.assertTrue(leave.can_cancel, "The leave should still be cancellable")
work_entries.action_validate()
self.env.cache.invalidate([(can_cancel_field, leave.ids)])
leave.invalidate_recordset(['can_cancel'])
# Work entries locked
self.assertFalse(leave.can_cancel, "The leave should not be cancellable")
+15 -10
View File
@@ -89,13 +89,18 @@ class TestEGEdiCommon(AccountEdiTestCommon):
@classmethod
def create_invoice(cls, **kwargs):
return (cls.env['account.move']
.with_context(edi_test_mode=True)
.create({
'move_type': 'out_invoice',
'partner_id': cls.partner_a.id,
'invoice_date': '2022-03-15',
'date': '2022-03-15',
**kwargs,
'invoice_line_ids': [Command.create({**line_vals, }) for line_vals in kwargs.get('invoice_line_ids', [])]
}))
invoice = (
cls.env['account.move']
.with_context(edi_test_mode=True)
.create({
'move_type': 'out_invoice',
'partner_id': cls.partner_a.id,
'invoice_date': '2022-03-15',
'date': '2022-03-15',
**kwargs,
'invoice_line_ids': [Command.create({**line_vals, }) for line_vals in kwargs.get('invoice_line_ids', [])]
})
)
# this fixes rounding issues in cache
cls.env.invalidate_all()
return invoice
+1
View File
@@ -1093,6 +1093,7 @@ class Message(models.Model):
def _invalidate_documents(self, model=None, res_id=None):
""" Invalidate the cache of the documents followed by ``self``. """
fnames = ['message_ids', 'message_needaction', 'message_needaction_counter']
self.flush_recordset(['model', 'res_id'])
for record in self:
model = model or record.model
res_id = res_id or record.res_id
@@ -357,7 +357,7 @@ class TestSubcontractingFlows(TestMrpSubcontractingCommon):
'parent_id': main_partner_2.id,
'company_id': self.env.ref('base.main_company').id,
})
self.env.cache.invalidate()
self.env.invalidate_all()
# We create a different BoM for the same product
comp3 = self.env['product.product'].create({
@@ -33,6 +33,9 @@ class TestProjectReport(TestProjectCommon):
self.assertEqual(task_3.rating_avg, 0)
self.assertEqual(task_3.rating_last_value, 0)
# fix cache consistency
self.env['project.task'].invalidate_model(['rating_avg', 'rating_last_value'])
tasks = [self.task_1, self.task_2, task_3]
for task in tasks:
rating_values = task.read(['rating_avg', 'rating_last_value'])[0]
+1
View File
@@ -638,6 +638,7 @@ class PurchaseOrder(models.Model):
# Invoice_ids may be filtered depending on the user. To ensure we get all
# invoices related to the purchase order, we read them in sudo to fill the
# cache.
self.invalidate_model(['invoice_ids'])
self.sudo()._read(['invoice_ids'])
invoices = self.invoice_ids
@@ -602,7 +602,7 @@ class TestReorderingRule(TransactionCase):
"route_ids": [],
}
)
self.env.cache.invalidate()
self.env.invalidate_all()
self.env["procurement.group"].run([procurement])
@@ -707,10 +707,11 @@ class TestReorderingRule(TransactionCase):
{'qty_forecast': -1, 'qty_to_order': 1},
])
delivery.scheduled_date += td(days=7)
# invalidate the fields that will eventually be inconsistent
orderpoint.invalidate_model(fnames=['qty_forecast', 'qty_to_order'])
orderpoint.product_id.invalidate_model(fnames=['virtual_available'])
delivery.scheduled_date += td(days=7)
self.assertRecordValues(orderpoint, [
{'qty_forecast': 0, 'qty_to_order': 0},
])
+2 -4
View File
@@ -176,6 +176,7 @@ class TestSaleOrder(TestSaleCommon):
# upsell and invoice
self.sol_serv_order.write({'product_uom_qty': 10})
# There is a bug with `new` and `_origin`
# If you create a first new from a record, then change a value on the origin record, than create another new,
# this other new wont have the updated value of the origin record, but the one from the previous new
@@ -184,10 +185,7 @@ class TestSaleOrder(TestSaleCommon):
# Here, we update `qty_delivered` on the origin record, but the `new` records which are in cache with this order line
# as origin are not updated, nor the fields that depends on it.
self.env.flush_all()
for field in self.env['sale.order.line']._fields.values():
for res_id in list(self.env.cache._data[field]):
if not res_id:
self.env.cache._data[field].pop(res_id)
self.env.invalidate_all()
invoice3 = self.sale_order._create_invoices()
self.assertEqual(len(invoice3.invoice_line_ids), 1, 'Sale: third invoice is missing lines')
@@ -269,8 +269,6 @@ class TestProgramRules(TestSaleCouponCommon):
})
]})
# Invalidate total_order_count
field_order_count = self.env['loyalty.program']._fields['order_count']
field_total_order_count = self.env['loyalty.program']._fields['total_order_count']
self.env.cache.invalidate([(field_order_count, self.immediate_promotion_program.ids), (field_total_order_count, self.immediate_promotion_program.ids)])
self.immediate_promotion_program.invalidate_recordset(['order_count', 'total_order_count'])
self._auto_rewards(order, self.immediate_promotion_program)
self.assertEqual(len(order.order_line.ids), 2, "The promo offer shouldn't have been applied as the number of uses is exceeded")
+3 -4
View File
@@ -93,6 +93,7 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
self.assertEqual(del_qties, del_qties_truth, 'Sale Stock: delivered quantities are wrong after complete delivery')
# Without timesheet, we manually set the delivered qty for the product serv_del
self.so.order_line.sorted()[1]['qty_delivered'] = 2.0
# There is a bug with `new` and `_origin`
# If you create a first new from a record, then change a value on the origin record, than create another new,
# this other new wont have the updated value of the origin record, but the one from the previous new
@@ -101,10 +102,8 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
# Here, we update `qty_delivered` on the origin record, but the `new` records which are in cache with this order line
# as origin are not updated, nor the fields that depends on it.
self.env.flush_all()
for field in self.env['sale.order.line']._fields.values():
for res_id in list(self.env.cache._data[field]):
if not res_id:
self.env.cache._data[field].pop(res_id)
self.env.invalidate_all()
inv_id = self.so._create_invoices()
self.assertEqual(self.so.invoice_status, 'invoiced',
'Sale Stock: so invoice_status should be "fully invoiced" after complete delivery and invoicing')
@@ -9,6 +9,15 @@ class ReportStockQuantity(models.Model):
_auto = False
_description = 'Stock Quantity Report'
_depends = {
'product.product': ['product_tmpl_id'],
'product.template': ['type'],
'stock.location': ['parent_path'],
'stock.move': ['company_id', 'date', 'location_dest_id', 'location_id', 'product_id', 'product_qty', 'state'],
'stock.quant': ['company_id', 'location_id', 'product_id', 'quantity'],
'stock.warehouse': ['view_location_id'],
}
date = fields.Date(string='Date', readonly=True)
product_tmpl_id = fields.Many2one('product.template', readonly=True)
product_id = fields.Many2one('product.product', string='Product', readonly=True)
+1 -1
View File
@@ -774,7 +774,7 @@ class TestCowViewSaving(TestViewSavingCommon):
'arch': '<div position="replace"><p>COMPARE</p></div>',
'key': '_website_sale_comparison.product_add_to_compare',
})])
Website.with_context(load_all_views=True).viewref('_website_sale_comparison.product_add_to_compare').invalidate_model()
View.invalidate_model()
# Simulate end of installation/update
View._create_all_specific_views(['_website_sale_comparison'])
+7 -5
View File
@@ -1346,11 +1346,13 @@ class IrModelSelection(models.Model):
if selection.value == vals['value']:
continue
if selection.field_id.store:
# in order to keep the cache consistent, flush the
# corresponding field, and invalidate it from cache
model = self.env[selection.field_id.model]
fname = selection.field_id.name
model.invalidate_model([fname])
# replace the value by the new one in the field's corresponding column
query = 'UPDATE "{table}" SET "{field}"=%s WHERE "{field}"=%s'.format(
table=self.env[selection.field_id.model]._table,
field=selection.field_id.name,
)
query = f'UPDATE "{model._table}" SET "{fname}"=%s WHERE "{fname}"=%s'
self.env.cr.execute(query, [vals['value'], selection.value])
result = super().write(vals)
@@ -1655,6 +1657,7 @@ class IrModelRelation(models.Model):
""" Reflect the table of a many2many field for the given model, to make
it possible to delete it later when the module is uninstalled.
"""
self.env.invalidate_all()
cr = self._cr
query = """ SELECT 1 FROM ir_model_relation r, ir_module_module m
WHERE r.module=m.id AND r.name=%s AND m.name=%s """
@@ -1669,7 +1672,6 @@ class IrModelRelation(models.Model):
(SELECT id FROM ir_module_module WHERE name=%s),
(SELECT id FROM ir_model WHERE model=%s)) """
cr.execute(query, (table, self.env.uid, self.env.uid, module, model._name))
self.env.invalidate_all()
class IrModelAccess(models.Model):
+1 -2
View File
@@ -233,8 +233,7 @@ class IrRule(models.Model):
failing_rules += "\n\n" + _('Note: this might be a multi-company issue.')
# clean up the cache of records prefetched with display_name above
for record in records[:6]:
record._cache.clear()
records_sudo.invalidate_recordset()
msg = f"{operation_error}\n\n{failing_records}\n{failing_user}\n\n{failing_rules}\n\n{resolution_info}"
return AccessError(msg)
@@ -112,7 +112,8 @@ class MergePartnerAutomatic(models.TransientModel):
Partner = self.env['res.partner']
relations = self._get_fk_on('res_partner')
self.env.flush_all()
# this guarantees cache consistency
self.env.invalidate_all()
for table, column in relations:
if 'base_partner_merge_' in table: # ignore two tables
@@ -175,8 +176,6 @@ class MergePartnerAutomatic(models.TransientModel):
query = 'DELETE FROM "%(table)s" WHERE "%(column)s" IN %%s' % query_dic
self._cr.execute(query, (tuple(src_partners.ids),))
self.env.invalidate_all()
@api.model
def _update_reference_fields(self, src_partners, dst_partner):
""" Update all reference fields from the src_partner to dst_partner.
@@ -935,9 +935,8 @@ class Attachment(models.Model):
return
comodel = self.env[self.res_model]
if 'res_id' in fnames and 'attachment_ids' in comodel:
field = comodel._fields['attachment_ids']
record = comodel.browse(self.res_id)
self.env.cache.invalidate([(field, record._ids)])
record.invalidate_recordset(['attachment_ids'])
record.modified(['attachment_ids'])
return super(Attachment, self).modified(fnames, *args, **kwargs)
@@ -244,6 +244,7 @@ class TestFields(TransactionCaseWithUserDemo):
(0, 0, {'name': 'x_stuff_id', 'ttype': 'many2one', 'relation': 'ir.model'}),
],
})
self.env.invalidate_all()
# set 'x_stuff_id' refer to a model not loaded yet
self.cr.execute("""
UPDATE ir_model_fields
@@ -791,7 +792,6 @@ class TestFields(TransactionCaseWithUserDemo):
# switch to environment with user demo
records = records.with_user(self.user_demo)
records.env.cache.invalidate()
# check that records are not accessible
with self.assertRaises(AccessError):
@@ -1611,7 +1611,7 @@ class TestFields(TransactionCaseWithUserDemo):
""" test field access on new records vs real records. """
Model = self.env['test_new_api.category']
real_record = Model.create({'name': 'Foo'})
self.env.cache.invalidate()
self.env.invalidate_all()
new_origin = Model.new({'name': 'Bar'}, origin=real_record)
new_record = Model.new({'name': 'Baz'})
@@ -2080,6 +2080,7 @@ class TestFields(TransactionCaseWithUserDemo):
self.assertEqual(demo_discussion.messages, discussion.messages)
# See YTI FIXME
self.env.flush_all()
self.env.invalidate_all()
# add a message as user demo
@@ -2744,12 +2745,12 @@ class TestX2many(common.TransactionCase):
self.assertEqual(parent.with_context(active_test=False).active_children_ids, act_children)
# check read()
self.env.cache.invalidate()
self.env.invalidate_all()
self.assertEqual(parent.children_ids, act_children)
self.assertEqual(parent.all_children_ids, all_children)
self.assertEqual(parent.active_children_ids, act_children)
self.env.cache.invalidate()
self.env.invalidate_all()
self.assertEqual(parent.with_context(active_test=False).children_ids, all_children)
self.assertEqual(parent.with_context(active_test=False).all_children_ids, all_children)
self.assertEqual(parent.with_context(active_test=False).active_children_ids, act_children)
+20 -20
View File
@@ -49,7 +49,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
'author': USER.id,
'size': 0,
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = self.Message.onchange(values, 'discussion', field_onchange)
self.assertIn('name', result['value'])
self.assertEqual(result['value']['name'], "[%s] %s" % (discussion.name, USER.name))
@@ -62,7 +62,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
'author': USER.id,
'size': 0,
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = self.Message.onchange(values, 'body', field_onchange)
self.assertIn('size', result['value'])
self.assertEqual(result['value']['size'], len(BODY))
@@ -76,7 +76,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
'author': USER.id,
'size': 0,
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = self.Message.onchange(values, 'body', field_onchange)
self.assertNotIn('name', result['value'])
@@ -94,7 +94,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
'root_categ': False,
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = Category.onchange(values, 'parent', field_onchange).get('value', {})
self.assertIn('root_categ', result)
self.assertEqual(result['root_categ'], root.name_get()[0])
@@ -102,7 +102,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
values.update(result)
values['parent'] = False
self.env.cache.invalidate()
self.env.invalidate_all()
result = Category.onchange(values, 'parent', field_onchange).get('value', {})
self.assertIn('root_categ', result)
self.assertIs(result['root_categ'], False)
@@ -143,7 +143,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
}),
],
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = self.Discussion.onchange(values, 'name', field_onchange)
self.assertIn('messages', result['value'])
self.assertEqual(result['value']['messages'], [
@@ -214,7 +214,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
}),
],
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = self.Discussion.onchange(values, 'name', field_onchange)
self.assertIn('messages', result['value'])
self.assertItemsEqual(result['value']['messages'], [
@@ -263,7 +263,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
'lines': [Command.set([line1.id]),
Command.create({'name': False, 'partner': False, 'tags': [Command.clear()]})],
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = multi.onchange(values, 'partner', field_onchange)
self.assertEqual(result['value'], {
@@ -292,7 +292,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
'partner': False,
'tags': [Command.clear(), Command.create({'name': 'Tag'})]})],
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = multi.onchange(values, 'partner', field_onchange)
expected_value = {
'name': partner2.name,
@@ -313,13 +313,13 @@ class TestOnChange(SavepointCaseWithUserDemo):
self.assertEqual(result['value'], expected_value)
# ensure ID is not returned when asked and a many2many record is set to be created
self.env.cache.invalidate()
self.env.invalidate_all()
result = multi.onchange(values, 'partner', dict(field_onchange, **{'lines.tags.id': None}))
self.assertEqual(result['value'], expected_value)
# ensure inverse of one2many field is not returned
self.env.cache.invalidate()
self.env.invalidate_all()
result = multi.onchange(values, 'partner', dict(field_onchange, **{'lines.multi': None}))
self.assertEqual(result['value'], expected_value)
@@ -348,7 +348,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
'messages': [Command.link(msg.id) for msg in discussion.messages],
'participants': [Command.link(usr.id) for usr in discussion.participants],
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = discussion.onchange(values, 'moderator', field_onchange)
self.assertIn('participants', result['value'])
@@ -368,13 +368,13 @@ class TestOnChange(SavepointCaseWithUserDemo):
self.env['ir.default'].set('test_new_api.foo', 'value2', 666, condition='value1=42')
# setting 'value1' to 42 should trigger the change of 'value2'
self.env.cache.invalidate()
self.env.invalidate_all()
values = {'name': 'X', 'value1': 42, 'value2': False}
result = Foo.onchange(values, 'value1', field_onchange)
self.assertEqual(result['value'], {'value2': 666})
# setting 'value1' to 24 should not trigger the change of 'value2'
self.env.cache.invalidate()
self.env.invalidate_all()
values = {'name': 'X', 'value1': 24, 'value2': False}
result = Foo.onchange(values, 'value1', field_onchange)
self.assertEqual(result['value'], {})
@@ -442,7 +442,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
})
# check if server-side cache is working correctly
self.env.cache.invalidate()
self.env.invalidate_all()
self.assertIn(email, discussion.emails)
self.assertNotIn(email, discussion.important_emails)
email.important = True
@@ -451,7 +451,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
# check that when trigger an onchange, we don't reset important emails
# (force `invalidate` as but appear in onchange only when we get a cache
# miss)
self.env.cache.invalidate()
self.env.invalidate_all()
self.assertEqual(len(discussion.messages), 4)
values = {
'name': "Foo Bar",
@@ -462,7 +462,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
'important_messages': [Command.link(msg.id) for msg in discussion.important_messages],
'important_emails': [Command.link(eml.id) for eml in discussion.important_emails],
}
self.env.cache.invalidate()
self.env.invalidate_all()
result = discussion.onchange(values, 'name', field_onchange)
self.assertEqual(
@@ -494,13 +494,13 @@ class TestOnChange(SavepointCaseWithUserDemo):
'message_currency': self.env.user.name_get()[0],
}
self.env.cache.invalidate()
self.env.invalidate_all()
Message = self.env['test_new_api.related']
result = Message.onchange(value, 'message', field_onchange)
self.assertEqual(result['value'], onchange_result)
self.env.cache.invalidate()
self.env.invalidate_all()
Message = self.env(user=self.user_demo.id)['test_new_api.related']
result = Message.onchange(value, 'message', field_onchange)
@@ -530,7 +530,7 @@ class TestOnChange(SavepointCaseWithUserDemo):
# changing 'discussion' on message should not read 'messages' on discussion
with patch.object(type(discussion), 'read', mock_read, create=True):
self.env.cache.invalidate()
self.env.invalidate_all()
self.Message.onchange(values, 'discussion', field_onchange)
self.assertFalse(called[0], "discussion.messages has been read")
@@ -66,7 +66,7 @@ class TestTermCount(common.TransactionCase):
odoo.tools.trans_load(self.cr, 'test_translation_import/i18n/fr.po', 'fr_FR', verbose=False, overwrite=True)
# trans_load invalidates ormcache but not record cache
menu.env.cache.invalidate()
self.env.invalidate_all()
self.assertEqual(menu.name, "New Name")
self.assertEqual(menu.with_context(lang='fr_FR').name, "Nouveau nom")
+1 -1
View File
@@ -1734,7 +1734,7 @@ def users(*logins):
func(*args, **kwargs)
# Invalidate the cache between subtests, in order to not reuse
# the former user's cache (`test_read_mail`, `test_write_mail`)
self.env.cache.invalidate()
self.env.invalidate_all()
finally:
self.uid = old_uid