Commit ab693398 authored by Jérome Perrin's avatar Jérome Perrin

ERP5Type: more pylint / astroid fixes

parent 4863e629
...@@ -163,8 +163,7 @@ class ComponentTool(BaseTool): ...@@ -163,8 +163,7 @@ class ComponentTool(BaseTool):
if six.PY2: if six.PY2:
from astroid.builder import MANAGER from astroid.builder import MANAGER
else: else:
from astroid.builder import AstroidManager from astroid.astroid_manager import MANAGER
MANAGER = AstroidManager()
astroid_cache = MANAGER.astroid_cache astroid_cache = MANAGER.astroid_cache
for k in list(astroid_cache.keys()): for k in list(astroid_cache.keys()):
if k.startswith('erp5.component.') and k not in component_package_list: if k.startswith('erp5.component.') and k not in component_package_list:
......
...@@ -467,10 +467,6 @@ _pylint_message_re = re.compile( ...@@ -467,10 +467,6 @@ _pylint_message_re = re.compile(
def checkPythonSourceCode(source_code_str, portal_type=None): def checkPythonSourceCode(source_code_str, portal_type=None):
""" """
Check source code with pylint or compile() builtin if not available. Check source code with pylint or compile() builtin if not available.
TODO-arnau: Get rid of NamedTemporaryFile (require a patch on pylint to
allow passing a string) and this should probably return a proper
ERP5 object rather than a dict...
""" """
if not source_code_str: if not source_code_str:
return [] return []
...@@ -555,7 +551,13 @@ def checkPythonSourceCode(source_code_str, portal_type=None): ...@@ -555,7 +551,13 @@ def checkPythonSourceCode(source_code_str, portal_type=None):
'--dummy-variables-rgx=_$|dummy|__traceback_info__|__traceback_supplement__', '--dummy-variables-rgx=_$|dummy|__traceback_info__|__traceback_supplement__',
] ]
if six.PY3: if six.PY3:
args.append("--msg-template='{C}: {line},{column}: {msg} ({symbol})'") args.extend(
(
"--msg-template='{C}: {line},{column}: {msg} ({symbol})'",
# BBB until we drop compatibility with PY2
"--disable=redundant-u-string-prefix,raise-missing-from",
)
)
if portal_type == 'Interface Component': if portal_type == 'Interface Component':
# __init__ method from base class %r is not called # __init__ method from base class %r is not called
args.append('--disable=W0231') args.append('--disable=W0231')
...@@ -581,10 +583,9 @@ def checkPythonSourceCode(source_code_str, portal_type=None): ...@@ -581,10 +583,9 @@ def checkPythonSourceCode(source_code_str, portal_type=None):
finally: finally:
if six.PY2: if six.PY2:
from astroid.builder import MANAGER from astroid.builder import MANAGER
astroid_cache = MANAGER.astroid_cache
else: else:
from astroid.manager import AstroidManager from astroid.astroid_manager import MANAGER
astroid_cache = AstroidManager().astroid_cache astroid_cache = MANAGER.astroid_cache
astroid_cache.pop( astroid_cache.pop(
os.path.splitext(os.path.basename(input_file.name))[0], os.path.splitext(os.path.basename(input_file.name))[0],
None) None)
......
...@@ -39,8 +39,7 @@ if getZopeVersion()[0] == 2: # BBB Zope2 ...@@ -39,8 +39,7 @@ if getZopeVersion()[0] == 2: # BBB Zope2
else: else:
IS_ZOPE2 = False IS_ZOPE2 = False
import six import six
if six.PY2: from .patches import pylint
from .patches import pylint
from zLOG import LOG, INFO from zLOG import LOG, INFO
DISPLAY_BOOT_PROCESS = False DISPLAY_BOOT_PROCESS = False
......
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from __future__ import absolute_import from __future__ import absolute_import
import importlib
import six
import sys import sys
import types
import warnings import warnings
import six
from Products.ERP5Type import IS_ZOPE2 from Products.ERP5Type import IS_ZOPE2
# TODO: make sure that trying to use it does not import isort, because the # TODO: make sure that trying to use it does not import isort, because the
...@@ -32,27 +34,21 @@ sys.modules.setdefault('isort', None) ...@@ -32,27 +34,21 @@ sys.modules.setdefault('isort', None)
## All arguments are passed as arguments and this needlessly outputs a 'No ## All arguments are passed as arguments and this needlessly outputs a 'No
## config file found, using default configuration' message on stderr. ## config file found, using default configuration' message on stderr.
try: if six.PY2:
from logilab.common.configuration import OptionsManagerMixIn from logilab.common.configuration import OptionsManagerMixIn
except ImportError: OptionsManagerMixIn.read_config_file = lambda *args, **kw: None
# pylint 2.x (python3)
from pylint.config import OptionsManagerMixIn
OptionsManagerMixIn.read_config_file = lambda *args, **kw: None
## Pylint transforms and plugin to generate AST for ZODB Components ## Pylint transforms and plugin to generate AST for ZODB Components
from astroid.builder import AstroidBuilder from astroid.builder import AstroidBuilder
from astroid.exceptions import AstroidBuildingException
from astroid import node_classes
if six.PY2: if six.PY2:
from astroid import MANAGER from astroid.exceptions import AstroidBuildingException as AstroidBuildingError
else: else:
from astroid import AstroidManager from astroid.exceptions import AstroidBuildingError
MANAGER = AstroidManager() from astroid import node_classes
from astroid import MANAGER
try: if six.PY2:
from astroid.builder import _guess_encoding from astroid.builder import _guess_encoding
except ImportError:
# XXX: With python3, tokenize.detect_encoding() is used instead. This # XXX: With python3, tokenize.detect_encoding() is used instead. This
# should do the same instead of copying/pasting legacy code... # should do the same instead of copying/pasting legacy code...
import re import re
...@@ -67,7 +63,7 @@ except ImportError: ...@@ -67,7 +63,7 @@ except ImportError:
match = _ENCODING_RGX.match(line) match = _ENCODING_RGX.match(line)
if match is not None: if match is not None:
return match.group(1) return match.group(1)
def string_build(self, data, modname='', path=None): def string_build(self, data, modname='', path=None):
""" """
build astroid from source code string and return rebuilded astroid build astroid from source code string and return rebuilded astroid
...@@ -101,11 +97,11 @@ def string_build(self, data, modname='', path=None): ...@@ -101,11 +97,11 @@ def string_build(self, data, modname='', path=None):
LOG("Products.ERP5Type.patches.pylint", WARNING, LOG("Products.ERP5Type.patches.pylint", WARNING,
"%s: Considered as not importable: Wrong encoding? (%r)" % "%s: Considered as not importable: Wrong encoding? (%r)" %
(modname, exc)) (modname, exc))
raise AstroidBuildingException(exc) raise AstroidBuildingError(exc)
module = self._data_build(data, modname, path) module = self._data_build(data, modname, path)
module.file_bytes = data module.file_bytes = data
return self._post_build(module, encoding) return self._post_build(module, encoding)
AstroidBuilder.string_build = string_build AstroidBuilder.string_build = string_build
# patch node_classes.const_factory not to fail on LazyModules that e.g. # patch node_classes.const_factory not to fail on LazyModules that e.g.
# pygolang installs for pytest and ipython into sys.modules dict: # pygolang installs for pytest and ipython into sys.modules dict:
...@@ -160,17 +156,17 @@ def _buildAstroidModuleFromComponentModuleName(modname): ...@@ -160,17 +156,17 @@ def _buildAstroidModuleFromComponentModuleName(modname):
obj = getattr(component_tool, obj = getattr(component_tool,
component_id.replace('_version', '', 1)) component_id.replace('_version', '', 1))
except AttributeError: except AttributeError:
raise AstroidBuildingException() raise AstroidBuildingError()
if obj.getValidationState() in ('modified', 'validated'): if obj.getValidationState() in ('modified', 'validated'):
component_obj = obj component_obj = obj
else: else:
raise AstroidBuildingException() raise AstroidBuildingError()
else: else:
try: try:
package, reference = component_id.split('.', 1) package, reference = component_id.split('.', 1)
except ValueError: except ValueError:
raise AstroidBuildingException() raise AstroidBuildingError()
for version in portal.getVersionPriorityNameList(): for version in portal.getVersionPriorityNameList():
try: try:
obj = getattr(component_tool, obj = getattr(component_tool,
...@@ -189,11 +185,12 @@ def _buildAstroidModuleFromComponentModuleName(modname): ...@@ -189,11 +185,12 @@ def _buildAstroidModuleFromComponentModuleName(modname):
return module return module
if component_obj is None: if component_obj is None:
raise AstroidBuildingException() raise AstroidBuildingError()
if six.PY3:
return AstroidBuilder(MANAGER).module_build(
importlib.import_module(modname))
# module_build() could also be used but this requires importing
# the ZODB Component and also monkey-patch it to support PEP-302
# for __file__ starting with '<'
module = AstroidBuilder(MANAGER).string_build( module = AstroidBuilder(MANAGER).string_build(
component_obj.getTextContent(validated_only=True), component_obj.getTextContent(validated_only=True),
modname) modname)
...@@ -201,7 +198,7 @@ def _buildAstroidModuleFromComponentModuleName(modname): ...@@ -201,7 +198,7 @@ def _buildAstroidModuleFromComponentModuleName(modname):
def fail_hook_erp5_component(modname): def fail_hook_erp5_component(modname):
if not modname.startswith('erp5.'): if not modname.startswith('erp5.'):
raise AstroidBuildingException() raise AstroidBuildingError()
if (modname in ('erp5.portal_type', if (modname in ('erp5.portal_type',
'erp5.component', 'erp5.component',
...@@ -229,8 +226,11 @@ MANAGER.register_failed_import_hook(fail_hook_erp5_component) ...@@ -229,8 +226,11 @@ MANAGER.register_failed_import_hook(fail_hook_erp5_component)
## transforms but this would require either checking dynamically which ## transforms but this would require either checking dynamically which
## attributes has been added (much more complex than the current approach) ## attributes has been added (much more complex than the current approach)
## or listing them statically (inconvenient). ## or listing them statically (inconvenient).
from astroid.exceptions import NotFoundError from astroid.exceptions import AstroidError, NotFoundError
from astroid.scoped_nodes import Module if six.PY2:
from astroid.scoped_nodes import Module
else:
from astroid.nodes import Module
Module_getattr = Module.getattr Module_getattr = Module.getattr
def _getattr(self, name, *args, **kw): def _getattr(self, name, *args, **kw):
try: try:
...@@ -238,8 +238,12 @@ def _getattr(self, name, *args, **kw): ...@@ -238,8 +238,12 @@ def _getattr(self, name, *args, **kw):
except NotFoundError as e: except NotFoundError as e:
if self.name.startswith('erp5.'): if self.name.startswith('erp5.'):
raise raise
if six.PY3 and self.name == 'numpy' or self.name.startswith('numpy.'):
real_module = __import__(self.name, fromlist=[self.name], level=0) raise
real_module = __import__(
self.name,
fromlist=[self.name] if six.PY2 else [name],
level=0)
try: try:
attr = getattr(real_module, name) attr = getattr(real_module, name)
except AttributeError: except AttributeError:
...@@ -255,13 +259,21 @@ def _getattr(self, name, *args, **kw): ...@@ -255,13 +259,21 @@ def _getattr(self, name, *args, **kw):
except AttributeError: except AttributeError:
from astroid import nodes from astroid import nodes
if isinstance(attr, dict): if isinstance(attr, dict):
ast = nodes.Dict(attr) if six.PY2:
ast = nodes.Dict(attr)
else:
ast = nodes.Dict(attr, 0, None, end_lineno=0, end_col_offset=0)
elif isinstance(attr, list): elif isinstance(attr, list):
ast = nodes.List(attr) ast = nodes.List(attr)
elif isinstance(attr, tuple): elif isinstance(attr, tuple):
ast = nodes.Tuple(attr) ast = nodes.Tuple(attr)
elif isinstance(attr, set): elif isinstance(attr, set):
ast = nodes.Set(attr) if six.PY2:
ast = nodes.Set(attr)
else:
ast = nodes.Set(attr, 0, None, end_lineno=0, end_col_offset=0)
elif isinstance(attr, types.ModuleType):
ast = MANAGER.ast_from_module(attr)
else: else:
try: try:
ast = nodes.Const(attr) ast = nodes.Const(attr)
...@@ -272,16 +284,29 @@ def _getattr(self, name, *args, **kw): ...@@ -272,16 +284,29 @@ def _getattr(self, name, *args, **kw):
raise raise
# ast_from_class() actually works for any attribute of a Module # ast_from_class() actually works for any attribute of a Module
# (on py2 at least), but it raises some AssertionError when the class
# is defined dynamically, for example with zope.hookable.hookable,
# which (in version 6.0) is defined as:
#
# if _PURE_PYTHON or _c_hookable is None:
# hookable = _py_hookable
# else: # pragma: no cover
# hookable = _c_hookable
try: try:
ast = MANAGER.ast_from_class(attr) ast = MANAGER.ast_from_class(attr)
except AstroidBuildingException: except (AstroidError, AssertionError):
raise e if six.PY2:
raise e
try:
ast = next(MANAGER.infer_ast_from_something(attr))
except AstroidError:
raise e
self.locals[name] = [ast] self.locals[name] = [ast]
return [ast] return [ast]
Module.getattr = _getattr Module.getattr = _getattr
if sys.version_info < (2, 8): if six.PY2:
from astroid.node_classes import From from astroid.node_classes import From
def _absolute_import_activated(self): def _absolute_import_activated(self):
if (self.name.startswith('checkPythonSourceCode') or if (self.name.startswith('checkPythonSourceCode') or
...@@ -428,7 +453,7 @@ _inspected_modules = {} ...@@ -428,7 +453,7 @@ _inspected_modules = {}
def fail_hook_BTrees(modname): def fail_hook_BTrees(modname):
# Only consider BTrees.OOBTree pattern # Only consider BTrees.OOBTree pattern
if not modname.startswith('BTrees.') or len(modname.split('.')) != 2: if not modname.startswith('BTrees.') or len(modname.split('.')) != 2:
raise AstroidBuildingException() raise AstroidBuildingError()
if modname not in _inspected_modules: if modname not in _inspected_modules:
try: try:
modcode = build_stub( modcode = build_stub(
...@@ -444,7 +469,7 @@ def fail_hook_BTrees(modname): ...@@ -444,7 +469,7 @@ def fail_hook_BTrees(modname):
else: else:
astng = _inspected_modules[modname] astng = _inspected_modules[modname]
if astng is None: if astng is None:
raise AstroidBuildingException('Failed to import module %r' % modname) raise AstroidBuildingError('Failed to import module %r' % modname)
return astng return astng
MANAGER.register_failed_import_hook(fail_hook_BTrees) MANAGER.register_failed_import_hook(fail_hook_BTrees)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment