[REM] base: remove _patch_method and _revert_method
There is only one legitimate usage of `_patch_method` (base_automation) and none of `_revert_method`. The other uses are in tests and they are all wrong: if the test crashes between the `_patch_method` and the `_revert_method`, the method will not be reverted. For the only proper usage of `_patch_method`, move the code to this place. Correct tests using `_patch_method`/`_revert_method` by calling the `patch` method of `BaseCase`. Also, remove the `api.returns` from the `create` method of `BaseModel` as it is useless and confusing. In fact, we never use it because we have a special treatment at the RPC level for the `create` method (see `_call_kw_model_create`). closes odoo/odoo#110370 Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
committed by
Raphael Collet
parent
01c2146d13
commit
5a870462e0
@@ -498,7 +498,9 @@ class BaseAutomation(models.Model):
|
||||
""" Patch method `name` on `model`, unless it has been patched already. """
|
||||
if model not in patched_models[name]:
|
||||
patched_models[name].add(model)
|
||||
model._patch_method(name, method)
|
||||
ModelClass = type(model)
|
||||
method.origin = getattr(ModelClass, name)
|
||||
setattr(ModelClass, name, method)
|
||||
|
||||
# retrieve all actions, and patch their corresponding model
|
||||
for action_rule in self.with_context({}).search([]):
|
||||
|
||||
@@ -833,7 +833,7 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
|
||||
def unlink(self):
|
||||
raise Exception('just')
|
||||
Product._patch_method('unlink', unlink)
|
||||
self.patch(type(Product), 'unlink', unlink)
|
||||
|
||||
variants_2x1 = self.template.product_variant_ids
|
||||
self._assert_2color_x_1size()
|
||||
@@ -855,8 +855,6 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
archived_variants = self._get_archived_variants()
|
||||
self.assertFalse(archived_variants)
|
||||
|
||||
Product._revert_method('unlink')
|
||||
|
||||
def test_02_update_variant_archive_2_value(self):
|
||||
"""We do the same operations on the template as in the previous tests,
|
||||
except we simulate that the variants can't be unlinked.
|
||||
@@ -868,7 +866,7 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
|
||||
def unlink(slef):
|
||||
raise Exception('just')
|
||||
Product._patch_method('unlink', unlink)
|
||||
self.patch(type(Product), 'unlink', unlink)
|
||||
|
||||
variants_2x2 = self.template.product_variant_ids
|
||||
self._assert_2color_x_2size()
|
||||
@@ -924,8 +922,6 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
self.assertEqual(archived_variants, variants_2x2)
|
||||
self._assert_2color_x_2size(archived_variants)
|
||||
|
||||
Product._revert_method('unlink')
|
||||
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_03_update_variant_archive_3_value(self):
|
||||
self._remove_ptal_size()
|
||||
@@ -935,7 +931,7 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
|
||||
def unlink(slef):
|
||||
raise Exception('just')
|
||||
Product._patch_method('unlink', unlink)
|
||||
self.patch(type(Product), 'unlink', unlink)
|
||||
|
||||
self._assert_2color_x_1size()
|
||||
archived_variants = self._get_archived_variants()
|
||||
@@ -983,14 +979,12 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
archived_variants = self._get_archived_variants()
|
||||
self.assertEqual(archived_variants, variants_2x1 + variant_0x0)
|
||||
|
||||
Product._revert_method('unlink')
|
||||
|
||||
def test_04_from_to_single_values(self):
|
||||
Product = self.env['product.product']
|
||||
|
||||
def unlink(slef):
|
||||
raise Exception('just')
|
||||
Product._patch_method('unlink', unlink)
|
||||
self.patch(type(Product), 'unlink', unlink)
|
||||
|
||||
# CASE: remove one value, line becoming single value
|
||||
variants_2x2 = self.template.product_variant_ids
|
||||
@@ -1027,8 +1021,6 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
self._assert_2color_x_0size(archived_variants)
|
||||
self.assertEqual(archived_variants, variants_2x0)
|
||||
|
||||
Product._revert_method('unlink')
|
||||
|
||||
def test_name_search_dynamic_attributes(self):
|
||||
dynamic_attr = self.env['product.attribute'].create({
|
||||
'name': 'Dynamic',
|
||||
@@ -1079,7 +1071,7 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
# Patch unlink method to force archiving instead deleting
|
||||
def unlink(self):
|
||||
self.active = False
|
||||
Product._patch_method('unlink', unlink)
|
||||
self.patch(type(Product), 'unlink', unlink)
|
||||
|
||||
# Creating attributes
|
||||
pa_color = ProductAttribute.create({'sequence': 1, 'name': 'color', 'create_variant': 'dynamic'})
|
||||
@@ -1184,8 +1176,6 @@ class TestVariantsArchive(ProductVariantsCommon):
|
||||
})
|
||||
self.assertTrue(product_white.active)
|
||||
|
||||
Product._revert_method('unlink')
|
||||
|
||||
def test_set_barcode(self):
|
||||
tmpl = self.product.product_tmpl_id
|
||||
tmpl.barcode = '123'
|
||||
|
||||
@@ -779,7 +779,8 @@ class TestMailMailRace(common.TransactionCase):
|
||||
# In practice, the update will wait the end of the send() transaction and set the notif as bounce, as expeced
|
||||
cr.execute("UPDATE mail_notification SET notification_status='bounce' WHERE id = %s", [notif.id])
|
||||
return message['Message-Id']
|
||||
self.env['ir.mail_server']._patch_method('send_email', send_email)
|
||||
|
||||
self.patch(self.registry['ir.mail_server'], 'send_email', send_email)
|
||||
|
||||
mail.send()
|
||||
|
||||
@@ -787,7 +788,6 @@ class TestMailMailRace(common.TransactionCase):
|
||||
self.assertEqual(notif.notification_status, 'sent')
|
||||
|
||||
# some cleaning since we commited the cr
|
||||
self.env['ir.mail_server']._revert_method('send_email')
|
||||
|
||||
notif.unlink()
|
||||
mail.unlink()
|
||||
|
||||
@@ -222,14 +222,14 @@ class TestTracking(TestMailCommon):
|
||||
if 'name' in init_values and init_values['name'] == magic_code:
|
||||
return 'mail.mt_name_changed'
|
||||
return False
|
||||
self.registry('mail.test.container')._patch_method('_track_subtype', _track_subtype)
|
||||
self.patch(self.registry('mail.test.container'), '_track_subtype', _track_subtype)
|
||||
|
||||
def _track_template(self, changes):
|
||||
res = {}
|
||||
if 'name' in changes:
|
||||
res['name'] = (mail_template, {'composition_mode': 'mass_mail'})
|
||||
return res
|
||||
self.registry('mail.test.container')._patch_method('_track_template', _track_template)
|
||||
self.patch(self.registry('mail.test.container'), '_track_template', _track_template)
|
||||
|
||||
cls = type(self.env['mail.test.container'])
|
||||
self.assertFalse(hasattr(getattr(cls, 'name'), 'track_visibility'))
|
||||
|
||||
@@ -3827,7 +3827,6 @@ class BaseModel(metaclass=MetaModel):
|
||||
parent_records._parent_store_update()
|
||||
|
||||
@api.model_create_multi
|
||||
@api.returns('self', lambda value: value.id)
|
||||
def create(self, vals_list):
|
||||
""" create(vals_list) -> records
|
||||
|
||||
@@ -5008,44 +5007,6 @@ class BaseModel(metaclass=MetaModel):
|
||||
def _unregister_hook(self):
|
||||
""" Clean up what `~._register_hook` has done. """
|
||||
|
||||
@classmethod
|
||||
def _patch_method(cls, name, method):
|
||||
""" Monkey-patch a method for all instances of this model. This replaces
|
||||
the method called ``name`` by ``method`` in the given class.
|
||||
The original method is then accessible via ``method.origin``, and it
|
||||
can be restored with :meth:`~._revert_method`.
|
||||
|
||||
Example::
|
||||
|
||||
def do_write(self, values):
|
||||
# do stuff, and call the original method
|
||||
return do_write.origin(self, values)
|
||||
|
||||
# patch method write of model
|
||||
model._patch_method('write', do_write)
|
||||
|
||||
# this will call do_write
|
||||
records = model.search([...])
|
||||
records.write(...)
|
||||
|
||||
# restore the original method
|
||||
model._revert_method('write')
|
||||
"""
|
||||
origin = getattr(cls, name)
|
||||
method.origin = origin
|
||||
# propagate decorators from origin to method, and apply api decorator
|
||||
wrapped = api.propagate(origin, method)
|
||||
wrapped.origin = origin
|
||||
setattr(cls, name, wrapped)
|
||||
|
||||
@classmethod
|
||||
def _revert_method(cls, name):
|
||||
""" Revert the original method called ``name`` in the given class.
|
||||
See :meth:`~._patch_method`.
|
||||
"""
|
||||
method = getattr(cls, name)
|
||||
setattr(cls, name, method.origin)
|
||||
|
||||
#
|
||||
# Instance creation
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user