From 10db26d43902355f952b1d17add81b792be3146f Mon Sep 17 00:00:00 2001 From: Arnaud Fontaine <arnaud.fontaine@nexedi.com> Date: Tue, 24 Dec 2019 16:59:47 +0900 Subject: [PATCH] ZODB Components: pylint: Just ignoring no-name-in-module for monkey patch was not enough. For example, ExtensionClass (such as ValidationFailed) need to have their AST properly generated. This fixes 'Use of super on an old style class (super-on-old-class)' error. --- product/ERP5Type/patches/pylint.py | 56 +++++++++++-------- .../tests/testDynamicClassGeneration.py | 9 +-- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/product/ERP5Type/patches/pylint.py b/product/ERP5Type/patches/pylint.py index b399590f12..858adee8a1 100644 --- a/product/ERP5Type/patches/pylint.py +++ b/product/ERP5Type/patches/pylint.py @@ -190,29 +190,39 @@ MANAGER.register_failed_import_hook(fail_hook_erp5_component) ## transforms but this would require either checking dynamically which ## attributes has been added (much more complex than the current approach) ## or listing them statically (inconvenient). -from pylint.checkers import BaseChecker -from pylint.interfaces import UNDEFINED -BaseChecker_add_message = BaseChecker.add_message -def add_message(self, msg_descr, line=None, node=None, args=None, - confidence=UNDEFINED): - """ - Monkey patched to dynamically ignore some error/warning messages - """ - if msg_descr == 'no-name-in-module': - name, module_name = args - if not module_name.startswith('erp5.'): - # Do not call __import__ as this may load ZODB Component which - # should use 'version' and not use monkey patches... - try: - getattr(sys.modules[module_name], name) - except (KeyError, AttributeError): - pass - else: - # Do nothing as this does exist - return - BaseChecker_add_message(self, msg_descr, line=line, node=node, - args=args, confidence=confidence) -BaseChecker.add_message = add_message +from astroid.exceptions import NotFoundError +from astroid.scoped_nodes import Module +Module_getattr = Module.getattr +def _getattr(self, name, *args, **kw): + try: + return Module_getattr(self, name, *args, **kw) + except NotFoundError, e: + if self.name.startswith('erp5.'): + raise + + real_module = __import__(self.name, fromlist=[self.name], level=0) + try: + attr = getattr(real_module, name) + except AttributeError: + raise e + + # XXX: What about int, str or bool not having __module__? + try: + origin_module_name = attr.__module__ + except AttributeError: + raise e + if self.name == origin_module_name: + raise + + # ast_from_class() actually works for any attribute of a Module + try: + ast = MANAGER.ast_from_class(attr) + except AstroidBuildingException: + raise e + + self.locals[name] = [ast] + return [ast] +Module.getattr = _getattr if sys.modules['isort'] is None: del sys.modules['isort'] diff --git a/product/ERP5Type/tests/testDynamicClassGeneration.py b/product/ERP5Type/tests/testDynamicClassGeneration.py index aa1af1d19a..a4ae749c38 100644 --- a/product/ERP5Type/tests/testDynamicClassGeneration.py +++ b/product/ERP5Type/tests/testDynamicClassGeneration.py @@ -2225,11 +2225,12 @@ hoge() %(module2)s.hoge() %(module2_with_version)s.hoge() -# Attributes added through Products.XXX.patches: Must not raise error +# Attributes added through Products.XXX.patches: Must not raise error nor +# warnings when being used. from Products.DCWorkflow.DCWorkflow import ValidationFailed -# To avoid 'unused-import' warnings... -ValidationFailed('anything') - +class FooBar(ValidationFailed): + def __init__(self, *args, **kw): + super(FooBar, self).__init__(*args, **kw) """ % (dict(namespace=namespace, reference1=imported_reference1, module2=imported_module2, -- 2.30.9