-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFR] OpenUpgrade framework patches #3
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,7 +42,6 @@ repos: | |
rev: 20.8b1 | ||
hooks: | ||
- id: black | ||
exclude: ^openupgrade_framework/odoo_patch/ | ||
- repo: https://github.com/prettier/pre-commit | ||
rev: v2.1.2 | ||
hooks: | ||
|
@@ -53,7 +52,6 @@ repos: | |
- "@prettier/[email protected]" | ||
args: | ||
- --plugin=@prettier/plugin-xml | ||
exclude: ^openupgrade_framework/odoo_patch/ | ||
- repo: https://github.com/pre-commit/mirrors-eslint | ||
rev: v7.8.1 | ||
hooks: | ||
|
@@ -88,15 +86,13 @@ repos: | |
rev: v2.7.2 | ||
hooks: | ||
- id: pyupgrade | ||
exclude: ^openupgrade_framework/odoo_patch/ | ||
- repo: https://github.com/PyCQA/isort | ||
rev: 5.5.1 | ||
hooks: | ||
- id: isort | ||
name: isort except __init__.py | ||
args: | ||
- --settings=. | ||
exclude: /__init__\.py$|^openupgrade_framework/odoo_patch/ | ||
- repo: https://github.com/acsone/setuptools-odoo | ||
rev: 2.6.0 | ||
hooks: | ||
|
@@ -106,7 +102,6 @@ repos: | |
hooks: | ||
- id: flake8 | ||
name: flake8 except __init__.py | ||
exclude: /__init__\.py$|^openupgrade_framework/odoo_patch/ | ||
additional_dependencies: ["flake8-bugbear==20.1.4"] | ||
- id: flake8 | ||
name: flake8 only __init__.py | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
from . import odoo_patch | ||
from . import openupgrade |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
from . import odoo | ||
from . import addons |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1 @@ | ||
from . import modules | ||
from . import service | ||
|
||
# Nothing todo the function, the function check_security didn't changed | ||
from . import http | ||
from . import addons, models, modules |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import base |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import ir_model | ||
from . import ir_ui_view |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Copyright Odoo Community Association (OCA) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
from openupgradelib import openupgrade | ||
from odoo import api, models | ||
from odoo.addons.base.models.ir_model import IrModel, IrModelData, IrModelRelation | ||
from odoo.tools import mute_logger | ||
|
||
|
||
def _drop_table(self): | ||
""" Never drop tables """ | ||
for model in self: | ||
if self.env.get(model.model) is not None: | ||
openupgrade.message( | ||
self.env.cr, "Unknown", False, False, | ||
"Not dropping the table or view of model %s", model.model) | ||
|
||
|
||
def _drop_column(self): | ||
""" Never drop columns """ | ||
for field in self: | ||
if field.name in models.MAGIC_COLUMNS: | ||
continue | ||
openupgrade.message( | ||
self.env.cr, "Unknown", False, False, | ||
"Not dropping the column of field %s of model %s", field.name, | ||
field.model, | ||
) | ||
continue | ||
|
||
|
||
IrModel._drop_column = _drop_column | ||
IrModel._drop_table = _drop_table | ||
|
||
|
||
@api.model | ||
def _process_end(self, modules): | ||
""" Don't warn about upgrade conventions from Odoo | ||
('fields should be explicitely removed by an upgrade script') | ||
""" | ||
with mute_logger('odoo.addons.base.models.ir_model'): | ||
return IrModelData._process_end._original_method(self, modules) | ||
|
||
|
||
_process_end._original_method = IrModelData._process_end | ||
IrModelData._process_end = _process_end | ||
|
||
|
||
def _module_data_uninstall(self): | ||
""" Don't delete many2many relation tables. Only unlink the | ||
ir.model.relation record itself. | ||
""" | ||
self.unlink() | ||
|
||
|
||
IrModelRelation._module_data_uninstall = _module_data_uninstall | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Copyright Odoo Community Association (OCA) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
import logging | ||
from odoo import api | ||
from odoo.tools import mute_logger | ||
from odoo.addons.base.models.ir_ui_view import View | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
@api.constrains('arch_db') | ||
def _check_xml(self): | ||
""" Mute warnings about views which are common during migration """ | ||
with mute_logger('odoo.addons.base.models.ir_ui_view'): | ||
return View._check_xml._original_method(self) | ||
|
||
|
||
def handle_view_error(self, message, *args, raise_exception=True, from_exception=None, from_traceback=None): | ||
""" Don't raise or log exceptions in view validation unless explicitely requested """ | ||
raise_exception = self.env.context.get('raise_view_error') | ||
to_mute = 'odoo.addons.base.models.ir_ui_view' if raise_exception else 'not_muted' | ||
with mute_logger(to_mute): | ||
try: | ||
return View.handle_view_error._original_method( | ||
self, message, *args, | ||
raise_exception=False, from_exception=from_exception, | ||
from_traceback=from_traceback) | ||
except ValueError: | ||
_logger.warn( | ||
"Can't render custom view %s for model %s. " | ||
"Assuming you are migrating between major versions of " | ||
"Odoo, this view is now set to inactive. Please " | ||
"review the view contents manually after the migration.", | ||
self.xml_id, self.model) | ||
self.write({'active': False}) | ||
|
||
|
||
_check_xml._original_method = View._check_xml | ||
View._check_xml = _check_xml | ||
handle_view_error._original_method = View.handle_view_error | ||
View.handle_view_error = handle_view_error | ||
Comment on lines
+38
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, shouldn't you use |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Copyright Odoo Community Association (OCA) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
import logging | ||
from uuid import uuid4 | ||
from odoo.models import BaseModel | ||
from odoo.addons.base.models.ir_model import MODULE_UNINSTALL_FLAG | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
def unlink(self): | ||
""" Don't break on unlink of obsolete records | ||
when called from ir.model::_process_end() | ||
|
||
This only adapts the base unlink method. If overrides of this method | ||
on individual models give problems, add patches for those as well. | ||
""" | ||
if not self.env.context.get(MODULE_UNINSTALL_FLAG): | ||
return BaseModel.unlink._original_method(self) | ||
savepoint = str(uuid4) | ||
try: | ||
self.env.cr.execute('SAVEPOINT "%s"' % savepoint) | ||
return BaseModel.unlink._original_method(self) | ||
except Exception as e: | ||
self.env.cr.execute('ROLLBACK TO SAVEPOINT "%s"' % savepoint) | ||
_logger.warning( | ||
"Could not delete obsolete record with ids %s of model %s: %s", | ||
self.ids, self._name, e) | ||
Comment on lines
+20
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could just use |
||
return False | ||
|
||
|
||
unlink._original_method = BaseModel.unlink | ||
BaseModel.unlink = unlink | ||
Comment on lines
+32
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same point about |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1 @@ | ||
# Minor changes. (call to safe_eval changed) | ||
# otherwise : adapted to V14 | ||
from . import graph | ||
|
||
# A lot of changes in the core functions. | ||
from . import loading | ||
|
||
# Adapted to V14 | ||
from . import migration | ||
|
||
# Adapted to V14 | ||
from . import registry | ||
from . import graph, migration |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,21 @@ | ||
# flake8: noqa | ||
# pylint: skip-file | ||
|
||
import logging | ||
# Copyright Odoo Community Association (OCA) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
import odoo | ||
import odoo.tools as tools | ||
from odoo.tools.safe_eval import safe_eval | ||
|
||
from odoo.modules.graph import Graph | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
if True: | ||
|
||
def _update_from_db(self, cr): | ||
if not len(self): | ||
return | ||
# update the graph with values from the database (if exist) | ||
## First, we set the default values for each package in graph | ||
additional_data = {key: {'id': 0, 'state': 'uninstalled', 'dbdemo': False, 'installed_version': None} for key in self.keys()} | ||
## Then we get the values from the database | ||
cr.execute('SELECT name, id, state, demo AS dbdemo, latest_version AS installed_version' | ||
' FROM ir_module_module' | ||
' WHERE name IN %s',(tuple(additional_data),) | ||
) | ||
|
||
## and we update the default values with values from the database | ||
additional_data.update((x['name'], x) for x in cr.dictfetchall()) | ||
|
||
# <OpenUpgrade:ADD> | ||
# Prevent reloading of demo data from the new version on major upgrade | ||
if ('base' in self and additional_data['base']['dbdemo'] and | ||
additional_data['base']['installed_version'] < | ||
odoo.release.major_version): | ||
cr.execute("UPDATE ir_module_module SET demo = false") | ||
for data in additional_data.values(): | ||
data['dbdemo'] = False | ||
# </OpenUpgrade> | ||
|
||
def update_from_db(self, cr): | ||
""" Prevent reloading of demo data from the new version on major upgrade """ | ||
Graph.update_from_db._original_method(self, cr) | ||
if ( | ||
"base" in self | ||
and self["base"].dbdemo | ||
and self["base"].installed_version < odoo.release.major_version | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 Beware! You have to use a smart version comparison algorithm. Check out |
||
): | ||
cr.execute("UPDATE ir_module_module SET demo = false") | ||
for package in self.values(): | ||
for k, v in additional_data[package.name].items(): | ||
setattr(package, k, v) | ||
|
||
|
||
def _add_modules(self, cr, module_list, force=None): | ||
if force is None: | ||
force = [] | ||
packages = [] | ||
len_graph = len(self) | ||
|
||
# <OpenUpgrade:ADD> | ||
# force additional dependencies for the upgrade process if given | ||
# in config file | ||
forced_deps = tools.config.get_misc('openupgrade', 'force_deps', '{}') | ||
forced_deps = tools.config.get_misc('openupgrade', | ||
'force_deps_' + odoo.release.version, | ||
forced_deps) | ||
forced_deps = safe_eval(forced_deps) | ||
# </OpenUpgrade> | ||
|
||
for module in module_list: | ||
# This will raise an exception if no/unreadable descriptor file. | ||
# NOTE The call to load_information_from_description_file is already | ||
# done by db.initialize, so it is possible to not do it again here. | ||
info = odoo.modules.module.load_information_from_description_file(module) | ||
if info and info['installable']: | ||
# <OpenUpgrade:ADD> | ||
info['depends'].extend(forced_deps.get(module, [])) | ||
# </OpenUpgrade> | ||
packages.append((module, info)) # TODO directly a dict, like in get_modules_with_version | ||
elif module != 'studio_customization': | ||
_logger.warning('module %s: not installable, skipped', module) | ||
|
||
dependencies = dict([(p, info['depends']) for p, info in packages]) | ||
current, later = set([p for p, info in packages]), set() | ||
|
||
while packages and current > later: | ||
package, info = packages[0] | ||
deps = info['depends'] | ||
|
||
# if all dependencies of 'package' are already in the graph, add 'package' in the graph | ||
if all(dep in self for dep in deps): | ||
if not package in current: | ||
packages.pop(0) | ||
continue | ||
later.clear() | ||
current.remove(package) | ||
node = self.add_node(package, info) | ||
for kind in ('init', 'demo', 'update'): | ||
if package in tools.config[kind] or 'all' in tools.config[kind] or kind in force: | ||
setattr(node, kind, True) | ||
else: | ||
later.add(package) | ||
packages.append((package, info)) | ||
packages.pop(0) | ||
|
||
self.update_from_db(cr) | ||
|
||
for package in later: | ||
unmet_deps = [p for p in dependencies[package] if p not in self] | ||
_logger.info('module %s: Unmet dependencies: %s', package, ', '.join(unmet_deps)) | ||
|
||
return len(self) - len_graph | ||
package.dbdemo = False | ||
|
||
|
||
Graph.update_from_db = _update_from_db | ||
Graph.add_modules = _add_modules | ||
update_from_db._original_method = Graph.update_from_db | ||
Graph.update_from_db = update_from_db | ||
Comment on lines
+20
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same about |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't you be using
OdooPatch
?