Commit Graph
252 Commits
Author SHA1 Message Date
Xavier-Do 9b1957fd81 [FIX] core: revert check on new models before setup
This reverts commit 9cc4d6956b71291958114196107b1889109e92a1.

How to reproduce the issue:
- Starts from a database with some modules installed (account).
- Install a module with data only (l10n_generic_coa)

The models are not setup and the data fails to install.

A proper fix would be to mark the registry as dirty when new models are
added and only setup models when needed.

Since the faulty commit was part of a bunch of optimization and the
impact of this particular one is quite small, reverting it is a quick
and easy fix waiting for a better one (maybe, one day).

closes odoo/odoo#79552

Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-11-09 14:46:21 +00:00
Adrian Torres ed6595ed15 [FIX] base: prevent messing up existing registry 2021-04-08 08:20:03 +02:00
Paolo (pgi) fe7ed6627d [FIX] base: invalid UNIQUE constraint just warn
When a submodule overrides an old UNIQUE constraint with a new one,
records in that module may respect the new one and not the old one.
As the old module is updated, it would fail giving an ERROR message,
and therefore blocking the Odoo.sh deployment pipeline.

i.e. website_sale (old): res_users_login_key -> ['login', 'website_id']
             base (new): res_users_login_key -> ['login']

With this patch, the error level is changed from ERROR to WARNING,
leaving Odoo.sh free to continue the build deployment, as the error
was not a blocking one.

closes odoo/odoo#79199

X-original-commit: 8ed3641f81502d3a7e9c9bb93771c6f5601a31a9
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
Signed-off-by: Paolo Gatti (pgi) <pgi@odoo.com>
2021-10-29 14:07:47 +00:00
Xavier-Do 9dceea1818 [IMP] core: skip (setup|init)_models for module without models
Some modules are only adding data/tests/routes/static content.

In this case, it is useless to check the database schema or setup models
in registry.

closes odoo/odoo#78898

Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-10-26 13:22:40 +00:00
Xavier-Do 0e2b2c9c8a [FIX] core: avoid useless setup_models at install
When installing a database with all modules in enterprise,
install take around 20 minutes and almost half of that is spent in the
`setup_model` method.

There is actually two calls to `setup_models` for each module.

One of them was introduced in b5c50fa824
and only looks useful when upgrading a module with migration scripts.

This first fix proposes to skip `setup_models` if the module state is
`to install`.

closes odoo/odoo#78808

Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2021-10-22 15:04:43 +00:00
Raphael Collet bf0a6c9683 [FIX] registry: make invalidation flags thread-specific
The registry attributes 'registry_invalidated' and 'cache_invalidated'
are used to flag that the current request has modified the registry or
invalidated the ormcache, respectively.  This provides a simple yet
efficient way to signal registry changes or cache invalidations to other
workers.

However, those flags were not meant to be used with multi-threaded
workers.  For instance, a thread may signal registry changes that are
actually made by another thread.  It can also happen that a thread
changes the registry, which makes another thread crash (like a thread
modifying a dict while another one iterates over it), and the latter
will reset the registry to its original state because it misinterprets
the registry changes as its own changes.

The situation can even get worse, making threads crash in cascade and
eventually leaving the registry in an inconsistent state.  When this
happens, the worker is broken and has to be manually restarted.

The fix consists in making those flags thread-specific.  This does not
prevent thread crashing because of concurrent changes, but at least it
avoids leaving the worker in a broken state.

closes odoo/odoo#77273

X-original-commit: 28adbfa5a9df9b7754529d45188c0eedeffdf783
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-09-27 18:07:56 +00:00
Ivan Yelizariev 68b652b5b6 [FIX] core: regenerate user groups view after forcing demo data
Since
https://github.com/odoo/odoo/commit/8a3e1a0ccdad25ba5b4b99639bdaeb9073a27f1f,
`_update_user_groups_view` is called only once per module installation. However,
module installation is not the only scenario when data files are loaded and
hence we need to add the method call.

---

opw-2602541

closes odoo/odoo#76869

X-original-commit: a46d20c89c24a4e60faef09cf8ad7721bd29d6cc
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-09-22 08:15:47 +00:00
Adrian Torres c393a9882e [FIX] core: load all bases for ir.model before adding manual models
Commit cd12293386 introduced an
optimization in the way that models and their inheritances are loaded,
with this commit we defer the setting of each model class' bases
from the _build_model method to the _prepare_setup method.

This has the advantage of setting any given model class' `__bases__`
attribute only once, but it also means that when _add_manual_models is
called, the __bases__ for ir.model are not yet set (only the default
implementation exists), therefore any module overrides to ir.model do
not take effect when creating the custom models.

This meant that if one creates a custom model with chatter support (i.e.
custom ir.model behaviour implemented in mail) and one restarted the
server, the registry would not properly setup ir.model before creating
the custom model (yielding warnings about tracking and such not being
valid fields) and when creating a record of the custom model, the
registry would crash.

With this commit, ir.model's _prepare_setup is explicitly called before
_add_manual_models to ensure that all overrides to ir.model are taken
into account.

closes odoo/odoo#76325

X-original-commit: f3afb23cdf21f395855771a037c721e977dc93c8
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
2021-09-10 12:34:06 +00:00
Raphael ColletandXavier Dollé 1595c0ee27 [REF] core: replace thread-local "envs" by cursor-bound "transaction"
Refactor the Environments object into a Transaction object, which is
bound to one cursor, and is no longer shared among several cursors.

The following methods/properties have been changed:
 - Environment.envs no longer works (because of the design change);
 - Environment.manage() is deprecated (no longer useful);
 - Environment.reset() is now an instance method;
 - env.clear_upon_failure() is deprecated in favor of cr.savepoint().

closes odoo/odoo#75598

Related: odoo/enterprise#20451
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Xavier Dollé <xdo@odoo.com>
2021-09-03 15:45:46 +00:00
Benoit Socias c6ba756e4b [IMP] core, website: use fuzzy matching in web-based search
Before this commit searched terms were the ones entered by the end-user.

After this commit if the searched term is not found then the search is
performed on a resembling term.
The similarity is obtained from a Levenshtein distance combined with
ratios of common and different letters.
By default the dictionary against which the search term is matched is
based on the content of the search fields containing a word that starts
with the first letter of the search term.
If the `pg_trgm` Postgresql extension is installed the dictionary is
built from matches using the `<%%` operator (similar to the
`word_similarity` function).
Several approaches were benchmarked during development, those results
are available through the task record.

task-2379555
https://github.com/odoo/odoo/pull/65871

Part-of: odoo/odoo#65871
2021-09-03 06:59:33 +00:00
Xavier-Do e27340066b [IMP] core: enforce explicit license in all manifest
The license was missing in most enterprise manifest so
the decision was taken to make it explicit in all cases.

The missing licenses were add in all version starting from
12.0 in repos odoo, enterprise and design-themes.

Starting from this commit, when a license is not defined,
a warning will be triggered.

closes odoo/odoo#74347

Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2021-07-30 12:34:11 +00:00
Xavier Morel 6196ed0ab0 [IMP] core: mitigate possible deadlock on module installation
When installing some modules, if an other action is undertaken around
the same time it is possible for the two to deadlock, leading to the
two workers being killed by the wallclock limit watcher. This should
only be an issue on the *threaded* server, workers should not be
affected, meaning the issue is not reproducible on runbot.

A relatively reliable way to trigger this issue manually is to create
an empty database, on the "apps" kanban view install the "sales"
application, and as soon as the UI gets unblocked install the "CRM"
application. An other method (also reliable but not really doable by
hand) is to simultanously log in and install the sales
application (`sale_management` module).

The core of the issue seems to be in `_button_immediate_function`:

1. `Other` has an env ready for use and has accessed various
   models (so has pretty shallow locks on the tables e.g.
   ACCESS SHARE).
2. `Install` takes the registry lock to create the new registry.
3. `Install` needs to update one of the tables `other` has touched,
   starts waiting on the `ACCESS EXCLUSIVE` lock (the only one
   `ACCESS SHARE` conflicts with) in order to execute DDL (most `ALTER
   TABLE` forms require exclusive access to the table).
4. `Other` needs a new environment (e.g. `sudo()`, `with_user`,
   `with_context`, ...), starts waiting on the registry lock.

At this point the two threads are deadlocked, `other` waits on the
registry lock which `install` holds, while `install` waits on a table
lock which `other` holds. Since one of the waits is on the application
side, Postgres' deadlock detector can not notice the issue. That one
of the locks is on the Python side is why only the threaded
server *should* be affected.

An initial seemingly promising mitigation attempt was to

    LOCK res_partner IN ACCESS EXCLUSIVE MODE

in the prelude of `_button_immediate_function` as `res.partner` is one
of the most commonly modified models, this would force
`_button_immediate_function` to wait until all existing requests have
completed and prevent later requests from progressing.

This turns out to be unreliable, as later requests could already have
acquired an environment and would race ahead as soon as the
transaction is committed if the scheduler lets them. Trying to lock
the registries earlier doesn't work as the locking is interleaved in
normal operation and we'd just deadlock there. The commit is because
`load_modules` does not take an externally provided cursor and instead
creates its own (thus its own connection and transaction). And because
of its lack of atomicity the issue might occur regardless.

An alternate mitigation is instead to set (or drastically reduce) the
lock wait delay during module installation, installation should
normally be entirely uncontended (or infeasible in production with
large traffic) so there is limited reason it'd be waiting several
seconds on a lock. Conveniently, this means instead of the thread
being killed entirely, the install request gets aborted *and retried*,
so it can succeed a little more slowly if that allows the other
request to complete and no other concurrent request causes the same
issue.

Other alternate mitigation which got discarded: reusing registries
when creating new environments (from existing ones) if the database is
the same, that works for some case of switching environments, it
doesn't work for other where we actually fetch a registry e.g. assets
generation calls `get_modules_order` which calls `module_boot` which
calls `module_installed_bypass_session` which gets a
registry. `get_modules_order` is the last place we know we have an
existing registry. Though maybe we could strip out the entire thing
and call `module_installed(self.env)` directly?

Issue 2581648

closes odoo/odoo#73906

X-original-commit: ab84d970dcf1a9dbd5697b6600930cd1bcba3634
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2021-07-16 15:58:16 +00:00
Stéphane Bidoul cf7a21d733 [FIX] core: install new dependencies of module to upgrade
When a custom module is in 'to upgrade' state,
and the code has a dependency that is not yet
installed, Odoo refuses to upgrade it, and
says the new dependency is unmet.

This commit fixes this by also calling button_upgrade() in this situation,
and not only for modules in 'installed' state.

This situation arises in a version migration scenario. Custom modules are
in 'to upgrade' state after migration.
If one of these custom modules has a new dependency
after migration, it refuses to upgrade.

closes odoo/odoo#72942

X-original-commit: d5ffe0159ada953985a23c29e36763599bd10ed9
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
2021-06-29 13:46:07 +00:00
Denis Ledoux b06e4454d5 [FIX] registry: check_foreign_keys, constraint names are limited to 63 chars
When computing the foreign key name,
`check_foreign_keys` didn't take into account the limit of 63 characters
for constraint names.

Because of this, some constraints were dropped and recreated
over and over while they were correct, during install and upgrades.

For instance, when installing `base`
when adding the foreign key for which the name was computed
`base_partner_merge_automatic_wizard_res_partner_rel_base_partner_merge_automatic_wizard_id_fkey`
Postgresql created the constraint under the name
`base_partner_merge_automatic__base_partner_merge_automatic_fkey`
and therefore, as the name did not match,
the constraint was dropped and re-created.

closes odoo/odoo#72234

X-original-commit: 43a4738ebf8a74a389b99f8f58330b3044beaa0c
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
2021-06-16 13:15:26 +00:00
Alvaro FuentesandChristophe Simonis 0a96e7b90c [FIX] core: correct imports from odoo.addons.base.maintenance.migrations
This legacy package was supposed to be an alias to `odoo.upgrade`.
However, depending on how your import its sub-packages (and in which
order), we were ending with the module being loaded multiple times,
breaking the expectation of a singleton.

```python
In [1]: from odoo.addons.base.maintenance.migrations import util as m1

In [2]: import odoo.addons.base.maintenance.migrations.util as m2

In [3]: m1
Out[3]: <module 'odoo.upgrade.util' from '/Users/chs/devel/odoo/odoo/stable/odoo/addons/base/maintenance/migrations/util.py'>

In [4]: m2
Out[4]: <module 'odoo.addons.base.maintenance.migrations.util' from '/Users/chs/devel/odoo/odoo/stable/odoo/addons/base/maintenance/migrations/util.py'>

In [5]: from odoo.addons.base.maintenance.migrations import util as m3

In [6]: m3
Out[6]: <module 'odoo.addons.base.maintenance.migrations.util' from '/Users/chs/devel/odoo/odoo/stable/odoo/addons/base/maintenance/migrations/util.py'>

In [7]: m2 == m3
Out[7]: True

In [8]: m1 == m3
Out[8]: False

In [9]:
```

Now, with this import hook, we ensure that the modules imported from
`odoo.addons.base.maintenance.migrations` are aliases to ones imported
from `odoo.upgrade`.

```python
In [1]: import odoo.addons.base.maintenance.migrations.util as m2

In [2]: m2.__name__
Out[2]: 'odoo.upgrade.util'
```

closes odoo/odoo#71351

X-original-commit: 0d0458a0f370f872caacac26361f2c4730c2cbba
Signed-off-by: Christophe Simonis <chs@odoo.com>
Co-authored-by: Christophe Simonis <chs@odoo.com>
2021-05-27 15:41:24 +00:00
Raphael Collet 4fb958d086 [IMP] core: group all field_inverses dicts on registry
This makes the union of many dicts into a single dict.

On a registry with 296 modules, this saves 300 kilobytes of memory,
which is about 3% of the registry's memory footprint.
2021-05-10 14:29:43 +00:00
Raphael Collet 02b8c687e5 [IMP] core: squeeze registry.field_depends
On a registry with 296 modules, this saves 1 megabytes of memory, which
is about 8% of the registry's memory footprint.
2021-05-10 14:29:07 +00:00
Raphael Collet a8cbe36948 [FIX] core: make registry.field_depends more robust
When a registry is loading, if a custom field cannot be set up, it will
be removed from the dependencies of the field 'display_name', which do
not exist yet on the registry.  This patch makes sure that the dict
registry.field_depends always exists, even as an empty dict.

closes odoo/odoo#70373

Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
2021-05-04 16:53:26 +00:00
Raphael Collet 81ff2717cf [REM] core: remove optimization sharing fields across registries
The optimization will be reintroduced later in a different form.
2021-05-03 12:33:29 +00:00
Raphael Collet 34d6f87d54 [REF] core: put field.depends on registry and make field.recursive explicit
The attributes field.depends and field.depends_context are problematic
for sharing fields across registries, because they depend on the model's
registry class, which may vary from one registry to another.  In order
to make computed fields shareable, we have to move those values away
from fields.

For the same reason, field.recursive should not be inferred, because its
value may depend on the registry, although it is generally not the case.
Moreover, the flag recursive=True is set on a field when field triggers
are determined (on the registry).  A compute method may be called before
the flag is set (if no update has been done yet), and that can lead to
incorrect computations.

This happened in test TestUsers2.test_reified_groups in module 'base'.
The user groups view was apparently determined without the flag being
set, and the view depends on the recursive field 'trans_implied_ids',
which was not correctly computed.

We thus force developers to be explicit about recursive computed fields.
The code now logs a warning when the flag is not set up properly.
2021-05-03 12:33:29 +00:00
Raphael Collet cc7fbb47ae [TMP] registry actual load time 2021-05-03 12:33:29 +00:00
Xavier-Do 4044e46861 [IMP] core: make compute order deterministic
CRM install query count can vary from one execution to another, leading
to difficulties when analysing performances evolution.
The main reason for this is that some compute methods were called in
different order. Even if compute order shouldn't have any effect on the
final result, making it well defined will help finding other causes of
non-determinism.

The initial observation was that sorting Environment.fields_to_compute
leads to a fixed number of query when installing crm.

The main cause of non-determinisim is the usage of `set` impacting
Field.compute_value and BaseModel._modified_triggers.
Transforming all these `set` to `OrderedSet` solves the problem.

The query count is now deterministic when installing a database from
scratch, but not when updating a database with -i crm.

OrderedSet is also slightly optimised by using a dict instead of an

closes odoo/odoo#68692

Ordereddict: dict order is deterministic since python3.6
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2021-04-02 15:29:12 +00:00
8cc066173d [IMP] *: Improve assets management
This commit changes the way assets are declared in Odoo modules.

Before: assets were declared in template files. Template bundles were
generated from primary templates, so technically any qweb template could
have been called as an asset bundle, with the 't-call-assets' directive.

Being standard qweb templates, they had access to standard HTML tags
(script, link, with or without raw scripts or style definition), qweb
directives (t-call, t-raw, etc.) and could be inherited by other
templates.

Now: assets are defined in the module's manifest and generated by the
't-call-assets' directive.

More information on the new system can be found on the updated user
documentation (see the "JavaScript Reference" section).

Task: 2352566

Co-authored-by: Bruno Boi <boi@odoo.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Lucas Perais <lpe@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Simon Genin <ges@odoo.com>
2021-03-31 13:57:17 +02:00
ioFilippo 0a3c05d18e [FIX] modules: apply override translation option
Translation overwriting was not working when forced by command line
arg --i18n-overwrite

This is due to the change of signature of the method, no longer
relying on the context

Fixes odoo/odoo#67419

closes odoo/odoo#67873

X-original-commit: 44624f5d51a266c4fc37644d3fc36b810e722ee4
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2021-03-15 15:06:10 +00:00
Nicolas Seinlet b404ae6a55 [FIX] registry: avoid dropping indexes
When an index has name 'tablename_fieldname_index', this index is
dropped if the field has index=False.  This lead to dropping a
user-created index or dropping/recreating the index when index=True is
set in a dependent module.  Some info is logged instead.

closes odoo/odoo#67602

X-original-commit: 6a87318df296a11e3300723ca0c8b49c0dcf5fa7
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-03-10 14:56:16 +00:00
Nicolas Seinlet 5fa1256bb6 [FIX] registry: no name in constraint check
When table name is long enough, the foreign key constraint name computed
by odoo and the one by PostgreSQL are different, for the same table,
column and definition, are different. As an example,
base_partner_merge_automatic_wizard_res_partner_rel(partner_id) foreign
key is named
base_partner_merge_automatic_wizard_res_partner_rel_res_partner_id_fkey
in Odoo while it's
base_partner_merge_automatic_wizard_res_par_res_partner_id_fkey in
PostgreSQL. This difference trigger a useless foreign key drop/create.

closes odoo/odoo#67601

X-original-commit: 353b415c74da057d5e81cce4d309bebb5f0f2927
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-03-10 14:55:59 +00:00
Alvaro Fuentes 8aa4f42442 [IMP] tests: add test_sequence order for tests
We have some tests in odoo/upgrade that are sensitive to the order on
which they are executed. Specifically: IntegrityCase tests need to be
run after all UpgradeCase tests across all Odoo modules.

To support this we implemented a sorting mechanism for tests based on
the test_sequence class attribute. This is intended to be used by meta
cases, not by individual tests.

closes odoo/odoo#66521

Related: odoo/upgrade#2184
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
2021-02-19 12:51:00 +00:00
luz paz c9e29e5917 [FIX] *: correct typos
Various user facing an non-user-facing typos
Found via `codespell`

Closes odoo/odoo#65648

Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2021-02-19 13:20:48 +00:00
Olivier Dony 12225d5c4f [FIX] registry: prevent inherited phantom cache clears
This patch complements the previous one by ensuring that any
`cache_invalidated=True` flag inherited from the master process
(pre-fork mode) cannot trigger a cache clear.

This could occur when the first request is served, because the flag was
never clear in the master process, which never server any request.

At the end of `check_signaling()`, the local cache has either been
cleared because a (real) increment of the cache sequence was detected,
or it is considered still valid. The final state of the
`cache_invalidated` flag should reflect this, by being `False`.

closes odoo/odoo#65346

X-original-commit: 3585c2c38955ece4292da77de7173fb31a6992ba
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-02-01 14:30:08 +00:00
Olivier Dony 654052d5a5 [FIX] registry: do not signal a phantom cache clear on load
During loading, the registry clears all `ormcache` data multiple
times, in order to ensure consistency with the newly loaded module
data.

Since 083c70bbb6, this was done by
calling `self.clear_caches()`, with the side-effect
of signalling to all other worker processes that the cache
*needs* to be invalidated, which is actually untrue.

If the other workers have any reason to reload their own registries,
they will also clear their own cache in the process - there is no
need to forcefully invalidate it globally.

One could think that combining the pre-fork mode with the `-d <db>`
parameter would mitigate this issue, by making all workers inherit from
a fully loaded registry, In reality it doesn't work, because they also
inherit from the `cache_invalidated=True` flag, that was never cleared
in the master process. So despite having a fully loaded registry, the
newly forked workers will signal a cache invalidation upon serving
their first request.

Further, in a multi-tenant setup with large numbers of databases,
registries may be recycled and loaded much more frequently than
new workers are starting, due to the limited registry LRU, amplifying
this effect a bit.

~~

This patch directly clears the cache LRU without going through
`clear_cache()`, avoiding setting the `cache_invalidated` flag of the
registry, and thus not signalling to other workers.

This is similar to what was being done before 083c70bbb6,
where the LRU was dropped like all other lazy properties.

X-original-commit: 87aef4e3a36d92462454f51960abf7215c5ab7f1
2021-02-01 14:30:07 +00:00
Christophe Simonis 8d5aaaa0e2 [FIX] core: check module state inconsistencies after end upgrade scripts
Some modules may be removed by the upgrade scripts with the help of the
ORM and are done in `end` scripts.
This is the case for uninstalling the themes which use the `_theme_remove`
method [1].

[1] in 12.0: https://github.com/odoo/odoo/blob/e2084a4356f63249920d8c777e92f1710be8b5a6/addons/website_theme_install/models/ir_module_module.py#L337

closes odoo/odoo#64219

X-original-commit: e5ab5410dbc006fc4bcdd21e603026483bf5d360
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
Signed-off-by: Christophe Simonis <chs@odoo.com>
2021-01-07 15:24:27 +00:00
Julien Castiaux 6a6077b313 [FIX] module.py: Remove leftover "active" from manifest
The "active" field is a non-working deprecated alias to "auto_install",
it does not work and was confusing users (see #59850). It has been
removed.

closes odoo/odoo#62086

Task: 2361729
Signed-off-by: Julien Castiaux <Julien00859@users.noreply.github.com>
2020-11-23 12:41:52 +00:00
Hardik Prajapati 584c9fe5cc [FIX] registry: transitive dependencies of custom fields may not exist
Currently in 13.0 when creating a new model through studio and convert
the x_name field to a computed fields with a dependency set on a
custom field from a native model, user get a Key_error when upgrading
or installing a new module

due to the custom field with an invalid depends raise error through a
transitive dependency.

The loading of the registry completely fails,
because the loading of the field custom_field raises a `KeyError` exception
in `def transitive_dependencies` @ `dependencies[field]`
it happens here because the custom_field was skipped at
`dependencies[field] = set(field.resolve_depends(model))`

task - 2366502

closes odoo/odoo#61663

X-original-commit: 92f6908bae4a6678f76a3ce9e29ac3907803ceb2
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-11-12 11:54:11 +00:00
Raphael Collet 9e6df0fb71 [FIX] core: reinstall hooks after setting up models in registry
Before this patch, adding a field on a custom model discards all
automated actions on that model.  The explanation is relatively simple.
When models are set up in the registry, the classes of custom models are
dropped then recreated.  Given that automated actions are implemented as
monkey-patches on model classes, the setup of models simply loses those
monkey-patches, which explains why they stop working on custom models.

The fix introduces an `_unregister_hook()` method, that is expected to
clean up what has been done in `_register_hook()`.  When the registry is
ready (i.e., not being loaded), the setup of models first invokes
`_unregister_hook()` on models, proceeds with the setup, and finally
invokes `_register_hook()` to reinstall the hooks.

OPW 2362308

closes odoo/odoo#60833

X-original-commit: 67152bf82da2674179297d32e4cec9dd534fa0c9
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-10-27 13:59:20 +00:00
Xavier-Do c24c2338ac [IMP] loading: check missing ir_model_access per module
Since e1a5ed51db, missing ir_model_access are warned at the end of an install.
Unfortunately, it is still possible that a module add a model and another module add the corresponding ir_model_access.
Since runbot install all module at once, this won't be spot until a single module build is ran when each module is
installed independently.

This commit proposes to move the check at the end of each module.
This commit also format the log in orther to ease copy/paste of proposed rules in case of multiple new models
and add module to xmlids.

Note that the log may be repeated multiple times if multiple modules redefine this model.

Linked to #59193

closes odoo/odoo#59213

Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2020-10-06 16:27:26 +00:00
Xavier-Do 4da3f9cf1c [FIX] base: avoid warning when computing desc of to_buy modules
post upgrade tests will trigger 'module not found' warning when testing modules views
because of 'fake' modules without real file path.

closes odoo/odoo#56335

Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2020-08-21 16:07:00 +00:00
wanandrco-odoo f2ceef0e2f [IMP] core: add models defined by a query instead of a table/view
By adding a parameter `_table_query` on the Model, we can now have views
that depend on the context.  The query is used instead of the table name
in ORM operations.  This allows to pre-compute some values to improve
performance, instead of storing context values in the database.

Co-authored-by: william-andre <wan@odoo.com>
Co-authored-by: rco-odoo <rco@odoo.com>
2020-08-20 07:45:18 +00:00
Xavier Morel a3ec322993 [IMP] core: tests reporting
* remove useless OdooTestRunner
* don't log results & time per-file, log a module-level tally instead
* add number of tests to post-test results
* generate a single test suite per module (see note)
* use the previous item to split out the at_install test-running in
  two steps: generating the suite for the module then running that
  suite, this way for modules which have no test, or for
  which all tests have been deselected by test tags, we can avoid some
  of the setup necessary to prepare for running tests but possibly
  quite expensive (e.g. `setup_models`)

Note: single test suite per module

I wanted to stop creating a test result for (essentially) every file
in the module, however because of the class-level ``addCleanup``, a
TestResult can't be reused by independent suites:

In order to run class-level cleanup, the test suite checks between
tests if the test it's *preparing* to run is in the same class as the
last test it ran, and if not applies the class-level cleanup.

The problem is that the "previous test class" is stored on the result
object, which is never cleaned up, and the "between tests" check is
really performed *before each test*.

This means when reusing results across suites it will run the
class-level cleanup at the end of one suite and immediately at the
start of the next, which will cause issues if class-level cleanups are
not idempotent (thankfully ``TestTestCursor`` has a non-idempotent
``tearDownClass` which let me discover the error).

Possible fixes are:

* don't reuse results
* clear the relevant states / attributes between suites
* put individual suites in a Big Suite for running

The latter seems simpler: just create a single suite for the entire
odoo-level module instead of creating one suite per test module.

Note to the note: the case of nested suite is taken in account, the
"end of suite" cleanup only runs at the end of the top-level suite, so
technically we don't have to unwrap suites for *that* purpose, we're
doing so in order to filter the test cases inside the suites. But
maybe we could integrate this feature to the suites themselves...

closes odoo/odoo#55185

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2020-08-19 14:08:21 +00:00
Xavier Morel c1c43bbe38 [REM] core: assertion reports
That's a not-very-useful subset of OdooTestResult, so:

* make results merge-able (aka add ability to update a result with the
  contents of another)
* remove support for test data files, and transmission of the
  assertion report thing through the data-files loading
* replace "legitimate" uses of assertion report by test result
* have run_unit_tests manipulate and return a result instead of weird
  flags & ternaries
2020-08-19 14:08:12 +00:00
Xavier Morel ec8a64a85c [REF] core: move testing-related functions to odoo/tests submodules
Attempts to clean up odoo/module and odoo/service a tad, they still
invoke testing-related utilities but are more logical in what
they *contain*.
2020-08-19 07:28:44 +00:00
Julien Castiaux 75b8e39bb2 [IMP] module.py: remove useless pkg_resources jinja hook
The `PackageLoader` jinja's loader purpose is to discover template files
given a python module path. It was necessary to register a special hook
into the import scheme of Odoo to support `import crm`, `import openerp`
and `import openerp.addons` like module path.

Since the support for those old module paths is deprecated since v13 and
the jinja's team shows desire to remove support to `pkg_resource` utils
as highlighted by #50552, it is better to remove it.

closes odoo/odoo#53515

Task: 2282681
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-08-17 11:14:45 +00:00
Xavier Morel 083c70bbb6 [IMP] core: replace dedicated uid cache by ormcache
Before this, invalidations to the UID cache is not synchronised
between workers because it's an ad-hoc solution (so a user changing
their password or an admin disabling a user would only lock out an
attacker currently using the API of one of possibly several
workers). Shift the entire thing to ormcache which already has proper
support for synchronising cache invalidation between workers.

Also simplify the cache invalidation mess in Users.write because the
caches have been unified into a single registry-level LRU, so the
half-dozen cache clears on specific ormcached methods & models is
pretty much the same as repeatedly calling clear_caches on the current
model.

**However** registry.cache is trivially accessible from server actions
and safe_eval as long as they provide access to a model (through
`model.pool.cache`). Which is common, and an issue given we're very
much putting sensible data in there.

Fix this by renaming `Registry.cache` to `Registry.__cache`, this
requires few editions and mangled names are not accessible from
safe_eval contexts.

The alternative would have been to add more bespoke handling of the
uid cache to hook it into the cache invalidation propagation
machinery.

After discussion with (@)odony, fixing LRU access and using that seems
cleaner and less error-prone.

Note on lazy_property
=====================

Make Registry.cache / Registry.__cache into a regular attribute: the
overhead of the LRU is not that high (compared to that of the registry
itself), it's rare that we *don't* need it, and it's assumed to be a
persisted attribute (it's not just a cache) so making it a normal
attribute seems fine; and lazy_property doesn't work for mangled
names: the name of the property is mangled using the name of the
definition class, but the name of the symbol (fget) is not mangled so
lazy_property would set the __cache attribute but then Python would
lookup _Registry__cache, creating a new cache every access.

And we can't (always) mangle things correctly on `__get__(obj,
owner)`: `owner` is just `type(obj)`, meaning in the case of
inheritance the type we get is the type through which the property is
accessed rather than the one it's defined on. So it would work in the
cases where no inheritance is involved (such as Registry.__cache) but
not in general (lest we want to play around walking the MRO ourselves
to find the definition source, which doesn't seem worth it).

lazy_property *could* be made to work properly on Python 3.6+: the
descriptor protocol gains `__set_name__(name, owner)`, which is called
with the properly mangled name — and with the definition class to boot
(though there might still be issues when overriding lazy properties as
the override will be mangled & named differently... or maybe that's a
feature?). However we're still supporting 3.5 at this point, AFAIK, so
that's not an option. Plus it feels unnecessary / not very useful.

However add an assertion to `lazy_property` so it signals when we try
to use it on a mangled method (as otherwise it kinda sorta work in the
sense that the property / object is accessible but is in effect a
slower way to write a regular property).
2020-08-14 23:03:27 +00:00
Adrian Torres 422ca9563e [FIX] core: apply post-constraints only if necessary
This is a followup of commit bc2bb5e03c2b32d4ee1b0597ea5889c17d2b0e0e

When a module is updated, a constraint application may (temporarily)
fail because the existing data does not respect the constraint, this is
OK and can be fixed through hooks/migration scripts and was handled by
the aforementioned commit.

However when updating multiple modules, it is possible that an
inheriting module will try to re-apply the failed constraint and
succeed, if that is the case, when processing the `post_constraints` an
already-existing constraint will be applied and raise an error.

To fix this, a check is made before trying to apply the constraint, to
verify that it is not already in _constraint_queue, if it is not, then
we may attempt to apply it, if it is in the queue, then we may safely
ignore it as it will be applied further down the registry cycle.

closes odoo/odoo#55725

X-original-commit: 5225b9ce5178302af05b63029fb184e27b781815
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
2020-08-11 08:34:37 +00:00
Xavier Morel 92903e22f8 [IMP] core: reporting after tests
Currently there are a few issues with testing reporting (at the
command-line):

1. there is a global report after at_install tests, but it gets
   "scrolled off" by long post_install tests, and is thus easy to
   miss
2. with test tags, it's easy to fat finger a typo and run 0 tests,
   which look like everything's running fine (no failure)

To improve this, print a global report at shutdown (in
`--stop-after-init` mode if tests are enabled) which recapitulates the
test results *and prints a warning if no tests were run at all*.

Also update the reporting collection to make this more reliable:

* have `run_unit_tests` return `None` if it has run no tests, the
  assertion reporting machinery counts this as neither success nor
  failure which is exactly what we want
* have load_test only report a success *if files were actually
  loaded* (by having `load_data` return that information)

Task 2301268

closes odoo/odoo#54812

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2020-07-27 09:30:51 +00:00
Julien Castiaux e9859a0979 [FIX] module.py: Remove useless path initialization
The `initialize_sys_path` is the function responsible of getting the
custom Odoo import hooks to work, i.e. addons import via
`import odoo.addons`. This function is called by some other module
related functions to ensure the paths are correctly setup. We are
confident it is useless to re-initialize the path in many places.

The `load_openerp_module` function is called during server bootup by
both `odoo-bin server` and `odoo-bin shell`, both command parse the
configuration before starting the server which initialize the paths
already.

Most call to `get_module`, `get_module_path` and `get_resource_path` are
done in models or controllers where a registry is setup already. There
is one notable exception which is the subcommand discovery done during
the bootup, for that specific case, we initialize the paths with a
partially loaded configuration.

closes odoo/odoo#49715

Task: 2200956
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-04-17 13:23:04 +00:00
Xavier-Do dbf4060649 [IMP] tests: allow to run at_install tests without update
Debugging/improvement of an at install test may be tedious because of
the need to update the module, spending most of the time checking
tables and xml file.

1. This commit proposes to allow to execute test without installing or
updating a module. The test is still executed during the loading, and
the behavior should be close to an execution of tests during an update.

Co-authored-by rco-odoo <rco@odoo.com>

2. keep previous behavior if -i or -u is given

Three solutions were possible:
- The clean one that changes dev habits.
When test-enable or test_tags is given, all tests are always executed,
a test_tags is needed to select tests to execute:
Example: `-u module --test_enable` becomes `-u module --test-tags /module` to keep the same behaviour
This solution is the simplest, and executed tests does not depends on database already installed modules.
- The conservative solution.
When giving -i or -u, the behavior stays the same as before. When giving test-enable
without -i/-u, test are executed on all installed modules.
- The intermediate solution:
When no test_tags is given but a -i and -u is given, only the given modules are tested.
This is quite close to the second solution except that a -i module on a new database won't
test all dependencies on the first install.

The chosen solution is the second one to minimize changes on dev old habits,
only an almost unused feature is impacted: using test-enable without any -i or -u.
Before this pr only post install tests were executed in this case. Now at_install tests are also executed.
This combination is actually used by runbot to execute post_install test in parallel, but a `--test-tags -at_install`
tag is given so nothing to worry about here.

closes odoo/odoo#53499

Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-07-09 10:01:45 +00:00
Paul Morelle 8a94f62e08 [FIX] odoo: stop bloating sys.meta_path
Every call of initialize_sys_path was adding two new hooks to the
sys.meta_path, resulting in very long loading times on databases having
a lot of modules.

For example, 2.27s instead of 752 on a database having 130 installed
modules.

References:
- odoo/odoo#45780
- odoo/odoo#45662

closes odoo/odoo#53121

X-original-commit: 2444fde7f852787d87589a93c4bc385d76ff20e9
Signed-off-by: Christophe Simonis <chs@odoo.com>
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
2020-06-17 08:49:29 +00:00
Christophe Simonis 8ad7e7cb91 [FIX] core: read model from field in field_compute
Oversight of "simple refactoring" in 634775bff6d9eba9d4548cc801071a942895a719

closes odoo/odoo#51158

X-original-commit: 046b0dedda8f43e4ae13958a34a446e8a73c8d3f
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-05-13 11:19:44 +00:00
Denis Ledoux 9d2ca69377 [FIX] registry: transitive dependencies of custom fields may not exist
This is related to
826c86e9ab31963e410887a30326f45bcfadf5ea

The case is the same,
a custom field with an invalid depends,
except that this time its through a transitive dependency.
e.g.
custom_field_2 depends on custom_field_1
custom_field_1 depends on unexisting_field

The loading of the registry completely fails,
because the loading of the field `custom_field_2` raises a
`KeyError` exception in
`def transitive_dependencies` @ `dependencies[field]`
because the `custom_field_1` was skipped @ line
`dependencies[field] = set(field.resolve_depends(model))`

Landing in a state where the server can no longer start at all,
and the user can't therefore solve its custom field himself
to repair the situation.

closes odoo/odoo#51057

X-original-commit: 7b642884cc4d643a5a998b4639bf26b4e81cc46e
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
2020-05-11 15:23:25 +00:00
Julien Castiaux 47a1ae580f [REV] module: bring back openerp import hook
Use `warnings.warn` to log a warning entry on usage of deprecated
import hook instead of `logging.warning`. The `warnings` can be more
easily configured to show/hide class of warnings or to limit warning
emission, plus it is possible to log a single stack entry whereas
logging can just log the entire call stack.

Bring back the various openerp import hooks by reverting 9e1f13bac12

closes odoo/odoo#50604

Task: 2234749
X-original-commit: 5840202802c2ff6ca1ca8fd6f3892900481db5da
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Signed-off-by: Christophe Simonis <chs@odoo.com>
2020-05-04 16:05:26 +00:00