<feed xmlns='http://www.w3.org/2005/Atom'>
<title>Odoo/odoo/tests, branch 14.0</title>
<subtitle>The current checkout of upstream Odoo</subtitle>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/'/>
<entry>
<title>[IMP] core: clarify docs about config --test-tags</title>
<updated>2021-05-27T07:42:59+00:00</updated>
<author>
<name>Ivan Yelizariev</name>
<email>iel@odoo.com</email>
</author>
<published>2021-05-21T09:39:51+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=e4bf1e7dca2a9ef6dabf3f201d086ae77ff993d9'/>
<id>e4bf1e7dca2a9ef6dabf3f201d086ae77ff993d9</id>
<content type='text'>
Technical name is not added to test_tags since https://github.com/odoo/odoo/commit/95b4f2ab4b5698ab3a28c9c35ac8da6fb6def983

at_install tag is added by default since introducing @tagged decorator: https://github.com/odoo/odoo/commit/b356b190338e3ee032b9e3a7f670f76468965006

Clarify how special tags at_install/post_install work.

Also, add dots for @tagged doc, because otherwise we have a mess in sphinx docs.

---

task-2431630

closes odoo/odoo#71130

Signed-off-by: Victor Feyens (vfe) &lt;vfe@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Technical name is not added to test_tags since https://github.com/odoo/odoo/commit/95b4f2ab4b5698ab3a28c9c35ac8da6fb6def983

at_install tag is added by default since introducing @tagged decorator: https://github.com/odoo/odoo/commit/b356b190338e3ee032b9e3a7f670f76468965006

Clarify how special tags at_install/post_install work.

Also, add dots for @tagged doc, because otherwise we have a mess in sphinx docs.

---

task-2431630

closes odoo/odoo#71130

Signed-off-by: Victor Feyens (vfe) &lt;vfe@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] base: form view emulator: bidirectional definition of 'in' and 'not in'</title>
<updated>2021-04-08T13:16:18+00:00</updated>
<author>
<name>oco-odoo</name>
<email>oco@odoo.com</email>
</author>
<published>2021-04-06T15:00:44+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=73f2e9be09b4e874f0c78b5b08a29c640854b57e'/>
<id>73f2e9be09b4e874f0c78b5b08a29c640854b57e</id>
<content type='text'>
Doing domains like [('something_ids', 'in', 4)] crashed the emulator because it was trying to check something was 'in 4', instead of reversing the check (as real form views do).

closes odoo/odoo#68966

X-original-commit: eb14583442f2729182ffb8ec7b069e2505df3577
Signed-off-by: Xavier Morel (xmo) &lt;xmo@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Doing domains like [('something_ids', 'in', 4)] crashed the emulator because it was trying to check something was 'in 4', instead of reversing the check (as real form views do).

closes odoo/odoo#68966

X-original-commit: eb14583442f2729182ffb8ec7b069e2505df3577
Signed-off-by: Xavier Morel (xmo) &lt;xmo@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[IMP] tests: add data_dir support in test_module_operations</title>
<updated>2021-02-18T07:58:51+00:00</updated>
<author>
<name>Christophe Monniez</name>
<email>moc@odoo.com</email>
</author>
<published>2021-02-17T15:36:24+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=781c91784a0a997967a0152dca2c59a0cb2bab74'/>
<id>781c91784a0a997967a0152dca2c59a0cb2bab74</id>
<content type='text'>
In some situations, like during tests on runbot, the data-dir location
may vary.

With this commit, the `data-dir` CLI argument is added to the
test_module_operations script.

closes odoo/odoo#66422

Signed-off-by: Adrian Torres (adt) &lt;adt@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In some situations, like during tests on runbot, the data-dir location
may vary.

With this commit, the `data-dir` CLI argument is added to the
test_module_operations script.

closes odoo/odoo#66422

Signed-off-by: Adrian Torres (adt) &lt;adt@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[IMP] tours: make chrome request a websocket port from the OS</title>
<updated>2021-01-22T13:00:18+00:00</updated>
<author>
<name>Xavier Morel</name>
<email>xmo@odoo.com</email>
</author>
<published>2021-01-20T15:04:35+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=b4e12c460f056818b8f6746d799ea42110d232b2'/>
<id>b4e12c460f056818b8f6746d799ea42110d232b2</id>
<content type='text'>
This should be a smarter and properly reliable version of #42071: in
that, the runner requests a port, closes it, and gives the port to
Chrome. However this apparently turns out to be less reliable than
hoped for and the port we just released can immediately be picked up
by somebody else (the original PR assumed the allocation of ephemeral
ports would be random or FIFO but that may not be the case, especially
inside containers).

This uses the same technique of requesting port 0 so the OS allocates
one, but it's Chrome requesting &amp; immediately connecting so there
should be no race condition possible, and we keep the property that as
long as ephemeral ports are available Chrome will be able to open one
without conflicts or overlaps.

This leaves the issue of *retrieving* the port chrome got. Thankfully
it turns out we use a custom user-data-dir in which case Chrome writes
the port it got to `$DATA_DIR/DevToolsActivePort`[0]. Despite the
file's name it *also* contains the path for the devtools endpoint so
we need to only read the first line (rather than be able to read and
intify the entire thing).

Wait up to 10s before giving up entirely, and wait 100ms between each
check for the file's existence: on my machine without significant load
the file appears after 80 to 150ms, waiting up to 90ms seems ok (it's
not like we're in a super hurry as tours tend to be pretty long).

Other paths explored before moc used his eyes and brain and found out
about DevToolsActivePort:

* Chrome prints ws URL on the stderr, however because we don't know
  how much garbage Chrome might send there we need to send it to a
  continuous sink otherwise Chrome *might* end up blocking on its
  stderr because we're not reading from it. This turns out to be a bit
  of a mess of processes or additional threads.
* xdo suggested we check what ports Chrome listens on using something
  like netstat/ss (turns out `psutil` has support for that OOTB),
  which worked great except on WSL (where it didn't work at all), and
  the future-proofness was a bit questionable as Chrome might add
  other servers in the future.
* fme suggested using socket activation support[1] and passing in the
  port we'd opened without closing it, which would really have been
  ideal, however it turns out it was removed a few months later when
  chrome added pipes support[2], which was a pain to realize as chrome
  doesn't exactly do any useful error reporting (so unknown options
  just disappear into a void to be never seen or heard of ever).
* And while the pipes system[3] has *serious* positive attributes
  (even lower initialization overhead, we could remove the websocket
  dependency, also avoids wasting sockets though that's not too much
  of an issue here) it would require rewriting a lot more than just
  the initialization as it uses its own logical protocol
  (NUL-terminated JSON). TBF most of the messaging stuff is properly
  contained into just a few `_websocket` methods but still...

[0] https://bugs.chromium.org/p/chromium/issues/detail?id=624837#c4
[1] https://bugs.chromium.org/p/chromium/issues/detail?id=624837
[2] https://chromium-review.googlesource.com/c/chromium/src/+/954405/3#message-ab7415a7db7b94787300d987216e9ce60db47bc2
[3] https://chromium-review.googlesource.com/c/chromium/src/+/954405/3

opw-2378464

Replaces #64758

closes odoo/odoo#64844

Signed-off-by: Xavier Morel (xmo) &lt;xmo@odoo.com&gt;
Co-authored-by: Xavier Dollé &lt;xdo@odoo.com&gt;
Co-authored-by: Christophe Monniez &lt;moc@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This should be a smarter and properly reliable version of #42071: in
that, the runner requests a port, closes it, and gives the port to
Chrome. However this apparently turns out to be less reliable than
hoped for and the port we just released can immediately be picked up
by somebody else (the original PR assumed the allocation of ephemeral
ports would be random or FIFO but that may not be the case, especially
inside containers).

This uses the same technique of requesting port 0 so the OS allocates
one, but it's Chrome requesting &amp; immediately connecting so there
should be no race condition possible, and we keep the property that as
long as ephemeral ports are available Chrome will be able to open one
without conflicts or overlaps.

This leaves the issue of *retrieving* the port chrome got. Thankfully
it turns out we use a custom user-data-dir in which case Chrome writes
the port it got to `$DATA_DIR/DevToolsActivePort`[0]. Despite the
file's name it *also* contains the path for the devtools endpoint so
we need to only read the first line (rather than be able to read and
intify the entire thing).

Wait up to 10s before giving up entirely, and wait 100ms between each
check for the file's existence: on my machine without significant load
the file appears after 80 to 150ms, waiting up to 90ms seems ok (it's
not like we're in a super hurry as tours tend to be pretty long).

Other paths explored before moc used his eyes and brain and found out
about DevToolsActivePort:

* Chrome prints ws URL on the stderr, however because we don't know
  how much garbage Chrome might send there we need to send it to a
  continuous sink otherwise Chrome *might* end up blocking on its
  stderr because we're not reading from it. This turns out to be a bit
  of a mess of processes or additional threads.
* xdo suggested we check what ports Chrome listens on using something
  like netstat/ss (turns out `psutil` has support for that OOTB),
  which worked great except on WSL (where it didn't work at all), and
  the future-proofness was a bit questionable as Chrome might add
  other servers in the future.
* fme suggested using socket activation support[1] and passing in the
  port we'd opened without closing it, which would really have been
  ideal, however it turns out it was removed a few months later when
  chrome added pipes support[2], which was a pain to realize as chrome
  doesn't exactly do any useful error reporting (so unknown options
  just disappear into a void to be never seen or heard of ever).
* And while the pipes system[3] has *serious* positive attributes
  (even lower initialization overhead, we could remove the websocket
  dependency, also avoids wasting sockets though that's not too much
  of an issue here) it would require rewriting a lot more than just
  the initialization as it uses its own logical protocol
  (NUL-terminated JSON). TBF most of the messaging stuff is properly
  contained into just a few `_websocket` methods but still...

[0] https://bugs.chromium.org/p/chromium/issues/detail?id=624837#c4
[1] https://bugs.chromium.org/p/chromium/issues/detail?id=624837
[2] https://chromium-review.googlesource.com/c/chromium/src/+/954405/3#message-ab7415a7db7b94787300d987216e9ce60db47bc2
[3] https://chromium-review.googlesource.com/c/chromium/src/+/954405/3

opw-2378464

Replaces #64758

closes odoo/odoo#64844

Signed-off-by: Xavier Morel (xmo) &lt;xmo@odoo.com&gt;
Co-authored-by: Xavier Dollé &lt;xdo@odoo.com&gt;
Co-authored-by: Christophe Monniez &lt;moc@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] test_event_full: fix the registration testing tour</title>
<updated>2020-12-03T08:12:33+00:00</updated>
<author>
<name>std-odoo</name>
<email>std@odoo.com</email>
</author>
<published>2020-11-24T13:32:51+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=6d08408a33880221b28f0f8a81d699825d927a48'/>
<id>6d08408a33880221b28f0f8a81d699825d927a48</id>
<content type='text'>
Bug
===
Sometimes, the registration testing tour failed.

The bug can be semi-deterministic if we add a "sleep(1)" in the endpoint
"/event/&lt;event&gt;/track".

Reason
======
The reason for that is the service worker. It will pre-fetch all the
links in the page (see "prefetch-pages"), so for the "Online Reveal"
we will pre-fetch ~100 pages... If the server is slow, it can cause
issues.

If one endpoint takes some time, all other HTTP requests done by the
service worker will be waiting for it.

So, at the end of the testing tour, the service worker will continue to
make HTTP requests (because it makes the request sequentially) and so
some threads will still be created after the tour.

Even if "_wait_remaining_requests" is called to wait those threads, as
the service worker is still running, it will still continue to make HTTP
requests, creating new threads...

Fix
===
The solution to this issue is to kill the service workers of the browser
when we stop the tour before waiting for the end of the "HTTP request
threads".

Task 2381066

closes odoo/odoo#62248

Signed-off-by: Christophe Monniez (moc) &lt;moc@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Bug
===
Sometimes, the registration testing tour failed.

The bug can be semi-deterministic if we add a "sleep(1)" in the endpoint
"/event/&lt;event&gt;/track".

Reason
======
The reason for that is the service worker. It will pre-fetch all the
links in the page (see "prefetch-pages"), so for the "Online Reveal"
we will pre-fetch ~100 pages... If the server is slow, it can cause
issues.

If one endpoint takes some time, all other HTTP requests done by the
service worker will be waiting for it.

So, at the end of the testing tour, the service worker will continue to
make HTTP requests (because it makes the request sequentially) and so
some threads will still be created after the tour.

Even if "_wait_remaining_requests" is called to wait those threads, as
the service worker is still running, it will still continue to make HTTP
requests, creating new threads...

Fix
===
The solution to this issue is to kill the service workers of the browser
when we stop the tour before waiting for the end of the "HTTP request
threads".

Task 2381066

closes odoo/odoo#62248

Signed-off-by: Christophe Monniez (moc) &lt;moc@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] core: add UPDATE as valid many2many command in SSF</title>
<updated>2020-10-14T07:07:12+00:00</updated>
<author>
<name>Xavier ALT</name>
<email>xal@odoo.com</email>
</author>
<published>2020-09-21T13:21:30+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=a29837f01a567e09ea389ad4adaf96943448c43d'/>
<id>a29837f01a567e09ea389ad4adaf96943448c43d</id>
<content type='text'>
This commit fix the "Unsupported M2M command 1" raised `Form` helper.

The `onchange()` method will in fact emit UPDATE command for many2many
fields when the value submitted an the one in database has changed
(this is the case for example for nested m2m in form views)

OPW-2044631

closes odoo/odoo#59937

X-original-commit: 76bd8208a416cefab6becff9f2d7204c7d196201
Signed-off-by: Xavier Morel (xmo) &lt;xmo@odoo.com&gt;
Signed-off-by: Xavier ALT &lt;xavieralt@users.noreply.github.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This commit fix the "Unsupported M2M command 1" raised `Form` helper.

The `onchange()` method will in fact emit UPDATE command for many2many
fields when the value submitted an the one in database has changed
(this is the case for example for nested m2m in form views)

OPW-2044631

closes odoo/odoo#59937

X-original-commit: 76bd8208a416cefab6becff9f2d7204c7d196201
Signed-off-by: Xavier Morel (xmo) &lt;xmo@odoo.com&gt;
Signed-off-by: Xavier ALT &lt;xavieralt@users.noreply.github.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] base_setup, website, tests: remove Gengo references</title>
<updated>2020-10-01T15:10:42+00:00</updated>
<author>
<name>Nicolas Martinelli</name>
<email>nim@odoo.com</email>
</author>
<published>2020-10-01T15:08:44+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=a30edba504aa1b62aa02092112a55bca65cf9a0c'/>
<id>a30edba504aa1b62aa02092112a55bca65cf9a0c</id>
<content type='text'>
The Gengo modules were removed with:
https://github.com/odoo/odoo/commit/b38b72e456a
https://github.com/odoo/odoo/commit/9b1f0962baa

But there are still references to it.

opw-2349904

closes odoo/odoo#58931

Signed-off-by: Nicolas Martinelli (nim) &lt;nim@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The Gengo modules were removed with:
https://github.com/odoo/odoo/commit/b38b72e456a
https://github.com/odoo/odoo/commit/9b1f0962baa

But there are still references to it.

opw-2349904

closes odoo/odoo#58931

Signed-off-by: Nicolas Martinelli (nim) &lt;nim@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[IMP] tests: use concat demuxer to encode frames</title>
<updated>2020-09-22T19:17:17+00:00</updated>
<author>
<name>Christophe Monniez</name>
<email>moc@odoo.com</email>
</author>
<published>2020-09-16T13:27:48+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=bfbc1db205de43c8c89ca882e809d578bb733ac0'/>
<id>bfbc1db205de43c8c89ca882e809d578bb733ac0</id>
<content type='text'>
When the sceencast argument is used to produce a video file of failing
tests, the framerate is computed with a KISS average.
This results in a misleading video flow. For example, if a tour step is
stuck, the average could show a smooth transition instead of the reality.

With this commit, the real duration of frames are used to produce the
video. The result is a more realistic video flow.

The configuration text file used by the ffmpeg concat demuxer is kept
alongside with the video file so that it can be used for other purposes
(e.g.: parse the durations to be used by a video player on runbot).

closes odoo/odoo#58278

X-original-commit: 58eb6a4565c024077557fa2de83fdf831e5ef026
Signed-off-by: Xavier Dollé (xdo) &lt;xdo@odoo.com&gt;
Signed-off-by: Christophe Monniez (moc) &lt;moc@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When the sceencast argument is used to produce a video file of failing
tests, the framerate is computed with a KISS average.
This results in a misleading video flow. For example, if a tour step is
stuck, the average could show a smooth transition instead of the reality.

With this commit, the real duration of frames are used to produce the
video. The result is a more realistic video flow.

The configuration text file used by the ffmpeg concat demuxer is kept
alongside with the video file so that it can be used for other purposes
(e.g.: parse the durations to be used by a video player on runbot).

closes odoo/odoo#58278

X-original-commit: 58eb6a4565c024077557fa2de83fdf831e5ef026
Signed-off-by: Xavier Dollé (xdo) &lt;xdo@odoo.com&gt;
Signed-off-by: Christophe Monniez (moc) &lt;moc@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] base: virtual group fields on users with new default/onchange</title>
<updated>2020-09-18T08:26:28+00:00</updated>
<author>
<name>Xavier Morel</name>
<email>xmo@odoo.com</email>
</author>
<published>2020-09-18T06:41:51+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=f8658f229180a595d69cd6daefeded082c7f64ea'/>
<id>f8658f229180a595d69cd6daefeded082c7f64ea</id>
<content type='text'>
* override `onchange` in res.users in order to properly generate and
  send the reified group fields alongside the rest: while default_get
  sets them up, those fields then get stripped by the onchange
  machinery as they don't actually exist on the model
* add a test to check for it
* fix SSF in relation with the new default/onchange system
  - because fields may not actually exist on the record,
    `record_to_values` needs to `read` the record data rather than
    directly access the recordset: the recordset likely will not
    know about fake fields
  - after the initial onchange has run the form must be filled with
    falsy values in case the onchange has not sent defaults for
    everything
  - on creation, all fields in the form should be considered modified

Task 2341153

closes odoo/odoo#57987

Signed-off-by: Xavier Morel (xmo) &lt;xmo@odoo.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* override `onchange` in res.users in order to properly generate and
  send the reified group fields alongside the rest: while default_get
  sets them up, those fields then get stripped by the onchange
  machinery as they don't actually exist on the model
* add a test to check for it
* fix SSF in relation with the new default/onchange system
  - because fields may not actually exist on the record,
    `record_to_values` needs to `read` the record data rather than
    directly access the recordset: the recordset likely will not
    know about fake fields
  - after the initial onchange has run the form must be filled with
    falsy values in case the onchange has not sent defaults for
    everything
  - on creation, all fields in the form should be considered modified

Task 2341153

closes odoo/odoo#57987

Signed-off-by: Xavier Morel (xmo) &lt;xmo@odoo.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[FIX] core: cursor hooks API and implementation</title>
<updated>2020-09-03T09:05:21+00:00</updated>
<author>
<name>Raphael Collet</name>
<email>rco@odoo.com</email>
</author>
<published>2020-08-28T14:11:21+00:00</published>
<link rel='alternate' type='text/html' href='http://erp.ceuconsult.com:9000/Odoo/commit/?id=d4b2e9224839aed8fc160ebe5a89e0f7d4c6a5bb'/>
<id>d4b2e9224839aed8fc160ebe5a89e0f7d4c6a5bb</id>
<content type='text'>
Python 3.8 changed the equality rules for bound methods to be based on
the *identity* of the receiver (`__self__`) rather than its *equality*.
This means that in 3.7, methods from different instances will compare
(and hash) equal, thereby landing in the same map "slot", but that isn't
the case in 3.8.

While it's usually not relevant, it's an issue for `GroupCalls` which is
indexed by a function: in 3.7, that being a method from recordsets
comparing equal will deduplicate them, but not anymore in 3.8, leading
to duplicated callbacks (exactly the thing GroupCalls aims to avoid).

Also, the API of `GroupCalls` turned out to be unusual and weird.  The
bug above is fixed by using a plain list for callbacks, thereby avoiding
comparisons between registered functions.  The API is now:

    callbacks.add(func)     # add func to callbacks
    callbacks.run()         # run all callbacks in addition order
    callbacks.clear()       # remove all callbacks

In order to handle aggregated data, the `callbacks` object provides a
dictionary `callbacks.data` that any callback function can freely use.
For the sake of consistency, the `callbacks.data` dict is automatically
cleared upon execution of callbacks.

Discovered by @william-andre

Related to odoo#56583

References:

* https://bugs.python.org/issue1617161
* python/cpython#7848
* https://docs.python.org/3/whatsnew/changelog.html#python-3-8-0-alpha-1
  (no direct link because individual entries are not linkable, look for
  bpo-1617161)

X-original-commit: a986f4929bab95759086cc77ca5e60795f82e91a</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Python 3.8 changed the equality rules for bound methods to be based on
the *identity* of the receiver (`__self__`) rather than its *equality*.
This means that in 3.7, methods from different instances will compare
(and hash) equal, thereby landing in the same map "slot", but that isn't
the case in 3.8.

While it's usually not relevant, it's an issue for `GroupCalls` which is
indexed by a function: in 3.7, that being a method from recordsets
comparing equal will deduplicate them, but not anymore in 3.8, leading
to duplicated callbacks (exactly the thing GroupCalls aims to avoid).

Also, the API of `GroupCalls` turned out to be unusual and weird.  The
bug above is fixed by using a plain list for callbacks, thereby avoiding
comparisons between registered functions.  The API is now:

    callbacks.add(func)     # add func to callbacks
    callbacks.run()         # run all callbacks in addition order
    callbacks.clear()       # remove all callbacks

In order to handle aggregated data, the `callbacks` object provides a
dictionary `callbacks.data` that any callback function can freely use.
For the sake of consistency, the `callbacks.data` dict is automatically
cleared upon execution of callbacks.

Discovered by @william-andre

Related to odoo#56583

References:

* https://bugs.python.org/issue1617161
* python/cpython#7848
* https://docs.python.org/3/whatsnew/changelog.html#python-3-8-0-alpha-1
  (no direct link because individual entries are not linkable, look for
  bpo-1617161)

X-original-commit: a986f4929bab95759086cc77ca5e60795f82e91a</pre>
</div>
</content>
</entry>
</feed>
