Skip to content

[19.0][MIG] component: Migration to 19.0#525

Merged
OCA-git-bot merged 100 commits into
OCA:19.0from
camptocamp:19.0-mig-component
Apr 20, 2026
Merged

[19.0][MIG] component: Migration to 19.0#525
OCA-git-bot merged 100 commits into
OCA:19.0from
camptocamp:19.0-mig-component

Conversation

@yankinmax
Copy link
Copy Markdown
Contributor

@yankinmax yankinmax commented Apr 1, 2026

Standard migration.

Replaces #508

  1. This PR is opened to speed up migration to 19.0.
  2. Handle tests issue happening on the modules which depends on component.

See also @mkoeck comment here:
#508 (review)

Example with webservice

ERROR odoo odoo.tests.suite: ERROR: setUpClass (odoo.addons.webservice.tests.test_oauth2.TestWebServiceOauth2BackendApplication)
Traceback (most recent call last):
  File "/__w/web-api/web-api/webservice/tests/common.py", line 35, in setUpClass
    super().setUpClass()
  File "/opt/odoo-venv/lib/python3.10/site-packages/odoo/addons/component/tests/common.py", line 70, in setUpClass
    cls.setUpComponent()
  File "/opt/odoo-venv/lib/python3.10/site-packages/odoo/addons/component/tests/common.py", line 43, in setUpComponent
    cls.env.context = dict(
  File "/opt/odoo/odoo/orm/environments.py", line 94, in __setattr__
    raise AttributeError(f"Attribute {name!r} is read-only, call `env()` instead")
AttributeError: Attribute 'context' is read-only, call `env()` instead

Guewen Baconnier and others added 30 commits April 1, 2026 14:12
The favorite lookup should be by 'usage' (kinda interface) and by model
name ('components()' method).  The lookup by component name should
normally not be used as it reduces the flexibility.  Using a different
method for this lookup discourage its usage.  Also, the lookup by
component name completely ignores the current collection, which is bad
or not bad depending of what you want to achieve.
when inheriting from multiple components, we might inadvertly override a
value with None
Used for instance by the 'ecommerce' components
The mapping methods are now built by the component initialization when
the "aggregated" class is built.
And remove automatic naming from class name, not explicit enough,
especially when we have to inherit from one.

We could take the total opposite and only use class names components:

class MyComponent(Component):
    ...

class MyComponentExtended(Component):
    _inherit = 'MyComponent'

But it would be less close to the odoo's API.
============================================================================================================= test session starts =============================================================================================================
platform linux2 -- Python 2.7.9, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
run-last-failure: run all (no recorded failures)
rootdir: /opt/odoo, inifile:
plugins: cov-2.5.1, odoo-0.2.2
collected 25 items
odoo/external-src/connector/component/tests/test_build_component.py .........
odoo/external-src/connector/component/tests/test_component.py ........
odoo/external-src/connector/component/tests/test_lookup.py ......
odoo/external-src/connector/component/tests/test_work_on.py ..
---------- coverage: platform linux2, python 2.7.9-final-0 -----------
Name                                                                  Stmts   Miss  Cover
-----------------------------------------------------------------------------------------
odoo/external-src/connector/component/__init__.py                         4      0   100%
odoo/external-src/connector/component/__manifest__.py                     1      1     0%
odoo/external-src/connector/component/base_components.py                  3      0   100%
odoo/external-src/connector/component/builder.py                         18      0   100%
odoo/external-src/connector/component/core.py                           155      6    96%
odoo/external-src/connector/component/exception.py                        3      0   100%
odoo/external-src/connector/component/models/__init__.py                  1      0   100%
odoo/external-src/connector/component/models/collection.py                8      0   100%
odoo/external-src/connector/component/tests/__init__.py                   4      0   100%
odoo/external-src/connector/component/tests/common.py                    26      2    92%
odoo/external-src/connector/component/tests/test_build_component.py     102      0   100%
odoo/external-src/connector/component/tests/test_component.py            56      0   100%
odoo/external-src/connector/component/tests/test_lookup.py               84      0   100%
odoo/external-src/connector/component/tests/test_work_on.py              26      0   100%
-----------------------------------------------------------------------------------------
TOTAL                                                                   491      9    98%
========================================================================================================== 25 passed in 0.76 seconds ==========================================================================================================
the 'components' method had 2 different return types depending of the
'multi' argument.

Now we have 'component' or 'many_components' that return a Component
instance or a list of Component instances.
Proposing a new API based on components for the events
Because they can have different addons
* Move the methods to get components from the components to the
WorkContext, it should really be its responsibilities to get them.
There are shorcuts on the components though.
My first implementation was like that, then I moved the lookup methods
on the components thinking that it would allow to customize them. But if
we did that, we would have a different behavior from component to
component which is bad, so if one really wanted to do that, better have
to work with a different subclass of WorkContext, which would have its
own behavior, consistently throughout all the work session.

* Allow to switch the collection using work_on(), not only the
  model_name
Tests using odoo transactions must run post install, because during the
install the registry is not ready, so the components aren't neither.
For consistency, this is where components should go (as for models,
views, ...)
Checking that the odoo registry is ready is not working:
in tests, the events are not working because they are run
just before the odoo registry is set to ready.
(might be empty for EventWorkContext)
It allows to open/close objects on start/end of a synchro / work
session. The base method does none of that, but this is a really common
use case. Example: at the beginning of the work session, I open a
webservice client that is available in our WorkContext for the duration
of our work. At the end, I close the client to end the connection.
…ule is loaded with test-enable=True, the components of this module are not registerd by the call to the method _register_hook of the component.builder. Indeed the state of the module is still *to install*. This change allows to call the method *load_components* on the component.builder for a specific module by taking care to not reload the components of a module already loaded.
It the previous commit, @lmignon added the possibility to load all
components of an addon in a Component Registry.  This commit takes
benefit of this feature to simplify the existing tests and to add a base
test case for the Connector (that loads all components of 'component',
'component_event', 'connector'). It can be used in implementations using
the connector.
This method can be used to filter out some components. It is executed on
every candidate component returned by a lookup for a
collection/usage/model so must be kept light to execute if possible.

A use case can be for instance to have more than one kind of export in a
connector for a model.

Say that you have a different way to export customers and suppliers:

    with self.work_on('res.partner', kind='customer') as work:
        exporter = work.component(usage='record.exporter)
        exporter.run()

    with self.work_on('res.partner', kind='supplier') as work:
        exporter = work.component(usage='record.exporter)
        exporter.run()

You can declare your components as:

  class CustomerExporter(Component):

      _name = 'customer.exporter'
      _inherit = ['base.exporter']
      _usage = 'record.exporter'
      _apply_on = ['res.partner']

      @classmethod
      def _component_match(cls, work):
          return work.kind == 'customer'

      def run(self):
          # export customer

  class SupplierExporter(Component):

      _name = 'supplier.exporter'
      _inherit = ['base.exporter']
      _usage = 'record.exporter'
      _apply_on = ['res.partner']

      @classmethod
      def _component_match(cls, work):
          return work.kind == 'supplier'

      def run(self):
          # export supplier
When we want to test the implementation of a connector, it must be
simple. Add 2 new test cases for TransactionCase and SavepointCase which
load all the components of the dependencies addons on the tested addons.
Only the components of the addons in state 'installed' are loaded, so we
don't load components of addons that depend on the tested addon.

The tests must call _init_global_registry and build_registry instead of
_register_hook, so the registry is not set to ready. If the global
registry is set to ready during tests, the event will trigger during the
installation of addons which is not what we want.

The existing test case is meant only to be used when one has to
manipulate components in a custom registry.

See discussion on
guewen@447b22f#commitcomment-22851711
Copy link
Copy Markdown

@grindtildeath grindtildeath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG

@OCA-git-bot
Copy link
Copy Markdown
Contributor

This PR has the approved label and has been created more than 5 days ago. It should therefore be ready to merge by a maintainer (or a PSC member if the concerned addon has no declared maintainer). 🤖

1 similar comment
@OCA-git-bot
Copy link
Copy Markdown
Contributor

This PR has the approved label and has been created more than 5 days ago. It should therefore be ready to merge by a maintainer (or a PSC member if the concerned addon has no declared maintainer). 🤖

@yankinmax
Copy link
Copy Markdown
Contributor Author

Hello @OCA/connector-maintainers can you pls take a look and possibly trigger merge?

Copy link
Copy Markdown

@vvrossem vvrossem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

migration commit LG

Comment thread component/tests/test_component.py Outdated
@mostafabarmshory
Copy link
Copy Markdown

Dear @guewen @yankinmax @vvrossem

The connector is a common addon used across many projects, and there are multiple migration pull requests (MIG RPs) related to it.

None of them have been merged into the 19.0 main branch yet.
Please review them and approve one of them. We need this to be completed as soon as possible.

Copy link
Copy Markdown

@JordiMForgeFlow JordiMForgeFlow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

functional review

@simahawk simahawk mentioned this pull request Apr 13, 2026
@simahawk
Copy link
Copy Markdown
Contributor

simahawk commented Apr 13, 2026

Dear @guewen @yankinmax @vvrossem

The connector is a common addon used across many projects, and there are multiple migration pull requests (MIG RPs) related to it.

* [19.0][MIG] component: Migration to 19.0 #525

* [[19.0][MIG] component #508](https://github.com/OCA/connector/pull/508)

* [[19.0][MIG] component: Migration to 19.0 #521](https://github.com/OCA/connector/pull/521)

None of them have been merged into the 19.0 main branch yet. Please review them and approve one of them. We need this to be completed as soon as possible.

@yankinmax shall we prioritize this or #521? 🤔

@simahawk
Copy link
Copy Markdown
Contributor

I've answered myself: this one preserves the original work done by @Sanazzzmi. I've closed the other ;)

Copy link
Copy Markdown
Contributor

@simahawk simahawk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yankinmax LGTM. Just drop the superfluous comment and we are good to go.

Comment thread component/readme/CREDITS.md Outdated
@guewen
Copy link
Copy Markdown
Member

guewen commented Apr 20, 2026

/ocabot merge nobump

@OCA-git-bot
Copy link
Copy Markdown
Contributor

On my way to merge this fine PR!
Prepared branch 19.0-ocabot-merge-pr-525-by-guewen-bump-nobump, awaiting test results.

@OCA-git-bot OCA-git-bot merged commit f003bad into OCA:19.0 Apr 20, 2026
7 checks passed
@OCA-git-bot
Copy link
Copy Markdown
Contributor

Congratulations, your PR was merged at fa5b5be. Thanks a lot for contributing to OCA. ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.