Repository navigation
Conversation
- Apply new copier template. (from v1.14.2 to v1.18 : replace setup by pyproject.toml, replace black by ruff, ...) - Disable .github/workflows/test.yml because the openupgrade is not initialized yet - add new empty modules160-170.rst file
…de is not initialized yet
.github/workflows/test.yml
-This commit remove unecessary patch -Check if test exist then execute it in the test.yml -Remove the test loader from patch, detail at OCA#4327 (comment)
account_peppol by now
…run scripts" This reverts commit 576daf1.
…path does not exist
|
pre-commit failure fixed in OCA/pylint-odoo#590 |
There was a problem hiding this comment.
Tested on a 19.0 db with crm, sale_management, purchase, stock, account + l10n_mx, project, hr, mrp and point_of_sale (131 modules after the upgrade). These are the framework issues we hit, one per comment so you can take what makes sense.
Drafted with AI assistance (Claude Opus 5.5), reviewed by me; each suggestion was checked against the current code of this PR and our test migration.
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
| from openupgradelib import openupgrade | ||
|
|
||
| from odoo import models |
There was a problem hiding this comment.
For the patch below.
| from odoo import models | |
| from odoo import api, models |
| ) | ||
|
|
||
|
|
||
| IrModel._drop_table = _drop_table |
There was a problem hiding this comment.
v20 added IrModel._unlink_related_attachments, an ondelete(at_uninstall=False) that deletes all ir.attachment rows of the model, including attachment=True binary fields, and marks their files for GC. registry.uninstalling_modules is still empty when _process_end runs, so it fires for every obsolete model while _drop_table keeps the table.
| IrModel._drop_table = _drop_table | |
| IrModel._drop_table = _drop_table | |
| @api.ondelete(at_uninstall=False) | |
| def _unlink_related_attachments(self): | |
| """Never delete attachments (incl. binary field data) of removed models""" | |
| for model in self: | |
| openupgrade.message( | |
| self.env.cr, | |
| self.env.context.get("module", "Unknown"), | |
| False, | |
| False, | |
| "Not deleting the attachments of model %s", | |
| model.model, | |
| ) | |
| IrModel._unlink_related_attachments = _unlink_related_attachments |
| new_auto_install_modules = self.browse([]) | ||
| for module in self.env["ir.module.module"].search( | ||
| [ | ||
| ("auto_install", "=", True), | ||
| ("state", "=", "uninstalled"), | ||
| ("name", "not like", ("l10n_%")), | ||
| ] | ||
| ): |
There was a problem hiding this comment.
button_install skips auto_install modules whose country_ids don't match any company, this loop doesn't, so e.g. account_peppol gets installed on databases without a Peppol country.
| new_auto_install_modules = self.browse([]) | |
| for module in self.env["ir.module.module"].search( | |
| [ | |
| ("auto_install", "=", True), | |
| ("state", "=", "uninstalled"), | |
| ("name", "not like", ("l10n_%")), | |
| ] | |
| ): | |
| new_auto_install_modules = self.browse([]) | |
| company_countries = self.env["res.company"].sudo().search([]).country_id | |
| for module in self.env["ir.module.module"].search( | |
| [ | |
| ("auto_install", "=", True), | |
| ("state", "=", "uninstalled"), | |
| ("name", "not like", ("l10n_%")), | |
| ] | |
| ): | |
| # same rule as button_install | |
| if module.country_ids and not module.country_ids & company_countries: | |
| continue |
| try: | ||
| return IrUiView._check_xml._original_method(self) | ||
| except ValidationError as e: | ||
| _logger.warning( | ||
| "Can't render custom view %s for model %s. " | ||
| "Assuming you are migrating between major versions of Odoo. " | ||
| "Please review the view contents manually after the migration.\n" | ||
| "Error: %s", | ||
| self.xml_id, | ||
| self.model, | ||
| e, | ||
| ) |
There was a problem hiding this comment.
Two things here:
_validate_module_viewsandcreate()call_check_xmlon several views, soself.xml_idin the handler raisesExpected singletonand aborts the upgrade instead of logging.- As
_raise_view_errordoesn't raise anymore, validation goes on and fails later withAttributeError/KeyError/NameError/ValueError(_check_field_paths,_validate_domain_identifiers).
| try: | |
| return IrUiView._check_xml._original_method(self) | |
| except ValidationError as e: | |
| _logger.warning( | |
| "Can't render custom view %s for model %s. " | |
| "Assuming you are migrating between major versions of Odoo. " | |
| "Please review the view contents manually after the migration.\n" | |
| "Error: %s", | |
| self.xml_id, | |
| self.model, | |
| e, | |
| ) | |
| for view in self: | |
| try: | |
| IrUiView._check_xml._original_method(view) | |
| # with _raise_view_error not raising, validation can fail later on | |
| except ( | |
| ValidationError, | |
| ValueError, | |
| AttributeError, | |
| KeyError, | |
| NameError, | |
| ) as e: | |
| _logger.warning( | |
| "Can't render custom view %s for model %s. " | |
| "Assuming you are migrating between major versions of Odoo. " | |
| "Please review the view contents manually after the migration.\n" | |
| "Error: %s", | |
| view.xml_id, | |
| view.model, | |
| e, | |
| ) |
| # Copyright Odoo Community Association (OCA) | ||
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
| import logging | ||
| from uuid import uuid4 |
There was a problem hiding this comment.
Not needed with the change below.
| from uuid import uuid4 |
| savepoint = str(uuid4) | ||
| try: | ||
| self.env.cr.execute( # pylint: disable=sql-injection | ||
| f'SAVEPOINT "{savepoint}"' | ||
| ) | ||
| return BaseModel.unlink._original_method(self) | ||
| except Exception as e: | ||
| self.env.cr.execute( # pylint: disable=sql-injection | ||
| f'ROLLBACK TO SAVEPOINT "{savepoint}"' | ||
| ) |
There was a problem hiding this comment.
str(uuid4) is the repr of the function, so every call uses the same savepoint name, and the savepoint is never released after a successful unlink. cr.savepoint() also resets the ORM caches on rollback.
| savepoint = str(uuid4) | |
| try: | |
| self.env.cr.execute( # pylint: disable=sql-injection | |
| f'SAVEPOINT "{savepoint}"' | |
| ) | |
| return BaseModel.unlink._original_method(self) | |
| except Exception as e: | |
| self.env.cr.execute( # pylint: disable=sql-injection | |
| f'ROLLBACK TO SAVEPOINT "{savepoint}"' | |
| ) | |
| try: | |
| with self.env.cr.savepoint(): | |
| return BaseModel.unlink._original_method(self) | |
| except Exception as e: |
depends on: