From 83fdf019a8657bbe6e0e84f66d01d18ac8319cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 7 Sep 2019 23:38:20 +0200 Subject: [PATCH] Prevent assign unknown attributes on Model by adding __slots__ on proteus classes. issue6573 review254081002 --- CHANGELOG | 2 ++ proteus/__init__.py | 16 +++++++++++++++- proteus/tests/test_model.py | 9 ++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0dc96dad1c..746287f4ff 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Add __slots__ + Version 5.2.0 - 2019-05-06 * Bug fixes (see mercurial logs for details) * Remove support for Python 3.4 diff --git a/proteus/__init__.py b/proteus/__init__.py index f18987aba3..fddac83e58 100644 --- a/proteus/__init__.py +++ b/proteus/__init__.py @@ -18,6 +18,8 @@ _MODELS = threading.local() class _EvalEnvironment(dict): 'Dictionary for evaluation' + __slots__ = ('parent', 'eval_type') + def __init__(self, parent, eval_type='eval'): super(_EvalEnvironment, self).__init__() self.parent = parent @@ -82,6 +84,8 @@ class dualmethod(object): >>> Example().method() 1 """ + __slots__ = ('func') + def __init__(self, func): self.func = func @@ -447,6 +451,8 @@ class MetaModelFactory(object): class MetaModel(type): 'Meta class for Model' + __slots__ = () + def __new__(mcs, name, bases, dict): if self.model_name in getattr(_MODELS, models_key): return getattr(_MODELS, models_key)[self.model_name] @@ -481,6 +487,9 @@ class MetaModelFactory(object): class ModelList(list): 'List for Model' + __slots__ = ('model_name', 'parent', 'parent_field_name', 'parent_name', + 'domain', 'context', 'add_remove', 'search_order', 'search_context', + 'record_removed', 'record_deleted') def __init__(self, definition, sequence=None, parent=None, parent_field_name=''): @@ -650,6 +659,7 @@ class ModelList(list): class Model(object): 'Model class for Tryton records' + __slots__ = ('__id', '_values', '_changed', '_group', '__context') __counter = -1 _proxy = None @@ -725,7 +735,7 @@ class Model(object): name = name.encode('utf-8') class Spam(Model, metaclass=MetaModelFactory(name, config=config)()): - pass + __slots__ = () return Spam @classmethod @@ -1132,6 +1142,9 @@ class Model(object): class Wizard(object): 'Wizard class for Tryton wizards' + __slots__ = ('name', 'form', 'form_state', 'actions', '_config', + '_context', '_proxy', 'session_id', 'start_state', 'end_state', + 'states', 'state', 'models', 'action') def __init__(self, name, models=None, action=None, config=None, context=None): @@ -1210,6 +1223,7 @@ class Wizard(object): class Report(object): 'Report class for Tryton reports' + __slots__ = ('name', '_config', '_context', '_proxy') def __init__(self, name, config=None, context=None): super(Report, self).__init__() diff --git a/proteus/tests/test_model.py b/proteus/tests/test_model.py index 03dac052c6..5151aa29d0 100644 --- a/proteus/tests/test_model.py +++ b/proteus/tests/test_model.py @@ -103,6 +103,14 @@ class TestModel(ProteusTestCase): self.assertEqual(len(User(groups=[x.id for x in groups]).groups), len(groups)) + def test_assign_unknown_field(self): + "Test it is not allowed to assign unknown field" + User = Model.get('res.user') + user = User() + + with self.assertRaises(AttributeError): + user.unknown_field = 'foo' + def test_save(self): User = Model.get('res.user') test = User() @@ -286,7 +294,6 @@ class TestModel(ProteusTestCase): Group = Model.get('res.group') test = Group() test.name = 'Test delete' - test.login = 'test delete' test.save() test.delete()