odoo/odoo#111651 improved and optimised triggers but dropped the
in-place cleanup of field dependencies. As a consequence, during
module uninstallation if a stored computed field is removed (because
it's part of a module being uninstalled), and one of its dependencies
is subsequently altered (e.g. it's itself removed, or written to) the
second update will break as the query trying to find out which
dependent records to update will error, either because of trying to
select / filter on a missing column, or because of trying to fetch
in a missing table.
The simplest examples of this issue are computed fields with a
dependency on `ir.model`:
- In `calendar`, `calendar.event.res_model` is a related on
`res_model_id.model`, this prevents the removal of *any* `ir.model`
record if it gets uninstalled.
As a result the `calendar.attendee` and `calendar.event` tables
don't get removed (just emptied of all their non-automatic fields),
their records remain as well, and when the non-automatic fields get
re-added during installation re-instating the NOT NULL constraints
fails, breaking the uninstall/reinstall test.
- In `payment`, `payment.provider.module_state` is a related on
`module_id.state`, this breaks *during* uninstallation, as after
`module_uninstall` first calls `_module_data_uninstall` which
removes the field, then it *updates the modules being uninstalled*
(sets their state), which tries to find out which
`payment.provider`'s `module_state` is should update, which breaks
because the `module_id` column has been removed.
This second one was worked around in odoo/odoo#118900, by marking
modules as uninstalled before actually gutting them, but as it turns
out the "actual" fix is needed anyway. So revert the workaround, and
actually fix the issue.
closesodoo/odoo#119130
X-original-commit: 48a420efcf7c7b46416bab006003553cc9d23846
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
The TriggerTree class does not have a specific __repr__(). It thus
falls back on dict's __repr__(), which does not show the root of the
tree. This makes debugging hard and confusing.
closesodoo/odoo#113521
Signed-off-by: Raphael Collet <rco@odoo.com>
Odoo Test environments requires to modify many parts of the unittest
TestCase, Suite and Result.
The main initial reason is to **avoid to postpone result at the end of
the test suite**, because even if it is convenient to have all errors
visible after the tests in some case, odoo logs adds information during
the execution that can be useful to debug when a test fail, to have
context for an error. (see **OdooTestResult**)
We are also fixing the stack trace comming from a unittest and since
there is no proper way to hook inside the TestPartExecutor, a dirty hack
injects anoter result on the outcome to manage the error and complete
the stack trace. This was also a way to avoid to postpone subtest logs
at the end of the test case (see _ErrorCatcher)
`_feedErrorsToResult` was used to test the test suite behavior since
there are many customization and this is quite fragile, especially if
unittest changes behavior in other python version.
**Python 3.11** introduced python/cpython#664448d8 That, in a way, goes
in the same direction of the changed introduced with _ErrorCatcher:
immediately feed errors to resut instead of postponing it. But this also
removes `_feedErrorsToResult` that was used to test this behaviors, as
well as other ones.
Since odoo should remain multi-version, this amount of changes on the
initial behavior become to complicate to keep cross-version and the
(already in our mind for a while) solution to **vendor unittest** will
help to simplify most of our test code base.
This commit modified the vendored unittest files to simplify them as
much as possible to suite our needs.
Since the runner is still the unittest one, we need to inherit from
unittest.Testcase in order to have the right type.
This also means that we still have access to all TestCase methods
without overriding them all. This is convenient for assertion methods as
an example but the initial idea is to vendor our own version of TestCase
to avoid having trouble to adapte our miscommunications to future python
versions. A trade-off must be done to chose what should remain in our
code base. The idea is to keep logic closely linked to our changes in
our code base, mainly around the run method, but also addClassCleanup
wich need to be vendored for python 3.7, but assertions methods are
independent. Any logic can be moved fom unittest to our
vendored version in the future if needed.
X-original-commit: 9a5d1ea54be49e4cc8208c33e76a6bbd2414d5d0
Part-of: odoo/odoo#113850
Consider field F in module X with parameter translate=False, and F is
overridden in module Y with parameter translate=True. During the
upgrade of module X, module Y hasn't been loaded yet, and the ORM
considers the field to be `translate=False`. Therefore it converts its
database column from type jsonb to varchar, and accidentally drops
non-en_US values:
{"en_US": "English value", "fr_FR": "French value"} (jsonb)
-> 'English value' (varchar)
As a result, translations are lost after upgrade.
This commit fixes the bug by checking whether the field is translated in
database and patches the field accordingly when loading the registry.
This avoids the ORM considering the field as non-translated while
upgrading modules.
In order to "force" translated fields to become non-translated ones, at
the end of the loading process the patch above is discarded, and fields
are checked again. We then adapt the schema of models that have such
fields. This extra step handles the uninstallation of modules like
module Y in the example above.
The patching of the fields has one potential issue. While upgrading
module X, field F is patched with translate=True. If module Y actually
overrides F with translate=xml_translate or so, this may cause the
behavior of the upgrade to be slightly incorrect. Because of the
complexity, we have chosen to not support this case.
closesodoo/odoo#112223
X-original-commit: 1e6e482a9763baa5fae70d9b6676d16a46458f4a
Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: Wang Chong (cwg) <cwg@odoo.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
The class is a simple extension of dict, and adds an explicit attribute
for the content of the root node of a tree. It makes the code much more
readable with very small performance overhead.
closesodoo/odoo#111946
X-original-commit: 8a01d74e5f7d035cfd05bc02596f075270e0fcf8
Signed-off-by: Raphael Collet <rco@odoo.com>
This patch optimizes the way field trigger trees are computed. Overall,
the resulting trigger trees are mostly identical, but they can now be
determined one by one, which enables an on-demand approach and partial
cache.
Before this patch, getting the first trigger tree proceeded as follows:
- resolve the dependencies of all fields;
- compute the transitive closure of the dependencies of all fields;
- store the transitive closure above as field triggers for all fields
in a cache.
After this patch, getting the first trigger tree proceeded as follows:
- resolve the dependencies of all fields;
- cache them as direct triggers for all fields;
- compute one trigger tree as the transitive closure of the field's
triggers, and cache it.
This optimization is quite effective during the installation of modules,
and is even more effective when the number of fields is large. For
instance, a complete installation with all community modules is now 25%
faster. For a complete installation with all enterprise modules, the
installation time is even 30% less! A medium installation is about 16%
less time.
The optimization also speeds up the first request on a new Odoo worker,
since the minimum time for computing a handful of trigger trees is much
smaller than before. We have measured times for a first request going
from 1.6 seconds to 1 second for posting a message.
We have observed slight differences in trigger trees, but they occur in
places where the tree has redundant branches, in particular with fields
having recursive dependencies. It therefore makes no difference in what
is being triggered or invalidated.
X-original-commit: 68f786d494c3c73a085cd919b348c019f77794e7
Part-of: odoo/odoo#111946
Those APIs are aimed at hiding the implementation of trigger trees,
dependent fields and fields modifying relations. Explicit APIs simplify
the profiling of executions and comparison of implementations for
building trigger trees.
X-original-commit: d12b9270375634e738f5288d0c523ac0eec2fa18
Part-of: odoo/odoo#111946
Seems unnecessary, most of the information already lives in
`sys.modules`. We can just check that.
There are a few changes in behaviour, but they seem minor:
- if post_load fails, subsequent attempts to load the module will
"succeed"
- since we didn't remove/reload the module, a failure because of an
incorrect post_load wasn't fixable, however it was possible to
update the manifest
Still seems like a wonky state to be in, and one we should ignore.
Also remove the logging of the error: since we're re-raising as-is,
the parent logs it with a traceback, so this is unnecessary and
redundant.
closesodoo/odoo#103933
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This is mostly a cleaning/refactoring change.
The current API for init hooks (pre, post, uninstall) is to pass
`cr, registry`.
But the first thing which was done by most
post init and uninstall hooks was to create an env using
the cr passed
e.g.
`env = api.Environment(cr, SUPERUSER_ID, {})`
and the `registry` argument was unused in all these hooks,
completely.
By changing the API of hooks to pass `env` instead
of `cr, registry`, we gain in average two lines in every
hooks:
- the line creating the env `env = api.Environment(cr, SUPERUSER_ID, {})`
- the line importing `api` and `SUPERUSER_ID`
Therefore removing ~250 lines of repeated code lines accross odoo/odoo and
odoo/enterprise.
In addition to these lines removed,
it also ease the API of init hooks for Odoo developers,
who are used to that `env` and not so much how to create an `env`
from a cursor.
Part-of: odoo/odoo#108254
The goal of this revision is to re-use the environment among the
different steps of the registry loading,
instead of creating a new environment for each step.
1. Simply To avoid to repeat the line
`env = api.Environment(cr, SUPERUSER_ID, {})`
multiple times in the code
2. This also allows to share the context among the different
steps. This is not yet used in this revision, but it could
be, for instance to avoid the current repetition to add the keys
`install_module`, in `convert_csv_import` and `xml_import._tag_record`
Part-of: odoo/odoo#108254
Don't limit on the first directory found in the upgrade-path.
It follow the same behavior regarding scripts found in the `maintenance`
directory and the ones in the local `upgrades` directory of modules.
opw-2868713
closesodoo/odoo#111087
X-original-commit: d2e6c9d5010ab8092eff37775e92b486f89d28fc
Signed-off-by: Christophe Simonis <chs@odoo.com>
Keep the manifests as light as possible, to easily see custom behavior/content.
Complete the work of previous commits cleaning the manifests content:
* 42bad1a6d2
* ef7005f524
and make sure this kind of cleanup commit is not necessary in the future
because it is now automatically verified by a dedicated test.
closesodoo/odoo#107735
Related: odoo/enterprise#34903
Signed-off-by: Julien Castiaux <juc@odoo.com>
The existing code was generating misleading errors for imported Odoo
modules that could not be loaded. Although there was a specific hack
for module 'studio_customization', imported modules were not handled
properly. This patch adds the right condition in the SQL query in the
module that introduces imported modules.
closesodoo/odoo#106098
X-original-commit: e1cfc1f74000e55473f7a26f0df5a13c4d5094c0
Signed-off-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
Signed-off-by: Raphael Collet <rco@odoo.com>
There are two issues with the index naming convention used by the ORM:
Problem 1: it is possible to have naming conflict for indexes. For
instance, the name 'slide_channel_tag_group_sequence_index' is used for
both fields slide.channel.tag.group.sequence and
slide.channel.tag.group_sequence. Only the first index will be created.
Solution 1: we separate the model and field names with a double
underscore instead of a single one, which is the same strategy as with
LEFT JOIN aliases. This is correct because model names don't contain
such double underscores or underscores as prefix or suffix (it is not
forbiden but model name should follow the 'dot notation'.)
Problem 2: index names can be longer than 63 chars, but PostgreSQL
silently truncates it. This doesn't actually break anything (PostgreSQL
also truncates values when we check the existence of indexes) but it can
lead to using the same name twice. There is hopefully not any example
in our code.
Solution 2: if the name is too large, we truncate it and pad it with a
hash of the complete name to match 63 characters, which is also the
strategy used for LEFT JOIN aliases.
task-2984730
closesodoo/odoo#100736
Related: odoo/upgrade#3957
Signed-off-by: Raphael Collet <rco@odoo.com>
Loading an non-existing addon directory affect all other modules to be
not loaded. This commit makes sure the path exist before proceed to
explore all the modules under that directory.
closesodoo/odoo#104704
X-original-commit: d77d9f8a9ff945f5f61924eda835c877eb4f281c
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
`__manifest__.py` was introduced in Odoo 10 and quickly migrated
to (c758e9043a fixed the last holdouts).
Deprecate old manifests. People who need the compatibility can just
add a symlink (or duplicate the file if they're working on FAT or an
old os where core.symlinks can't be set to `true`).
closesodoo/odoo#103952
Signed-off-by: Raphael Collet <rco@odoo.com>
Before this commit the neutralize system introduced in v16 was using ORM
methods in order to change appropriate records. Although flexible, this approach
could lead to call some methods with side effects while neutralizing
(eg: overloads of write).
This patch converts the neutralize system to a safer "inert" SQL based approach
by migrating the generic method _neutralize to SQL files exposed in the
data folder.
Task id: 2961687closesodoo/odoo#102792
X-original-commit: e5dbded9bb363351feff7ca8a56c7f8a6860f492
Related: odoo/enterprise#32580
Signed-off-by: Fabien Meghazi <fme@odoo.com>
The cache currectly fails to correctly invalidate relational fields that depend
on a non-relational field. Two passes of invalidation are done, to reflect
dependencies on both the old and the new written values. In the first pass
only relational fields are considered, as explained in the comments:
> It is best explained with a simple example: consider two sales orders SO1 and
SO2. The computed total amount on sales orders indirectly depends on the
many2one field 'order_id' linking lines to their sales order. Now consider the
following code:
>
> line = so1.line_ids[0] # pick a line from SO1
> line.order_id = so2 # move the line to SO2
>
> In this situation, the total amount must be recomputed on *both* sales order:
the line's order before the modification, and the line's order after the
modification.
The written values can be seen as the roots of a dependency forest (a
collection of dependency trees). Before this commit all non-relational roots
and their corresponding trees were filtered out during the first pass. However,
this approach is wrong, as relational fields can also depend on non-relational
fields. Instead, the complete dependency forest has to be traversed, skipping
invalidation for non-relational fields during the first pass.
The test that was previously included accidentally succeeded because of a
separate and unrelated bug in the orm domain parser: in certain one2many or
many2many leafs the domain parser would not take into consideration the domain
included in the definition of the field. As a result, the test still passed
by accident, because the records that no longer matched the domain after the
write were still invalidated during the second pass.
The problem can clearly be demonstrated, however, when the dependency is
generated by a compute function.
closesodoo/odoo#101038
X-original-commit: d4a5827b42d80f0f830455dcd2056701eb09aed1
Signed-off-by: Rémy Voet <ryv@odoo.com>
Signed-off-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
When a module extends model 'base', the database schemas of all models are
checked, including indexes. And a log message appears for "unexpected index
mail_message_subtype_id_index on table mail_message_subtype". The index indeed
exists, but not for the table mentioned in the message. The ORM actually makes
a confusion between:
- the index mail_message_subtype_id_index for subtype_id on table mail_message
- the index mail_message_subtype_id_index for id on table mail_message_subtype
The fix consists in logging the message about the unexpected index only if the
index is on the expected table.
closesodoo/odoo#100297
X-original-commit: fe8d0024897208e876f097564d50e6795df2c1d3
Signed-off-by: Raphael Collet <rco@odoo.com>
Translated fields no longer use the model ir.translation. Instead they store
all their values as JSON, and store them into JSONB columns in the model's
table. The field's column value is either NULL or a JSON dict mapping language
codes to text (the field's value in the corresponding language), and must
contain an entry for key 'en_US' (as it is used as a fallback for all other
languages). Empty text is allowed in translation values, but not NULL.
Here are examples for a field with translate=True:
NULL
{"en_US": "Foo"}
{"en_US": "Foo", "fr_FR": "Bar", "nl_NL": "Baz"}
{"en_US": "Foo", "fr_FR": "", "nl_NL": "Baz"}
Like before, writing False to the field makes it NULL, i.e., False in all
languages. However, writing "" to the field makes its value empty in the
current language, but does not discard the values in the other languages.
Here are examples for a field with translate=xml_translate:
NULL
{"en_US": "<div>Foo<p>Bar</p></div>", "fr_FR": "<div>Fou<p>Barre</p></div>"}
Change for callable(translate) fields: one can now write any value in any
language on such a field. The new value will be adapted in all languages, based
on the mapping of terms between languages in the old values. Basically the
structure of the value must remain the same in all languages, like before.
Reading a translated field is now both simpler and faster than the former
implementation. We fetch the value of the field in the current language by
coalescing its value with the 'en_US' value of the field:
SELECT id, COALESCE(name->>'fr_FR', name->>'en_US') AS name ...
The raw cache of the field contains either None or a dict which is conceptually
a subset of the JSON value in database (except for missing languages). For the
sake of simplicity, most cache operations deal with the dict and return the text
value in the current language.
Trigram indexes have been adapted to the new storing strategy, and should enable
to search in any language. Before this change, only the source value of the
field ('en_US') could be indexed.
Computed stored translated fields are not supported by the framework, because of
the complexity of the computation itself: the field would need to be computed in
all active languages. We chose to not provide any hook to compute a field in
all languages at once, and the framework always invokes a compute method once to
recompute it.
Code translations are no longer stored into the database. They become static,
and are extracted from the PO files when needed. The worker simply uses a cache
with extracted code translations for performance. This is reasonable, since
fr_FR code translations for all modules takes around 2MB of memory, and the
cache can be shared among all registries in the worker. Changing code
translations requires to update the corresponding PO file and reloading the
worker(s).
Performance summary:
(+) reading 'model' translated fields is faster
(+) reading 'model_terms' translated fields is much faster (no need to inject
translations into the source value)
(+) searching translated fields with operator 'ilike' is much faster when the
field is indexed with 'trigram'
(+) updating translated fields requires less ORM flushing
(-) importing translations from PO files is 2x slower
Some extra fixes:
- make field 'name' of ir.actions.actions translated; because of the PG
inheritance, this is necessary to make the column definition consistent in
all models that inherit from ir.actions.actions.
- add some backend API for the web/website client for editing translations
- move methods get_field_string() to model ir.model.fields
- move _load_module_terms to model ir.module.module
- adapt tests in test_impex, test_new_api
- because env.lang is injected into SQL queries, its returned value is
now guaranteed to correspond to a valid active language or None
- remove wizard to insert missing translations (no longer makes sense)
task-id: 2081307
Co-authored-by: Fabien Pinckaers <fp@openerp.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
During tests on runbot, the main reason tours are slow to start is
because the first loading of "/web" need to generate assets bundles.
Generation can take up to 5 seconds time the number of tour.
Before this, the first requests to /web takes around 7 seconds on
runbot and the next ones less than 1 second.
After this commit, the first request to /web takes around 1.5 seconds
Note that the main difficulty is to choose when to generate the assets.
(With optimisations from following commits) the generation time is
arround 30 seconds (21 css + 12 js) the first time, for all modules.
If the attachements exists the generation time is arround 3 seconds
(2.5 js + 0.5 css) mainly because of globs to find usefull files.
In practice for runbot the ideal would be to generate them at
the end of the install so that it is shared for all post_install builds.
Doint it at the end of an install is not wanted in all cases, saas
pregenerated templates and upgrade may avoid doing that.
Doing it in a special runbot step (subcommand) is not possible for niglty
execution (no split, in one go). This needs to be in the code.
It is also not practical for devs wanting to have the same behaviour on
a local machine.
A solution to make the test conditionnal at install is to base the
condion on an existing test_module. test_assetsbundle is a good
candidate here. On runbot, the at_install step (befor split) will
automatically generate assets with this solution.
Assets are also generated before post_install tests. This should be fast
if they already exists and ensure that assets are up to date after
modifying sources locally or after downloading a database on runbot.
It should be fast enough for small database and may be even faster
in the future for small diffs.
Part-of: odoo/odoo#99176
We added trigram index for char fields since https://github.com/odoo/odoo/pull/83015.
But if `unaccent` is installed in the database (and isn't force to
`False` on field), these new trigram indexes are pointless and cost a
lot for nothing (almost nothing, it still can be used for equality
operator but in this case a btree will be far more efficient).
The simple way to fix it is to add `unaccent(<column>)` in the index
trigram definition, but unfortunately `unaccent` is not immutable and
may therefore not be indexed. In order to make `unaccent` indexable, we
must declare it as immutable (see
https://stackoverflow.com/questions/11005036/does-postgresql-support-accent-insensitive-collations/11007216#11007216
for more information and how to do that).
With this patch, trigram indexes are created with `unaccent(<column>)`
if the function `unaccent` is available in the database, and for the
fields that are not declared with `unaccent=False`. Moreover, we issue
a warning when `unaccent` is available but is not immutable, in which
case most trigram indexes will be useless.
odoo/upgrade#3736
task-2551518
closesodoo/odoo#95943
Signed-off-by: Rémy Voet <ryv@odoo.com>
It's pretty much unused and fairly complicated.
Also deprecate `listdir` entirely since `get_module_filetree` is the
only extant user of the recursive listdir.
closesodoo/odoo#98034
Related: odoo/enterprise#30403
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Because method _read() no longer updates existing values in memory,
those values in memory must be consistent with the database.
On the other hand, if pending updates are not performed on the database
before fetching values, it means that the corresponding database values
cannot be put in cache. This implies that one cannot empty the cache
without flushing the corresponding fields.
In order to avoid mistakes, flush automatically before invalidating the
cache. This makes the invalidation methods safe by default, and avoids
cargo-culting which would systematically associate invalidation to
flushing, which may eventually be less performant.
Part-of: odoo/odoo#66938
This provides a new API for those operations, in order to make the
distinction between the use cases more explicit. The former API was
using obscure parameter combinations to correspond to various cases.
In the summary below, `fnames` is an iterable of field names. If the
parameter is not given, it means "all fields" in the given context.
Note that method recompute() is now mostly private, as it should not be
used in business code.
# process pending computations and updates
records.env.flush_all() # all fields of all models
records.flush_model(fnames) # the fields of all records of the model
records.flush_recordset(fnames) # the fields of the given records
# process pending computations, became non-public methods
records.env._recompute_all() # all fields of all models
records._recompute_model(fnames) # the fields of all records of the model
records._recompute_recordset(fnames) # the fields of the given records
# invalidate the cache of fields
records.env.invalidate_all() # all fields of all models
records.invalidate_model(fnames) # the fields of all records of the model
records.invalidate_recordset(fnames) # the fields of the given records
Part-of: odoo/odoo#87527
This commit is the 14th commit of a comprehensive refactor of our HTTP
framework. See odoo/odoo#78857 for complete historic, discussions and
rationnals.
* `request.uid = x` => `request.update_env(user=x)`.
* `request.context = x` => `request.update_env(context=x)`.
* `request.context = dict(request.context, x=y)`
=> `request.update_context(x=y)`.
* `request.cr = None` => `request.cr.close()`.
* `http.mono_db()` => `request.db`.
* `http.dispatch_rpc()` => `service.dispatch_rpc()`.
* `@service.model.check` => `service.model.retrying()`.
* `request.endpoint`
=> `env['ir.http']._match(request.httprequest.path)[0].endpoint`.
* `request.routing_iteration `=> `removed`.
* `request.jsonrequest` => `request.dispatcher.jsonrequest`.
Note that `request.params` is now set much later in the process. If you
are in a situation where you values from the query string or the
http body you can use `request.get_http_params()`.
Note that using the new `request.future_response`, it is possible to
add headers and cookies on the response object before the response
object is initialized. Please note that headers/cookies saved on
the future response will NOT be injected in case of error.
PR: odoo#78857
Task: 2571224
The possible index names have been renamed "btree", "btree_not_null"
(instead of "not null") and "trigram" (instead of "gin").
Task 2742526
Part-of: odoo/odoo#83274
It's not entirely clear whether `@synchronized` is even useful, but
keep it for now. `locked` is just the default instance of
`@synchronised`.
- rewrite `@synchronized` using `decorator`, don't fold everything
into a single call as there's a potential for parametric conflict
- remove the independent `locked` in `sql_db.py`
- convert `lru` to `locked`
- move `Registry` over to `locked` where applicable
closesodoo/odoo#82718
Signed-off-by: Raphael Collet <rco@odoo.com>
Three supported types:
- btree (default for index=True)
- btree not null (when >90% of the data are null)
- gin trigram search (for char fields)
Review of indexes on all objects.
closesodoo/odoo#83015
Signed-off-by: Fabien Pinckaers <fp@odoo.com>
Those were not accounted for, leading to fstrings passing through
unflagged.
Also update the SQL checker to be stricter but smarter:
The previous version would "fail open", unknown nodes would be allowed
through hence f-strings not being flagged when they started appearing
in arg0 position, should now fail-closed, anything that's not allowed
is forbidden.
This flags a few more cases, all of which seem acceptable upon review.
However the previous version would also only resolve arg0 (in case it
had a `NAME`, to see if that resolved to an acceptable form of
query-building). The new version performs resolution during
`_check_concatenation` and should thus allow e.g. format strings to be
separate variables (though not e.g. module-level constants, yet
anyway).
In resolution, replace the ad-hoc process by astroid's built-in
`lookup` which seems to provide the same information. Slightly more in
fact, as it yields every assignment in case of e.g. conditionals, but
making use of that would require a lot more changes in the checker so
leaving the behaviour as-is for now.
It's important to *not* use `ilookup` here, because ilookup is not
"iterable" but "inferring", and we don't want values, we want
expression ASTs for analysis.
NOTE: previous improvements as well as fixes to existing code were
only implemented in 14.0, hence this being merged in 14.0 not 13.0
despite 13.0 still being supported.
closesodoo/odoo#81721
X-original-commit: 376ccf0944dae1bc53ae9c5385977c4e6b23e083
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
The http.addons_manifest is a map {module: manifest_dict} that is
populated upon the first http request. This map is basically a module
manifest cache with an extra `addons_path` key, the path of the module
on the file-system. This cache is eagerly populated upon the first http
request, the map is empty in non-http contextes (e.g. cron) which have
been a source of bugs (e.g. 50c8eb1).
A manifest cache is necessary because reading and parsing python files
from the file-system is not that cheap but there is no reason that cache
is located in `odoo.http`. A thin cache layer now wraps
`load_information_from_description_file()`/`load_manifest()` and is
lazily populated.
The `http.addons_manifest` have been removed. The extra `addons_path`
key is now present in the "normal" manifest. The `read_manifest()` was
hardly used so it has been deprecated. The only way to retrieve a
manifest is now `load_information_from_description_file()` which was
renamed `load_manifest()` (no cache) and `get_manifest()` (cache).
Side note about performances, the cache is necessary. Addons manifest
are read-only and reading + parsing python files from the file system is
not a cheap operation. Running the e-commerce tour
`@website_sale.test_04_admin_website_sale_tour` without cache on
`load_manifest()` requires 68,29 secs to complete on my laptop,
exceeding the default 1-minute time frame allowed in tests. Using a
cache the time is down to 36,53 secs. The performance impact is huge.
Part-of: odoo/odoo#79977
* add configuration for `flake8[flake8-rst-docstring]`
* enable docstring-related checks
* fix invalid docstrings in odoo's core & `base`
* fix a few more bits (mostly missing or incorrect `:param:` info
fields) are out of scope for the lint but my editor catches
closesodoo/odoo#74604
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
The cursor features a "transaction" object to manage application-
specific data in relation with cursor operations. In its initial
implementation, the transaction object was created by the registry.
This created a requirement: in order to be used in environments, a
cursor had to be created by registry.cursor().
We now remove that unnecessary technical requirement by making
environments create the transaction object on demand.
closesodoo/odoo#80644
X-original-commit: e902713648bca329e6821859462b2128aad62c09
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Until now, stored compute fields were computed after database insertion.
This meant that required fields should not be computed, for instance,
unless some hackish code was added to make it work. Another trick was
to provide some default value, but this actually prevents the field for
being computed after insertion.
This commit provides a field parameter to specify that the field should
be precomputed: adding precompute=True on the field definition force the
method create() to compute its value before inserting the new record in
the database. For the reason explained below, precomputing fields is
not always correct, and therefore the default remains to not precompute
a field.
Some stored fields must be computed after insertion, for instance:
* statistics fields computed with search/read_group/...
* fields referencing the current record (res.partner.commercial_partner_id)
* fields referencing another record that does not exist yet (think about
records created by one2many fields)
* fields depending on the create_date/write_date/create_uid/write_uid
Those fields shouldn't be defined with precompute=True, which triggers
their computation post record creation. This is why, by safety, we
consider the default behavior to be precompute=False.
closesodoo/odoo#80449
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Yannick Tivisse <yti@odoo.com>
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).
closesodoo/odoo#79552
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
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.
closesodoo/odoo#79199
X-original-commit: 8ed3641f81502d3a7e9c9bb93771c6f5601a31a9
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
Signed-off-by: Paolo Gatti (pgi) <pgi@odoo.com>
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.
closesodoo/odoo#78898
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
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`.
closesodoo/odoo#78808
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
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.
closesodoo/odoo#77273
X-original-commit: 28adbfa5a9df9b7754529d45188c0eedeffdf783
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
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
closesodoo/odoo#76869
X-original-commit: a46d20c89c24a4e60faef09cf8ad7721bd29d6cc
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
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.
closesodoo/odoo#76325
X-original-commit: f3afb23cdf21f395855771a037c721e977dc93c8
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>