diff --git a/component/__init__.py b/component/__init__.py index afa4a2929..70fab2841 100644 --- a/component/__init__.py +++ b/component/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from . import core from . import components diff --git a/component/__manifest__.py b/component/__manifest__.py index 18d7ba29d..1a772646d 100644 --- a/component/__manifest__.py +++ b/component/__manifest__.py @@ -1,22 +1,18 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) -{'name': 'Components', - 'summary': 'Add capabilities to register and use decoupled components,' - ' as an alternative to model classes', - 'version': '13.0.1.0.0', - 'author': 'Camptocamp,' - 'Odoo Community Association (OCA)', - 'website': 'https://github.com/OCA/connector', - 'license': 'LGPL-3', - 'category': 'Generic Modules', - 'depends': ['base', - ], - 'external_dependencies': { - 'python': ['cachetools'], - }, - 'installable': False, - 'development_status': 'Stable', - 'maintainers': ['guewen'], - } +{ + "name": "Components", + "summary": "Add capabilities to register and use decoupled components," + " as an alternative to model classes", + "version": "13.0.1.0.0", + "author": "Camptocamp," "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/connector", + "license": "LGPL-3", + "category": "Generic Modules", + "depends": ["base"], + "external_dependencies": {"python": ["cachetools"]}, + "installable": False, + "development_status": "Stable", + "maintainers": ["guewen"], +} diff --git a/component/builder.py b/component/builder.py index fbfca06e2..d0f0399a6 100644 --- a/component/builder.py +++ b/component/builder.py @@ -11,11 +11,8 @@ """ import odoo from odoo import models -from .core import ( - _component_databases, - ComponentRegistry, - DEFAULT_CACHE_SIZE, -) + +from .core import DEFAULT_CACHE_SIZE, ComponentRegistry, _component_databases class ComponentBuilder(models.AbstractModel): @@ -37,8 +34,9 @@ class ComponentBuilder(models.AbstractModel): order. """ - _name = 'component.builder' - _description = 'Component Builder' + + _name = "component.builder" + _description = "Component Builder" _components_registry_cache_size = DEFAULT_CACHE_SIZE @@ -58,34 +56,27 @@ def _init_global_registry(self): _component_databases[self.env.cr.dbname] = components_registry return components_registry - def build_registry(self, components_registry, states=None, - exclude_addons=None): + def build_registry(self, components_registry, states=None, exclude_addons=None): if not states: - states = ('installed', 'to upgrade') + states = ("installed", "to upgrade") # lookup all the installed (or about to be) addons and generate # the graph, so we can load the components following the order # of the addons' dependencies graph = odoo.modules.graph.Graph() - graph.add_module(self.env.cr, 'base') + graph.add_module(self.env.cr, "base") - query = ( - "SELECT name " - "FROM ir_module_module " - "WHERE state IN %s " - ) + query = "SELECT name " "FROM ir_module_module " "WHERE state IN %s " params = [tuple(states)] if exclude_addons: query += " AND name NOT IN %s " params.append(tuple(exclude_addons)) self.env.cr.execute(query, params) - module_list = [name for (name,) in self.env.cr.fetchall() - if name not in graph] + module_list = [name for (name,) in self.env.cr.fetchall() if name not in graph] graph.add_modules(self.env.cr, module_list) for module in graph: - self.load_components(module.name, - components_registry=components_registry) + self.load_components(module.name, components_registry=components_registry) def load_components(self, module, components_registry=None): """ Build every component known by MetaComponent for an odoo module @@ -100,6 +91,6 @@ def load_components(self, module, components_registry=None): :type registry: :py:class:`~.core.ComponentRegistry` """ components_registry = ( - components_registry or - _component_databases[self.env.cr.dbname]) + components_registry or _component_databases[self.env.cr.dbname] + ) components_registry.load_components(module) diff --git a/component/components/__init__.py b/component/components/__init__.py index a61d43eb9..0e4444933 100644 --- a/component/components/__init__.py +++ b/component/components/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- from . import base diff --git a/component/components/base.py b/component/components/base.py index 5a66e57b9..7c4a63328 100644 --- a/component/components/base.py +++ b/component/components/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) @@ -12,4 +11,5 @@ class BaseComponent(AbstractComponent): All your base are belong to us """ - _name = 'base' + + _name = "base" diff --git a/component/core.py b/component/core.py index 6424a16cc..d84febe8c 100644 --- a/component/core.py +++ b/component/core.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # Copyright 2017 Odoo # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) @@ -19,13 +18,12 @@ import logging import operator - -from collections import defaultdict, OrderedDict +from collections import OrderedDict, defaultdict from odoo import models -from odoo.tools import OrderedSet, LastOrderedSet -from .exception import NoComponentError, SeveralComponentError +from odoo.tools import LastOrderedSet, OrderedSet +from .exception import NoComponentError, SeveralComponentError _logger = logging.getLogger(__name__) @@ -50,11 +48,11 @@ def _get_addon_name(full_name): # or not. For instance, module ``sale`` can be imported as # ``odoo.addons.sale`` (the right way) or ``sale`` (for backward # compatibility). - module_parts = full_name.split('.') - if len(module_parts) > 2 and module_parts[:2] == ['odoo', 'addons']: - addon_name = full_name.split('.')[2] + module_parts = full_name.split(".") + if len(module_parts) > 2 and module_parts[:2] == ["odoo", "addons"]: + addon_name = full_name.split(".")[2] else: - addon_name = full_name.split('.')[0] + addon_name = full_name.split(".")[0] return addon_name @@ -103,7 +101,7 @@ def load_components(self, module): component_class._build_component(self) self._loaded_modules.add(module) - @cachedmethod(operator.attrgetter('_cache')) + @cachedmethod(operator.attrgetter("_cache")) def lookup(self, collection_name=None, usage=None, model_name=None): """ Find and return a list of components for a usage @@ -136,25 +134,32 @@ def lookup(self, collection_name=None, usage=None, model_name=None): # keep the order so addons loaded first have components used first candidates = ( - component for component in self._components.values() + component + for component in self._components.values() if not component._abstract ) if collection_name is not None: candidates = ( - component for component in candidates - if (component._collection == collection_name or - component._collection is None) + component + for component in candidates + if ( + component._collection == collection_name + or component._collection is None + ) ) if usage is not None: - candidates = (component for component in candidates - if component._usage == usage) + candidates = ( + component for component in candidates if component._usage == usage + ) if model_name is not None: - candidates = (c for c in candidates - if c.apply_on_models is None or - model_name in c.apply_on_models) + candidates = ( + c + for c in candidates + if c.apply_on_models is None or model_name in c.apply_on_models + ) return list(candidates) @@ -234,8 +239,9 @@ class WorkContext(object): """ - def __init__(self, model_name=None, collection=None, - components_registry=None, **kwargs): + def __init__( + self, model_name=None, collection=None, components_registry=None, **kwargs + ): self.collection = collection self.model_name = model_name self.model = self.env[model_name] @@ -248,16 +254,13 @@ def __init__(self, model_name=None, collection=None, self.components_registry = _component_databases[dbname] except KeyError: _logger.error( - 'No component registry for database %s. ' - 'Probably because the Odoo registry has not been built ' - 'yet.', dbname + "No component registry for database %s. " + "Probably because the Odoo registry has not been built " + "yet.", + dbname, ) raise - self._propagate_kwargs = [ - 'collection', - 'model_name', - 'components_registry', - ] + self._propagate_kwargs = ["collection", "model_name", "components_registry"] for attr_name, value in kwargs.items(): setattr(self, attr_name, value) self._propagate_kwargs.append(attr_name) @@ -275,12 +278,13 @@ def work_on(self, model_name=None, collection=None): Used when one need to lookup components for another model. """ - kwargs = {attr_name: getattr(self, attr_name) - for attr_name in self._propagate_kwargs} + kwargs = { + attr_name: getattr(self, attr_name) for attr_name in self._propagate_kwargs + } if collection is not None: - kwargs['collection'] = collection + kwargs["collection"] = collection if model_name is not None: - kwargs['model_name'] = model_name + kwargs["model_name"] = model_name return self.__class__(**kwargs) def _component_class_by_name(self, name): @@ -312,26 +316,29 @@ def component_by_name(self, name, model_name=None): model_name = model_name._name component_class = self._component_class_by_name(name) work_model = model_name or self.model_name - if (component_class._collection and - self.collection._name != component_class._collection): + if ( + component_class._collection + and self.collection._name != component_class._collection + ): raise NoComponentError( - "Component with name '%s' can't be used for collection '%s'." - (name, self.collection._name) + "Component with name '%s' can't be used for collection '%s'."( + name, self.collection._name + ) ) - if (component_class.apply_on_models and - work_model not in component_class.apply_on_models): + if ( + component_class.apply_on_models + and work_model not in component_class.apply_on_models + ): if len(component_class.apply_on_models) == 1: - hint_models = "'%s'" % (component_class.apply_on_models[0],) + hint_models = "'{}'".format(component_class.apply_on_models[0]) else: - hint_models = "" % ( - component_class.apply_on_models, - ) + hint_models = "".format(component_class.apply_on_models) raise NoComponentError( "Component with name '%s' can't be used for model '%s'.\n" "Hint: you might want to use: " - "component_by_name('%s', model_name=%s)" % - (name, work_model, name, hint_models) + "component_by_name('%s', model_name=%s)" + % (name, work_model, name, hint_models) ) if work_model == self.model_name: @@ -342,9 +349,7 @@ def component_by_name(self, name, model_name=None): def _lookup_components(self, usage=None, model_name=None): component_classes = self.components_registry.lookup( - self.collection._name, - usage=usage, - model_name=model_name, + self.collection._name, usage=usage, model_name=model_name ) return [cls for cls in component_classes if cls._component_match(self)] @@ -375,33 +380,36 @@ def component(self, usage=None, model_name=None): if isinstance(model_name, models.BaseModel): model_name = model_name._name model_name = model_name or self.model_name - component_classes = self._lookup_components( - usage=usage, model_name=model_name - ) + component_classes = self._lookup_components(usage=usage, model_name=model_name) if not component_classes: raise NoComponentError( "No component found for collection '%s', " - "usage '%s', model_name '%s'." % - (self.collection._name, usage, model_name) + "usage '%s', model_name '%s'." + % (self.collection._name, usage, model_name) ) elif len(component_classes) > 1: # If we have more than one component, try to find the one # specifically linked to the collection... component_classes = [ - c for c in component_classes - if c._collection == self.collection._name] + c for c in component_classes if c._collection == self.collection._name + ] if len(component_classes) > 1: # ... or try to find the one specifically linked to the model component_classes = [ - c for c in component_classes + c + for c in component_classes if c.apply_on_models and model_name in c.apply_on_models ] if len(component_classes) != 1: raise SeveralComponentError( "Several components found for collection '%s', " - "usage '%s', model_name '%s'. Found: %r" % - (self.collection._name, usage or '', - model_name or '', component_classes) + "usage '%s', model_name '%s'. Found: %r" + % ( + self.collection._name, + usage or "", + model_name or "", + component_classes, + ) ) if model_name == self.model_name: work_context = self @@ -423,9 +431,7 @@ def many_components(self, usage=None, model_name=None): if isinstance(model_name, models.BaseModel): model_name = model_name._name model_name = model_name or self.model_name - component_classes = self._lookup_components( - usage=usage, model_name=model_name - ) + component_classes = self._lookup_components(usage=usage, model_name=model_name) if model_name == self.model_name: work_context = self else: @@ -433,7 +439,7 @@ def many_components(self, usage=None, model_name=None): return [comp(work_context) for comp in component_classes] def __str__(self): - return "WorkContext(%s, %s)" % (self.model_name, repr(self.collection)) + return "WorkContext({}, {})".format(self.model_name, repr(self.collection)) __repr__ = __str__ @@ -448,9 +454,9 @@ class MetaComponent(type): _modules_components = defaultdict(list) - def __init__(self, name, bases, attrs): - if not self._register: - self._register = True + def __init__(cls, name, bases, attrs): + if not cls._register: + cls._register = True super().__init__(name, bases, attrs) return @@ -462,23 +468,23 @@ def __init__(self, name, bases, attrs): # test creates a test components for the purpose of the test, then a # second tests uses the "load_components" to load all the addons of the # module: it will load the component of the previous test. - if 'tests' in self.__module__.split('.'): + if "tests" in cls.__module__.split("."): return - if not hasattr(self, '_module'): - self._module = _get_addon_name(self.__module__) + if not hasattr(cls, "_module"): + cls._module = _get_addon_name(cls.__module__) - self._modules_components[self._module].append(self) + cls._modules_components[cls._module].append(cls) @property - def apply_on_models(self): + def apply_on_models(cls): # None means all models - if self._apply_on is None: + if cls._apply_on is None: return None # always return a list, used for the lookup - elif isinstance(self._apply_on, str): - return [self._apply_on] - return self._apply_on + elif isinstance(cls._apply_on, str): + return [cls._apply_on] + return cls._apply_on class AbstractComponent(object, metaclass=MetaComponent): @@ -790,35 +796,39 @@ def _build_component(cls, registry): parents = [] if cls._name in registry and not parents: - raise TypeError('Component %r (in class %r) already exists. ' - 'Consider using _inherit instead of _name ' - 'or using a different _name.' % (cls._name, cls)) + raise TypeError( + "Component %r (in class %r) already exists. " + "Consider using _inherit instead of _name " + "or using a different _name." % (cls._name, cls) + ) # determine the component's name name = cls._name or (len(parents) == 1 and parents[0]) if not name: - raise TypeError('Component %r must have a _name' % cls) + raise TypeError("Component %r must have a _name" % cls) # all components except 'base' implicitly inherit from 'base' - if name != 'base': - parents = list(parents) + ['base'] + if name != "base": + parents = list(parents) + ["base"] # create or retrieve the component's class if name in parents: if name not in registry: - raise TypeError("Component %r does not exist in registry." % - name) + raise TypeError("Component %r does not exist in registry." % name) ComponentClass = registry[name] ComponentClass._build_component_check_base(cls) check_parent = ComponentClass._build_component_check_parent else: ComponentClass = type( - name, (AbstractComponent,), - {'_name': name, - '_register': False, - # names of children component - '_inherit_children': OrderedSet()}, + name, + (AbstractComponent,), + { + "_name": name, + "_register": False, + # names of children component + "_inherit_children": OrderedSet(), + }, ) check_parent = cls._build_component_check_parent @@ -827,8 +837,8 @@ def _build_component(cls, registry): for parent in parents: if parent not in registry: raise TypeError( - "Component %r inherits from non-existing component %r." % - (name, parent) + "Component %r inherits from non-existing component %r." + % (name, parent) ) parent_class = registry[parent] if parent == name: @@ -850,22 +860,24 @@ def _build_component(cls, registry): def _build_component_check_base(cls, extend_cls): """ Check whether ``cls`` can be extended with ``extend_cls``. """ if cls._abstract and not extend_cls._abstract: - msg = ("%s transforms the abstract component %r into a " - "non-abstract component. " - "That class should either inherit from AbstractComponent, " - "or set a different '_name'.") + msg = ( + "%s transforms the abstract component %r into a " + "non-abstract component. " + "That class should either inherit from AbstractComponent, " + "or set a different '_name'." + ) raise TypeError(msg % (extend_cls, cls._name)) @classmethod - def _build_component_check_parent(component_class, cls, parent_class): + def _build_component_check_parent(component_class, cls, parent_class): # noqa: B902 """ Check whether ``model_class`` can inherit from ``parent_class``. """ if component_class._abstract and not parent_class._abstract: - msg = ("In %s, the abstract Component %r cannot inherit " - "from the non-abstract Component %r.") - raise TypeError( - msg % (cls, component_class._name, parent_class._name) + msg = ( + "In %s, the abstract Component %r cannot inherit " + "from the non-abstract Component %r." ) + raise TypeError(msg % (cls, component_class._name, parent_class._name)) @classmethod def _complete_component_build(cls): @@ -888,5 +900,6 @@ class Component(AbstractComponent): Look in :class:`AbstractComponent` for more details. """ + _register = False _abstract = False diff --git a/component/exception.py b/component/exception.py index 8a5d9b3fb..f61add52c 100644 --- a/component/exception.py +++ b/component/exception.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) diff --git a/component/models/__init__.py b/component/models/__init__.py index 4343b4aec..97ad61232 100644 --- a/component/models/__init__.py +++ b/component/models/__init__.py @@ -1,3 +1 @@ -# -*- coding: utf-8 -*- - from . import collection diff --git a/component/models/collection.py b/component/models/collection.py index f0f544099..9b21fd1af 100644 --- a/component/models/collection.py +++ b/component/models/collection.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) @@ -17,6 +16,7 @@ from contextlib import contextmanager from odoo import models + from ..core import WorkContext @@ -55,8 +55,9 @@ def run(self, magento_id): """ - _name = 'collection.base' - _description = 'Base Abstract Collection' + + _name = "collection.base" + _description = "Base Abstract Collection" @contextmanager def work_on(self, model_name, **kwargs): diff --git a/component/readme/HISTORY.rst b/component/readme/HISTORY.rst index 59a390d20..f917c5b5f 100644 --- a/component/readme/HISTORY.rst +++ b/component/readme/HISTORY.rst @@ -2,7 +2,7 @@ understand changes between version. The primary audience is end users and integrators. Purely technical changes such as code refactoring must not be mentioned here. - + This file may contain ONE level of section titles, underlined with the ~ (tilde) character. Other section markers are forbidden and will likely break the structure of the README.rst diff --git a/component/readme/USAGE.rst b/component/readme/USAGE.rst index 371a2570b..2826a95e0 100644 --- a/component/readme/USAGE.rst +++ b/component/readme/USAGE.rst @@ -20,4 +20,3 @@ component level):: def run(self, external_id): backend_adapter = self.component(usage='backend.adapter') external_data = backend_adapter.read(external_id) - diff --git a/component/tests/__init__.py b/component/tests/__init__.py index ef6a6108b..de5a88a91 100644 --- a/component/tests/__init__.py +++ b/component/tests/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from . import test_build_component from . import test_component from . import test_lookup diff --git a/component/tests/common.py b/component/tests/common.py index 9d3fd0a6c..510237a0e 100644 --- a/component/tests/common.py +++ b/component/tests/common.py @@ -1,20 +1,15 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) import copy - +import unittest from contextlib import contextmanager -import unittest import odoo from odoo import api from odoo.tests import common -from odoo.addons.component.core import ( - ComponentRegistry, - MetaComponent, - _get_addon_name, -) + +from odoo.addons.component.core import ComponentRegistry, MetaComponent, _get_addon_name @contextmanager @@ -30,11 +25,10 @@ def new_rollbacked_env(): class ComponentMixin(object): - @classmethod def setUpComponent(cls): with new_rollbacked_env() as env: - builder = env['component.builder'] + builder = env["component.builder"] # build the components of every installed addons comp_registry = builder._init_global_registry() cls._components_registry = comp_registry @@ -42,11 +36,12 @@ def setUpComponent(cls): # modules, not 'to install', which means we load only the # dependencies of the tested addons, not the siblings or # chilren addons - builder.build_registry(comp_registry, states=('installed',)) + builder.build_registry(comp_registry, states=("installed",)) # build the components of the current tested addon current_addon = _get_addon_name(cls.__module__) - env['component.builder'].load_components(current_addon) + env["component.builder"].load_components(current_addon) + # pylint: disable=W8106 def setUp(self): # should be ready only during tests, never during installation # of addons @@ -71,6 +66,7 @@ def setUpClass(cls): super().setUpClass() cls.setUpComponent() + # pylint: disable=W8106 def setUp(self): # resolve an inheritance issue (common.TransactionCase does not call # super) @@ -92,6 +88,7 @@ def setUpClass(cls): super().setUpClass() cls.setUpComponent() + # pylint: disable=W8106 def setUp(self): # resolve an inheritance issue (common.SavepointCase does not call # super) @@ -100,7 +97,8 @@ def setUp(self): class ComponentRegistryCase( - unittest.TestCase, common.MetaCase('DummyCase', (object,), {})): + unittest.TestCase, common.MetaCase("DummyCase", (object,), {}) +): """ This test case can be used as a base for writings tests on components This test case is meant to test components in a special component registry, @@ -151,25 +149,23 @@ def setUp(self): # keep the original classes registered by the metaclass # so we'll restore them at the end of the tests, it avoid # to pollute it with Stub / Test components - self._original_components = copy.deepcopy( - MetaComponent._modules_components - ) + self._original_components = copy.deepcopy(MetaComponent._modules_components) # it will be our temporary component registry for our test session self.comp_registry = ComponentRegistry() # it builds the 'final component' for every component of the # 'component' addon and push them in the component registry - self.comp_registry.load_components('component') + self.comp_registry.load_components("component") # build the components of every installed addons already installed # but the current addon (when running with pytest/nosetest, we # simulate the --test-enable behavior by excluding the current addon # which is in 'to install' / 'to upgrade' with --test-enable). current_addon = _get_addon_name(self.__module__) with new_rollbacked_env() as env: - env['component.builder'].build_registry( + env["component.builder"].build_registry( self.comp_registry, - states=('installed',), + states=("installed",), exclude_addons=[current_addon], ) @@ -192,32 +188,32 @@ def _build_components(self, *classes): cls._build_component(self.comp_registry) -class TransactionComponentRegistryCase(common.TransactionCase, - ComponentRegistryCase): +class TransactionComponentRegistryCase(common.TransactionCase, ComponentRegistryCase): """ Adds Odoo Transaction in the base Component TestCase """ + # pylint: disable=W8106 def setUp(self): # resolve an inheritance issue (common.TransactionCase does not use # super) common.TransactionCase.setUp(self) ComponentRegistryCase.setUp(self) - self.collection = self.env['collection.base'] + self.collection = self.env["collection.base"] def teardown(self): common.TransactionCase.tearDown(self) ComponentRegistryCase.tearDown(self) -class SavepointComponentRegistryCase(common.SavepointCase, - ComponentRegistryCase): +class SavepointComponentRegistryCase(common.SavepointCase, ComponentRegistryCase): """ Adds Odoo Transaction with Savepoint in the base Component TestCase """ + # pylint: disable=W8106 def setUp(self): # resolve an inheritance issue (common.SavepointCase does not use # super) common.SavepointCase.setUp(self) ComponentRegistryCase.setUp(self) - self.collection = self.env['collection.base'] + self.collection = self.env["collection.base"] def teardown(self): common.SavepointCase.tearDown(self) diff --git a/component/tests/test_build_component.py b/component/tests/test_build_component.py index 71d5151b4..284513802 100644 --- a/component/tests/test_build_component.py +++ b/component/tests/test_build_component.py @@ -1,9 +1,10 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) import mock + from odoo.addons.component.core import AbstractComponent, Component + from .common import ComponentRegistryCase @@ -25,102 +26,98 @@ class TestBuildComponent(ComponentRegistryCase): def test_no_name(self): """ Ensure that a component has a _name """ + class Component1(Component): pass - msg = '.*must have a _name.*' + msg = ".*must have a _name.*" with self.assertRaisesRegex(TypeError, msg): Component1._build_component(self.comp_registry) def test_register(self): """ Able to register components in components registry """ + class Component1(Component): - _name = 'component1' + _name = "component1" class Component2(Component): - _name = 'component2' + _name = "component2" # build the 'final classes' for the components and check that we find # them in the components registry Component1._build_component(self.comp_registry) Component2._build_component(self.comp_registry) - self.assertEqual( - ['base', 'component1', 'component2'], - list(self.comp_registry) - ) + self.assertEqual(["base", "component1", "component2"], list(self.comp_registry)) def test_inherit_bases(self): """ Check __bases__ of Component with _inherit """ + class Component1(Component): - _name = 'component1' + _name = "component1" class Component2(Component): - _inherit = 'component1' + _inherit = "component1" class Component3(Component): - _inherit = 'component1' + _inherit = "component1" Component1._build_component(self.comp_registry) Component2._build_component(self.comp_registry) Component3._build_component(self.comp_registry) self.assertEqual( - (Component3, - Component2, - Component1, - self.comp_registry['base']), - self.comp_registry['component1'].__bases__ + (Component3, Component2, Component1, self.comp_registry["base"]), + self.comp_registry["component1"].__bases__, ) def test_prototype_inherit_bases(self): """ Check __bases__ of Component with _inherit and different _name """ + class Component1(Component): - _name = 'component1' + _name = "component1" class Component2(Component): - _name = 'component2' - _inherit = 'component1' + _name = "component2" + _inherit = "component1" class Component3(Component): - _name = 'component3' - _inherit = 'component1' + _name = "component3" + _inherit = "component1" class Component4(Component): - _name = 'component4' - _inherit = ['component2', 'component3'] + _name = "component4" + _inherit = ["component2", "component3"] Component1._build_component(self.comp_registry) Component2._build_component(self.comp_registry) Component3._build_component(self.comp_registry) Component4._build_component(self.comp_registry) self.assertEqual( - (Component1, - self.comp_registry['base']), - self.comp_registry['component1'].__bases__ + (Component1, self.comp_registry["base"]), + self.comp_registry["component1"].__bases__, ) self.assertEqual( - (Component2, - self.comp_registry['component1'], - self.comp_registry['base']), - self.comp_registry['component2'].__bases__ + (Component2, self.comp_registry["component1"], self.comp_registry["base"]), + self.comp_registry["component2"].__bases__, ) self.assertEqual( - (Component3, - self.comp_registry['component1'], - self.comp_registry['base']), - self.comp_registry['component3'].__bases__ + (Component3, self.comp_registry["component1"], self.comp_registry["base"]), + self.comp_registry["component3"].__bases__, ) self.assertEqual( - (Component4, - self.comp_registry['component2'], - self.comp_registry['component3'], - self.comp_registry['base']), - self.comp_registry['component4'].__bases__ + ( + Component4, + self.comp_registry["component2"], + self.comp_registry["component3"], + self.comp_registry["base"], + ), + self.comp_registry["component4"].__bases__, ) def test_custom_build(self): """ Check that we can hook at the end of a Component build """ + class Component1(Component): - _name = 'component1' + _name = "component1" @classmethod def _complete_component_build(cls): @@ -130,143 +127,147 @@ def _complete_component_build(cls): Component1._build_component(self.comp_registry) # we inspect that our custom build has been executed - self.assertTrue( - self.comp_registry['component1']._build_done - ) + self.assertTrue(self.comp_registry["component1"]._build_done) def test_inherit_attrs(self): """ Check attributes inheritance of Components with _inherit """ + class Component1(Component): - _name = 'component1' + _name = "component1" - msg = 'ping' + msg = "ping" def say(self): - return 'foo' + return "foo" class Component2(Component): - _name = 'component2' - _inherit = 'component1' + _name = "component2" + _inherit = "component1" - msg = 'pong' + msg = "pong" def say(self): - return super().say() + ' bar' + return super().say() + " bar" Component1._build_component(self.comp_registry) Component2._build_component(self.comp_registry) # we initialize the components, normally we should pass # an instance of WorkContext, but we don't need a real one # for this test - component1 = self.comp_registry['component1'](mock.Mock()) - component2 = self.comp_registry['component2'](mock.Mock()) - self.assertEqual('ping', component1.msg) - self.assertEqual('pong', component2.msg) - self.assertEqual('foo', component1.say()) - self.assertEqual('foo bar', component2.say()) + component1 = self.comp_registry["component1"](mock.Mock()) + component2 = self.comp_registry["component2"](mock.Mock()) + self.assertEqual("ping", component1.msg) + self.assertEqual("pong", component2.msg) + self.assertEqual("foo", component1.say()) + self.assertEqual("foo bar", component2.say()) def test_duplicate_component(self): """ Check that we can't have 2 components with the same name """ + class Component1(Component): - _name = 'component1' + _name = "component1" class Component2(Component): - _name = 'component1' + _name = "component1" Component1._build_component(self.comp_registry) - msg = 'Component.*already exists.*' + msg = "Component.*already exists.*" with self.assertRaisesRegex(TypeError, msg): Component2._build_component(self.comp_registry) def test_no_parent(self): """ Ensure we can't _inherit a non-existent component """ + class Component1(Component): - _name = 'component1' - _inherit = 'component1' + _name = "component1" + _inherit = "component1" - msg = 'Component.*does not exist in registry.*' + msg = "Component.*does not exist in registry.*" with self.assertRaisesRegex(TypeError, msg): Component1._build_component(self.comp_registry) def test_no_parent2(self): """ Ensure we can't _inherit by prototype a non-existent component """ + class Component1(Component): - _name = 'component1' + _name = "component1" class Component2(Component): - _name = 'component2' - _inherit = ['component1', 'component3'] + _name = "component2" + _inherit = ["component1", "component3"] Component1._build_component(self.comp_registry) - msg = 'Component.*inherits from non-existing component.*' + msg = "Component.*inherits from non-existing component.*" with self.assertRaisesRegex(TypeError, msg): Component2._build_component(self.comp_registry) def test_add_inheritance(self): """ Ensure we can add a new inheritance """ + class Component1(Component): - _name = 'component1' + _name = "component1" class Component2(Component): - _name = 'component2' + _name = "component2" class Component2bis(Component): - _name = 'component2' - _inherit = ['component2', 'component1'] + _name = "component2" + _inherit = ["component2", "component1"] Component1._build_component(self.comp_registry) Component2._build_component(self.comp_registry) Component2bis._build_component(self.comp_registry) self.assertEqual( - (Component2bis, - Component2, - self.comp_registry['component1'], - self.comp_registry['base']), - self.comp_registry['component2'].__bases__ + ( + Component2bis, + Component2, + self.comp_registry["component1"], + self.comp_registry["base"], + ), + self.comp_registry["component2"].__bases__, ) def test_check_parent_component_over_abstract(self): """ Component can inherit from AbstractComponent """ + class Component1(AbstractComponent): - _name = 'component1' + _name = "component1" class Component2(Component): - _name = 'component2' - _inherit = 'component1' + _name = "component2" + _inherit = "component1" Component1._build_component(self.comp_registry) Component2._build_component(self.comp_registry) - self.assertTrue( - self.comp_registry['component1']._abstract - ) - self.assertFalse( - self.comp_registry['component2']._abstract - ) + self.assertTrue(self.comp_registry["component1"]._abstract) + self.assertFalse(self.comp_registry["component2"]._abstract) def test_check_parent_abstract_over_component(self): """ Prevent AbstractComponent to inherit from Component """ + class Component1(Component): - _name = 'component1' + _name = "component1" class Component2(AbstractComponent): - _name = 'component2' - _inherit = 'component1' + _name = "component2" + _inherit = "component1" Component1._build_component(self.comp_registry) - msg = '.*cannot inherit from the non-abstract.*' + msg = ".*cannot inherit from the non-abstract.*" with self.assertRaisesRegex(TypeError, msg): Component2._build_component(self.comp_registry) def test_check_transform_abstract_to_component(self): """ Prevent AbstractComponent to be transformed to Component """ + class Component1(AbstractComponent): - _name = 'component1' + _name = "component1" class Component1bis(Component): - _inherit = 'component1' + _inherit = "component1" Component1._build_component(self.comp_registry) - msg = '.*transforms the abstract component.*into a non-abstract.*' + msg = ".*transforms the abstract component.*into a non-abstract.*" with self.assertRaisesRegex(TypeError, msg): Component1bis._build_component(self.comp_registry) diff --git a/component/tests/test_component.py b/component/tests/test_component.py index ea58284da..e88457aae 100644 --- a/component/tests/test_component.py +++ b/component/tests/test_component.py @@ -1,16 +1,12 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) from contextlib import contextmanager -from odoo.addons.component.core import ( - Component, -) + +from odoo.addons.component.core import Component +from odoo.addons.component.exception import NoComponentError, SeveralComponentError + from .common import TransactionComponentRegistryCase -from odoo.addons.component.exception import ( - NoComponentError, - SeveralComponentError, -) class TestComponent(TransactionComponentRegistryCase): @@ -26,20 +22,20 @@ class TestComponent(TransactionComponentRegistryCase): def setUp(self): super().setUp() - self.collection = self.env['collection.base'] + self.collection = self.env["collection.base"] # create some Component to play with class Component1(Component): - _name = 'component1' - _collection = 'collection.base' - _usage = 'for.test' - _apply_on = ['res.partner'] + _name = "component1" + _collection = "collection.base" + _usage = "for.test" + _apply_on = ["res.partner"] class Component2(Component): - _name = 'component2' - _collection = 'collection.base' - _usage = 'for.test' - _apply_on = ['res.users'] + _name = "component2" + _collection = "collection.base" + _usage = "for.test" + _apply_on = ["res.users"] # build the components and register them in our # test component registry @@ -57,26 +53,27 @@ def get_base(): # We are working with res.partner in the following tests, # unless we change it in the test. with self.collection_record.work_on( - 'res.partner', - # we use a custom registry only - # for the sake of the tests - components_registry=self.comp_registry - ) as work: + "res.partner", + # we use a custom registry only + # for the sake of the tests + components_registry=self.comp_registry, + ) as work: # We get the 'base' component, handy to test the base # methods component, many_components, ... - yield work.component_by_name('base') + yield work.component_by_name("base") + self.get_base = get_base def test_component_attrs(self): """ Basic access to a Component's attribute """ with self.get_base() as base: # as we are working on res.partner, we should get 'component1' - comp = base.work.component(usage='for.test') + comp = base.work.component(usage="for.test") # but this is not what we test here, we test the attributes: self.assertEqual(self.collection_record, comp.collection) self.assertEqual(base.work, comp.work) self.assertEqual(self.env, comp.env) - self.assertEqual(self.env['res.partner'], comp.model) + self.assertEqual(self.env["res.partner"], comp.model) def test_component_get_by_name_same_model(self): """ Use component_by_name with current working model """ @@ -84,9 +81,9 @@ def test_component_get_by_name_same_model(self): # we ask a component directly by it's name, considering # we work with res.partner, we should get 'component1' # this is ok because it's _apply_on contains res.partner - comp = base.component_by_name('component1') - self.assertEqual('component1', comp._name) - self.assertEqual(self.env['res.partner'], comp.model) + comp = base.component_by_name("component1") + self.assertEqual("component1", comp._name) + self.assertEqual(self.env["res.partner"], comp.model) def test_component_get_by_name_other_model(self): """ Use component_by_name with another model """ @@ -94,68 +91,67 @@ def test_component_get_by_name_other_model(self): # we ask a component directly by it's name, but we # want to work with 'res.users', this is ok since # component2's _apply_on contains res.users - comp = base.component_by_name( - 'component2', model_name='res.users' - ) - self.assertEqual('component2', comp._name) - self.assertEqual(self.env['res.users'], comp.model) + comp = base.component_by_name("component2", model_name="res.users") + self.assertEqual("component2", comp._name) + self.assertEqual(self.env["res.users"], comp.model) # what happens under the hood, is that a new WorkContext # has been created for this model, with all the other values # identical to the previous WorkContext (the one for res.partner) # We can check that with: self.assertNotEqual(base.work, comp.work) - self.assertEqual('res.partner', base.work.model_name) - self.assertEqual('res.users', comp.work.model_name) + self.assertEqual("res.partner", base.work.model_name) + self.assertEqual("res.users", comp.work.model_name) def test_component_get_by_name_wrong_model(self): """ Use component_by_name with a model not in _apply_on """ - msg = ("Component with name 'component2' can't be used " - "for model 'res.partner'.*") + msg = ( + "Component with name 'component2' can't be used " + "for model 'res.partner'.*" + ) with self.get_base() as base: with self.assertRaisesRegex(NoComponentError, msg): # we ask for the model 'component2' but we are working # with res.partner, and it only accepts res.users - base.component_by_name('component2') + base.component_by_name("component2") def test_component_get_by_name_not_exist(self): """ Use component_by_name on a component that do not exist """ msg = "No component with name 'foo' found." with self.get_base() as base: with self.assertRaisesRegex(NoComponentError, msg): - base.component_by_name('foo') + base.component_by_name("foo") def test_component_by_usage_same_model(self): """ Use component(usage=...) on the same model """ # we ask for a component having _usage == 'for.test', and # model being res.partner (the model in the current WorkContext) with self.get_base() as base: - comp = base.component(usage='for.test') - self.assertEqual('component1', comp._name) - self.assertEqual(self.env['res.partner'], comp.model) + comp = base.component(usage="for.test") + self.assertEqual("component1", comp._name) + self.assertEqual(self.env["res.partner"], comp.model) def test_component_by_usage_other_model(self): """ Use component(usage=...) on a different model (name) """ # we ask for a component having _usage == 'for.test', and # a different model (res.users) with self.get_base() as base: - comp = base.component(usage='for.test', model_name='res.users') - self.assertEqual('component2', comp._name) - self.assertEqual(self.env['res.users'], comp.model) + comp = base.component(usage="for.test", model_name="res.users") + self.assertEqual("component2", comp._name) + self.assertEqual(self.env["res.users"], comp.model) # what happens under the hood, is that a new WorkContext # has been created for this model, with all the other values # identical to the previous WorkContext (the one for res.partner) # We can check that with: self.assertNotEqual(base.work, comp.work) - self.assertEqual('res.partner', base.work.model_name) - self.assertEqual('res.users', comp.work.model_name) + self.assertEqual("res.partner", base.work.model_name) + self.assertEqual("res.users", comp.work.model_name) def test_component_by_usage_other_model_env(self): """ Use component(usage=...) on a different model (instance) """ with self.get_base() as base: - comp = base.component(usage='for.test', - model_name=self.env['res.users']) - self.assertEqual('component2', comp._name) - self.assertEqual(self.env['res.users'], comp.model) + comp = base.component(usage="for.test", model_name=self.env["res.users"]) + self.assertEqual("component2", comp._name) + self.assertEqual(self.env["res.users"], comp.model) def test_component_error_several(self): """ Use component(usage=...) when more than one generic component match @@ -164,14 +160,14 @@ def test_component_error_several(self): # collection and no _apply_on, and we remove the _apply_on of component # 1 so they are generic components for a collection class Component3(Component): - _name = 'component3' - _collection = 'collection.base' - _usage = 'for.test' + _name = "component3" + _collection = "collection.base" + _usage = "for.test" class Component1(Component): - _inherit = 'component1' - _collection = 'collection.base' - _usage = 'for.test' + _inherit = "component1" + _collection = "collection.base" + _usage = "for.test" _apply_on = None Component3._build_component(self.comp_registry) @@ -183,7 +179,7 @@ class Component1(Component): # on *any* model. Here, the candidates components would be: # component3 (because it has no _apply_on so apply in any case) # component4 (for the same reason) - base.component(usage='for.test') + base.component(usage="for.test") def test_component_error_several_same_model(self): """ Use component(usage=...) when more than one component match a model @@ -191,10 +187,10 @@ def test_component_error_several_same_model(self): # we create a new Component with _usage 'for.test', in the same # collection and no _apply_on class Component3(Component): - _name = 'component3' - _collection = 'collection.base' - _usage = 'for.test' - _apply_on = ['res.partner'] + _name = "component3" + _collection = "collection.base" + _usage = "for.test" + _apply_on = ["res.partner"] Component3._build_component(self.comp_registry) @@ -203,7 +199,7 @@ class Component3(Component): # Here, the candidates components would be: # component1 (because we are working with res.partner), # component3 (for the same reason) - base.component(usage='for.test') + base.component(usage="for.test") def test_component_specific_model(self): """ Use component(usage=...) when more than one component match but @@ -212,9 +208,9 @@ def test_component_specific_model(self): # collection and no _apply_on. This is a generic component for the # collection class Component3(Component): - _name = 'component3' - _collection = 'collection.base' - _usage = 'for.test' + _name = "component3" + _collection = "collection.base" + _usage = "for.test" Component3._build_component(self.comp_registry) @@ -228,8 +224,8 @@ class Component3(Component): # allows to create a generic implementation (component3 here) and # override it only for a given model. So in this case, the final # component is component1. - comp = base.component(usage='for.test') - self.assertEquals('component1', comp._name) + comp = base.component(usage="for.test") + self.assertEquals("component1", comp._name) def test_component_specific_collection(self): """ Use component(usage=...) when more than one component match but @@ -237,8 +233,8 @@ def test_component_specific_collection(self): # we create a new Component with _usage 'for.test', without collection # and no _apply_on class Component3(Component): - _name = 'component3' - _usage = 'for.test' + _name = "component3" + _usage = "for.test" Component3._build_component(self.comp_registry) @@ -251,8 +247,8 @@ class Component3(Component): # on all model if no component is found for the current collection: # component3 must be ignored since a component (component1) exists # and is specificaly linked to the expected collection. - comp = base.component(usage='for.test') - self.assertEquals('component1', comp._name) + comp = base.component(usage="for.test") + self.assertEquals("component1", comp._name) def test_component_specific_collection_specific_model(self): """ Use component(usage=...) when more than one component match but @@ -261,8 +257,8 @@ def test_component_specific_collection_specific_model(self): # and no _apply_on. This is a component generic for all collections and # models class Component3(Component): - _name = 'component3' - _usage = 'for.test' + _name = "component3" + _usage = "for.test" Component3._build_component(self.comp_registry) @@ -280,82 +276,76 @@ class Component3(Component): # implementation (component3 here) and override it only for a given # collection and model. So in this case, the final component is # component1. - comp = base.component(usage='for.test') - self.assertEquals('component1', comp._name) + comp = base.component(usage="for.test") + self.assertEquals("component1", comp._name) def test_many_components(self): """ Use many_components(usage=...) on the same model """ + class Component3(Component): - _name = 'component3' - _collection = 'collection.base' - _usage = 'for.test' + _name = "component3" + _collection = "collection.base" + _usage = "for.test" Component3._build_component(self.comp_registry) with self.get_base() as base: - comps = base.many_components(usage='for.test') + comps = base.many_components(usage="for.test") # When a component has no _apply_on, it means it can be applied # on *any* model. So here, both component1 and component3 match - self.assertEqual( - ['component1', 'component3'], - [c._name for c in comps] - ) + self.assertEqual(["component1", "component3"], [c._name for c in comps]) def test_many_components_other_model(self): """ Use many_components(usage=...) on a different model (name) """ + class Component3(Component): - _name = 'component3' - _collection = 'collection.base' - _apply_on = 'res.users' - _usage = 'for.test' + _name = "component3" + _collection = "collection.base" + _apply_on = "res.users" + _usage = "for.test" Component3._build_component(self.comp_registry) with self.get_base() as base: - comps = base.many_components(usage='for.test', - model_name='res.users') + comps = base.many_components(usage="for.test", model_name="res.users") - self.assertEqual( - ['component2', 'component3'], - [c._name for c in comps] - ) + self.assertEqual(["component2", "component3"], [c._name for c in comps]) def test_many_components_other_model_env(self): """ Use many_components(usage=...) on a different model (instance) """ + class Component3(Component): - _name = 'component3' - _collection = 'collection.base' - _apply_on = 'res.users' - _usage = 'for.test' + _name = "component3" + _collection = "collection.base" + _apply_on = "res.users" + _usage = "for.test" Component3._build_component(self.comp_registry) with self.get_base() as base: - comps = base.many_components(usage='for.test', - model_name=self.env['res.users']) + comps = base.many_components( + usage="for.test", model_name=self.env["res.users"] + ) - self.assertEqual( - ['component2', 'component3'], - [c._name for c in comps] - ) + self.assertEqual(["component2", "component3"], [c._name for c in comps]) def test_no_component(self): """ No component found for asked usage """ with self.get_base() as base: with self.assertRaises(NoComponentError): - base.component(usage='foo') + base.component(usage="foo") def test_no_many_component(self): """ No component found for asked usage for many_components() """ with self.get_base() as base: - self.assertEqual([], base.many_components(usage='foo')) + self.assertEqual([], base.many_components(usage="foo")) def test_work_on_component(self): """ Check WorkContext.component() (shortcut to Component.component) """ with self.get_base() as base: - comp = base.work.component(usage='for.test') - self.assertEqual('component1', comp._name) + comp = base.work.component(usage="for.test") + self.assertEqual("component1", comp._name) def test_work_on_many_components(self): """ Check WorkContext.many_components() @@ -363,32 +353,32 @@ def test_work_on_many_components(self): (shortcut to Component.many_components) """ with self.get_base() as base: - comps = base.work.many_components(usage='for.test') - self.assertEqual('component1', comps[0]._name) + comps = base.work.many_components(usage="for.test") + self.assertEqual("component1", comps[0]._name) def test_component_match(self): """ Lookup with match method """ + class Foo(Component): - _name = 'foo' - _collection = 'collection.base' - _usage = 'speaker' - _apply_on = ['res.partner'] + _name = "foo" + _collection = "collection.base" + _usage = "speaker" + _apply_on = ["res.partner"] @classmethod def _component_match(cls, work): return False class Bar(Component): - _name = 'bar' - _collection = 'collection.base' - _usage = 'speaker' - _apply_on = ['res.partner'] + _name = "bar" + _collection = "collection.base" + _usage = "speaker" + _apply_on = ["res.partner"] self._build_components(Foo, Bar) with self.get_base() as base: # both components would we returned without the # _component_match method - comp = base.component(usage='speaker', - model_name=self.env['res.partner']) - self.assertEqual('bar', comp._name) + comp = base.component(usage="speaker", model_name=self.env["res.partner"]) + self.assertEqual("bar", comp._name) diff --git a/component/tests/test_lookup.py b/component/tests/test_lookup.py index 29fe84197..16e35cd62 100644 --- a/component/tests/test_lookup.py +++ b/component/tests/test_lookup.py @@ -1,11 +1,8 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) -from odoo.addons.component.core import ( - AbstractComponent, - Component, -) +from odoo.addons.component.core import AbstractComponent, Component + from .common import ComponentRegistryCase @@ -29,83 +26,77 @@ def test_lookup_collection(self): """ Lookup components of a collection """ # we register 2 components in foobar and one in other class Foo(Component): - _name = 'foo' - _collection = 'foobar' + _name = "foo" + _collection = "foobar" class Bar(Component): - _name = 'bar' - _collection = 'foobar' + _name = "bar" + _collection = "foobar" class Homer(Component): - _name = 'homer' - _collection = 'other' + _name = "homer" + _collection = "other" self._build_components(Foo, Bar, Homer) # we should no see the component in 'other' - components = self.comp_registry.lookup('foobar') - self.assertEqual( - ['foo', 'bar'], - [c._name for c in components] - ) + components = self.comp_registry.lookup("foobar") + self.assertEqual(["foo", "bar"], [c._name for c in components]) def test_lookup_usage(self): """ Lookup components by usage """ + class Foo(Component): - _name = 'foo' - _collection = 'foobar' - _usage = 'speaker' + _name = "foo" + _collection = "foobar" + _usage = "speaker" class Bar(Component): - _name = 'bar' - _collection = 'foobar' - _usage = 'speaker' + _name = "bar" + _collection = "foobar" + _usage = "speaker" class Baz(Component): - _name = 'baz' - _collection = 'foobar' - _usage = 'listener' + _name = "baz" + _collection = "foobar" + _usage = "listener" self._build_components(Foo, Bar, Baz) - components = self.comp_registry.lookup('foobar', usage='listener') - self.assertEqual('baz', components[0]._name) + components = self.comp_registry.lookup("foobar", usage="listener") + self.assertEqual("baz", components[0]._name) - components = self.comp_registry.lookup('foobar', usage='speaker') - self.assertEqual( - ['foo', 'bar'], - [c._name for c in components] - ) + components = self.comp_registry.lookup("foobar", usage="speaker") + self.assertEqual(["foo", "bar"], [c._name for c in components]) def test_lookup_no_component(self): """ No component """ # we just expect an empty list when no component match, the error # handling is handled at an higher level - self.assertEqual( - [], - self.comp_registry.lookup('something', usage='something') - ) + self.assertEqual([], self.comp_registry.lookup("something", usage="something")) def test_get_by_name(self): """ Get component by name """ + class Foo(AbstractComponent): - _name = 'foo' - _collection = 'foobar' + _name = "foo" + _collection = "foobar" self._build_components(Foo) # this is just a dict access - self.assertEqual('foo', self.comp_registry['foo']._name) + self.assertEqual("foo", self.comp_registry["foo"]._name) def test_lookup_abstract(self): """ Do not include abstract components in lookup """ + class Foo(AbstractComponent): - _name = 'foo' - _collection = 'foobar' - _usage = 'speaker' + _name = "foo" + _collection = "foobar" + _usage = "speaker" class Bar(Component): - _name = 'bar' - _inherit = 'foo' + _name = "bar" + _inherit = "foo" self._build_components(Foo, Bar) @@ -113,70 +104,69 @@ class Bar(Component): # we should never have 'foo' in the returned components # as it is abstract - components = comp_registry.lookup('foobar', usage='speaker') - self.assertEqual('bar', components[0]._name) + components = comp_registry.lookup("foobar", usage="speaker") + self.assertEqual("bar", components[0]._name) - components = comp_registry.lookup('foobar', usage='speaker') - self.assertEqual( - ['bar'], - [c._name for c in components] - ) + components = comp_registry.lookup("foobar", usage="speaker") + self.assertEqual(["bar"], [c._name for c in components]) def test_lookup_model_name(self): """ Lookup with model names """ + class Foo(Component): - _name = 'foo' - _collection = 'foobar' - _usage = 'speaker' + _name = "foo" + _collection = "foobar" + _usage = "speaker" # support list - _apply_on = ['res.partner'] + _apply_on = ["res.partner"] class Bar(Component): - _name = 'bar' - _collection = 'foobar' - _usage = 'speaker' + _name = "bar" + _collection = "foobar" + _usage = "speaker" # support string - _apply_on = 'res.users' + _apply_on = "res.users" class Any(Component): # can be used with any model as far as we look it up # with its usage - _name = 'any' - _collection = 'foobar' - _usage = 'listener' + _name = "any" + _collection = "foobar" + _usage = "listener" self._build_components(Foo, Bar, Any) - components = self.comp_registry.lookup('foobar', - usage='speaker', - model_name='res.partner') - self.assertEqual('foo', components[0]._name) + components = self.comp_registry.lookup( + "foobar", usage="speaker", model_name="res.partner" + ) + self.assertEqual("foo", components[0]._name) - components = self.comp_registry.lookup('foobar', - usage='speaker', - model_name='res.users') - self.assertEqual('bar', components[0]._name) + components = self.comp_registry.lookup( + "foobar", usage="speaker", model_name="res.users" + ) + self.assertEqual("bar", components[0]._name) - components = self.comp_registry.lookup('foobar', - usage='listener', - model_name='res.users') - self.assertEqual('any', components[0]._name) + components = self.comp_registry.lookup( + "foobar", usage="listener", model_name="res.users" + ) + self.assertEqual("any", components[0]._name) def test_lookup_cache(self): """ Lookup uses a cache """ + class Foo(Component): - _name = 'foo' - _collection = 'foobar' + _name = "foo" + _collection = "foobar" self._build_components(Foo) - components = self.comp_registry.lookup('foobar') - self.assertEqual(['foo'], [c._name for c in components]) + components = self.comp_registry.lookup("foobar") + self.assertEqual(["foo"], [c._name for c in components]) # we add a new component class Bar(Component): - _name = 'bar' - _collection = 'foobar' + _name = "bar" + _collection = "foobar" self._build_components(Bar) @@ -185,10 +175,10 @@ class Bar(Component): # We do this for testing, but in a real use case, we can't # add new Component classes on the fly, and when we install # new addons, the registry is rebuilt and cache cleared. - components = self.comp_registry.lookup('foobar') - self.assertEqual(['foo'], [c._name for c in components]) + components = self.comp_registry.lookup("foobar") + self.assertEqual(["foo"], [c._name for c in components]) self.comp_registry._cache.clear() # now we should find them both as the cache has been cleared - components = self.comp_registry.lookup('foobar') - self.assertEqual(['foo', 'bar'], [c._name for c in components]) + components = self.comp_registry.lookup("foobar") + self.assertEqual(["foo", "bar"], [c._name for c in components]) diff --git a/component/tests/test_work_on.py b/component/tests/test_work_on.py index f7a19d11b..3865f2048 100644 --- a/component/tests/test_work_on.py +++ b/component/tests/test_work_on.py @@ -1,8 +1,8 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) -from odoo.addons.component.core import WorkContext, ComponentRegistry +from odoo.addons.component.core import ComponentRegistry, WorkContext + from .common import TransactionComponentCase @@ -16,40 +16,40 @@ class TestWorkOn(TransactionComponentCase): def setUp(self): super().setUp() - self.collection = self.env['collection.base'] + self.collection = self.env["collection.base"] def test_collection_work_on(self): """ Create a new instance and test attributes access """ collection_record = self.collection.new() - with collection_record.work_on('res.partner') as work: + with collection_record.work_on("res.partner") as work: self.assertEqual(collection_record, work.collection) - self.assertEqual('collection.base', work.collection._name) - self.assertEqual('res.partner', work.model_name) - self.assertEqual(self.env['res.partner'], work.model) + self.assertEqual("collection.base", work.collection._name) + self.assertEqual("res.partner", work.model_name) + self.assertEqual(self.env["res.partner"], work.model) self.assertEqual(self.env, work.env) def test_propagate_work_on(self): """ Check custom attributes and their propagation """ registry = ComponentRegistry() work = WorkContext( - model_name='res.partner', + model_name="res.partner", collection=self.collection, # we can customize the lookup registry, but used mostly for tests components_registry=registry, # we can pass our own keyword args that will set as attributes - test_keyword='value', + test_keyword="value", ) self.assertIs(registry, work.components_registry) # check that our custom keyword is set as attribute - self.assertEqual('value', work.test_keyword) + self.assertEqual("value", work.test_keyword) # when we want to work on another model, work_on() create # another instance and propagate the attributes to it - work2 = work.work_on('res.users') + work2 = work.work_on("res.users") self.assertNotEqual(work, work2) self.assertEqual(self.env, work2.env) self.assertEqual(self.collection, work2.collection) - self.assertEqual('res.users', work2.model_name) + self.assertEqual("res.users", work2.model_name) self.assertIs(registry, work2.components_registry) # test_keyword has been propagated to the new WorkContext instance - self.assertEqual('value', work2.test_keyword) + self.assertEqual("value", work2.test_keyword)