diff options
| author | Raphael Collet <rco@odoo.com> | 2020-04-07 13:51:30 +0000 |
|---|---|---|
| committer | Raphael Collet <rco@odoo.com> | 2020-05-18 09:51:43 +0000 |
| commit | ea3e39506a2b360545ec0cd1d3235e69ad16ea6c (patch) | |
| tree | 9d103c7a40911c988e1a3cbecfd8d6a76a3a9a85 /odoo | |
| parent | 2e56191c8b86d05bbce17790de8a4732c0478013 (diff) | |
[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>
Diffstat (limited to 'odoo')
| -rw-r--r-- | odoo/addons/base/models/qweb.py | 1 | ||||
| -rw-r--r-- | odoo/addons/base/models/res_config.py | 2 | ||||
| -rw-r--r-- | odoo/addons/test_new_api/tests/test_attributes.py | 19 | ||||
| -rw-r--r-- | odoo/models.py | 11 |
4 files changed, 15 insertions, 18 deletions
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 |
