summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander.sulfrian@fu-berlin.de>2015-07-28 17:55:17 +0200
committerAlexander Sulfrian <alexander.sulfrian@fu-berlin.de>2017-03-29 13:29:59 +0200
commit2e3ac3bd311ecf4d26032cd029dcc5e92170fe7f (patch)
tree15fb9398655a37ce0d16a41acb4a5b08ce2ddffa
parent97a113956f8211a2e718afe98a623cafebc03922 (diff)
downloadbcfg2-2e3ac3bd311ecf4d26032cd029dcc5e92170fe7f.tar.gz
bcfg2-2e3ac3bd311ecf4d26032cd029dcc5e92170fe7f.tar.bz2
bcfg2-2e3ac3bd311ecf4d26032cd029dcc5e92170fe7f.zip
testsuite: Support for ancient pylint versions
For Python2.4 and Python2.5 we need very old pylint versions (0.21.x). So we have to work around some bugs: - This adds some ugly monkey patching to backport some bugfixes from newer pylint versions (that does not support Python2.4 anymore). - Another problem is, that pylint-0.24 changed its message IDs. So this translates the new IDs into the older ones, so that the old pylint can match the disabled messages. - The newer version of pylint support more messages and some of the new messages have to be disabled. The old pylint versions have to silently ignore unknown message ids. - The compatible astng version of the old pylint does not support register_transformer, so we need to build out own variant by monkey patching the ASTNGBuilder.
-rw-r--r--testsuite/ext/pylint_compat.py275
-rw-r--r--testsuite/ext/ssl_protocols.py12
-rw-r--r--testsuite/pylintrc.conf2
3 files changed, 286 insertions, 3 deletions
diff --git a/testsuite/ext/pylint_compat.py b/testsuite/ext/pylint_compat.py
new file mode 100644
index 000000000..8ccfbc89b
--- /dev/null
+++ b/testsuite/ext/pylint_compat.py
@@ -0,0 +1,275 @@
+from pylint.__pkginfo__ import version as pylint_version
+from logilab.astng.__pkginfo__ import version as astng_version
+
+def register(linter):
+ if pylint_version < '0.24.0':
+ import pylint.utils
+ orig_check_message_id = pylint.utils.MessagesHandlerMixIn.check_message_id
+ def check_message_id(self, msgid):
+ # translate the new message ids back into the old ones
+ replacements = {'12': '65', '13': '99'}
+ new = msgid[1:3]
+ if new in replacements:
+ msgid = msgid[0] + replacements[new] + msgid[3:]
+ return orig_check_message_id(self, msgid)
+ pylint.utils.MessagesHandlerMixIn.check_message_id = check_message_id
+
+ def ignore(meth, msgid, *args, **kwargs):
+ # ignore non-existent message ids in disable/enable comments
+ ignore = ['W1401', 'R0924']
+ if msgid in ignore:
+ return
+ return meth(msgid, *args, **kwargs)
+ linter._options_methods['disable'] = lambda *args, **kwargs: ignore(linter.disable, *args, **kwargs)
+ linter._options_methods['enable'] = lambda *args, **kwargs: ignore(linter.enable, *args, **kwargs)
+
+ if pylint_version < '0.22.0':
+ import pylint.checkers.exceptions
+ orig_visit_raise = pylint.checkers.exceptions.ExceptionsChecker.visit_raise
+ def visit_raise(self, node):
+ if not hasattr(node, 'type') and hasattr(node, 'exc'):
+ node.type = node.exc
+ return orig_visit_raise(self, node)
+ pylint.checkers.exceptions.ExceptionsChecker.visit_raise = visit_raise
+
+ if astng_version < '0.23':
+ import logilab.astng.scoped_nodes
+ from logilab.astng.bases import InferenceContext, InferenceError
+
+ # backport import bug fix (e642ba33ba1bdde04ac9f0c75a25dc40131c55e7)
+ def ancestors(self, recurs=True, context=None):
+ yielded = set([self])
+ if context is None:
+ context = InferenceContext()
+ for stmt in self.bases:
+ path = set(context.path)
+ try:
+ for baseobj in stmt.infer(context):
+ if not isinstance(baseobj, logilab.astng.scoped_nodes.Class):
+ # duh ?
+ continue
+ if baseobj in yielded:
+ continue # cf xxx above
+ yielded.add(baseobj)
+ yield baseobj
+ if recurs:
+ for grandpa in baseobj.ancestors(True, context):
+ if grandpa in yielded:
+ continue # cf xxx above
+ yielded.add(grandpa)
+ yield grandpa
+ except InferenceError:
+ # XXX log error ?
+ pass
+ context.path = path
+ logilab.astng.scoped_nodes.Class.ancestors = ancestors
+
+ # support for classpropery (d110bcf2de4b8bc48e41638cf430f17c5714ffbc)
+ try:
+ from logilab.astng.rebuilder import TreeRebuilder
+ except:
+ try:
+ from logilab.astng._nodes_ast import TreeRebuilder
+ except:
+ from logilab.astng._nodes_compiler import TreeRebuilder
+ from logilab.astng import nodes
+
+ orig_visit_function = TreeRebuilder.visit_function
+ def visit_function(self, node, parent):
+ newnode = orig_visit_function(self, node, parent)
+ if newnode.decorators is not None:
+ for decorator_expr in newnode.decorators.nodes:
+ if isinstance(decorator_expr, nodes.Name):
+ if decorator_expr.name == 'classproperty':
+ newnode.type = 'classmethod'
+ return newnode
+ TreeRebuilder.visit_function = visit_function
+
+ if astng_version < '0.22':
+ from logilab.astng import nodes
+ from logilab.astng.bases import _infer_stmts, copy_context, path_wrapper, \
+ InferenceError, NotFoundError
+ from logilab.astng._exceptions import ASTNGBuildingException
+ import logilab.astng.scoped_nodes
+ from logilab.astng.node_classes import List, DelName
+
+ # backport of 11886551cfdcf969f0a661f8ab63c1fa1a6dd399 with
+ # a bit revert of af896e299ce5e381a928a77a9c28941cad90a243
+ def infer_from(self, context=None, asname=True):
+ name = context.lookupname
+ if name is None:
+ raise InferenceError()
+ if asname:
+ name = self.real_name(name)
+ module = self.do_import_module(self.modname)
+ try:
+ context = copy_context(context)
+ context.lookupname = name
+ return _infer_stmts(module.getattr(name, ignore_locals=module is self.root()), context)
+ except NotFoundError:
+ raise InferenceError(name)
+ nodes.From.infer = path_wrapper(infer_from)
+
+ def getattr(self, name, context=None, ignore_locals=False):
+ if name in self.special_attributes:
+ if name == '__file__':
+ return [cf(self.file)] + self.locals.get(name, [])
+ if name == '__path__' and self.package:
+ return [List()] + self.locals.get(name, [])
+ return std_special_attributes(self, name)
+ if not ignore_locals and name in self.locals:
+ return self.locals[name]
+ if self.package:
+ try:
+ return [self.import_module(name, relative_only=True)]
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except:
+ pass
+ raise NotFoundError(name)
+ logilab.astng.scoped_nodes.Module.getattr = logilab.astng.scoped_nodes.remove_nodes(getattr, DelName)
+
+ if astng_version < '0.21.1':
+ # backport of 3d463da455e33e7ddc53a295b6a33db7b9e4288b
+ from logilab.astng.scoped_nodes import Function
+ from logilab.astng.rebuilder import RebuildVisitor
+ from logilab.astng.bases import YES, Instance
+
+ orig_init = Function.__init__
+ def init(self, name, doc):
+ orig_init(self, name, doc)
+ self.instance_attrs = {}
+ Function.__init__ = init
+
+ orig_getattr = Function.getattr
+ def getattr(self, name, context=None):
+ if name != '__module__' and name in self.instance_attrs:
+ return self.instance_attrs[name]
+ return orig_getattr(self, name, context)
+ Function.getattr = getattr
+
+ def delayed_assattr(self, node):
+ """visit a AssAttr node -> add name to locals, handle members
+ definition
+ """
+ try:
+ frame = node.frame()
+ for infered in node.expr.infer():
+ if infered is YES:
+ continue
+ try:
+ if infered.__class__ is Instance:
+ infered = infered._proxied
+ iattrs = infered.instance_attrs
+ elif isinstance(infered, Instance):
+ # Const, Tuple, ... we may be wrong, may be not, but
+ # anyway we don't want to pollute builtin's namespace
+ continue
+ elif infered.is_function:
+ iattrs = infered.instance_attrs
+ else:
+ iattrs = infered.locals
+ except AttributeError:
+ # XXX log error
+ #import traceback
+ #traceback.print_exc()
+ continue
+ values = iattrs.setdefault(node.attrname, [])
+ if node in values:
+ continue
+ # get assign in __init__ first XXX useful ?
+ if frame.name == '__init__' and values and not \
+ values[0].frame().name == '__init__':
+ values.insert(0, node)
+ else:
+ values.append(node)
+ except InferenceError:
+ pass
+ RebuildVisitor.delayed_assattr = delayed_assattr
+
+ if astng_version < '0.20.4':
+ try:
+ from logilab.astng._nodes_ast import TreeRebuilder, _lineno_parent
+ except:
+ from logilab.astng._nodes_compiler import TreeRebuilder
+ _lineno_parent = (lambda *args: TreeRebuilder._set_infos(None, *args))
+ from logilab.astng import nodes
+ from logilab.astng.bases import NodeNG, Instance
+ from logilab.astng.mixins import ParentAssignTypeMixin
+
+ class Set(NodeNG, Instance, ParentAssignTypeMixin):
+ _astng_fields = ('elts',)
+ elts = None
+
+ def pytype(self):
+ return '__builtin__.set'
+
+ def itered(self):
+ return self.elts
+
+ def visit_set(self, node, parent):
+ newnode = Set()
+ _lineno_parent(node, newnode, parent)
+ newnode.elts = [self.visit(child, newnode) for child in node.elts]
+ newnode.set_line_info(newnode.last_child())
+ return newnode
+ TreeRebuilder.visit_set = visit_set
+
+ def visit_setcomp(self, node, parent):
+ newnode = nodes.SetComp()
+ _lineno_parent(node, newnode, parent)
+ newnode.elt = self.visit(node.elt, newnode)
+ newnode.generators = [self.visit(child, newnode)
+ for child in node.generators]
+ newnode.set_line_info(newnode.last_child())
+ return newnode
+ TreeRebuilder.visit_setcomp = visit_setcomp
+
+ class DictComp(NodeNG):
+ _astng_fields = ('key', 'value', 'generators')
+ key = None
+ value = None
+ generators = None
+
+ def visit_dictcomp(self, node, parent):
+ newnode = DictComp()
+ _lineno_parent(node, newnode, parent)
+ newnode.key = self.visit(node.key, newnode)
+ newnode.value = self.visit(node.value, newnode)
+ newnode.generators = [self.visit(child, newnode)
+ for child in node.generators]
+ newnode.set_line_info(newnode.last_child())
+ return newnode
+ TreeRebuilder.visit_dictcomp = visit_dictcomp
+
+ # backport of bfe9e5c53cfb75c3b45ebb5cb8e8902464782c7d
+ from logilab.astng.node_classes import From
+ orig_from_init = From.__init__
+ def from_init(self, fromname, names, level=0):
+ orig_from_init(self, fromname or '', names, level)
+ From.__init__ = from_init
+
+ # partial backport of 6d59ad07d722d01e458aaf8fd14fd7dfc7ebaa6e
+ from logilab.astng.scoped_nodes import Module
+ orig_absolute_modname = Module.absolute_modname
+ def absolute_modname(self, modname, level):
+ result = orig_absolute_modname(self, modname, level)
+ if result[-1] == '.':
+ return result[:-1]
+ return result
+ Module.absolute_modname = absolute_modname
+
+ # python2.4 compatibility (no super on old-style classes)
+ from logilab.astng.bases import Proxy, UnboundMethod
+
+ def unbound_igetattr(self, name, context=None):
+ if name == 'im_func':
+ return iter((self._proxied,))
+ return Proxy.igetattr(self, name, context)
+ UnboundMethod.igetattr = unbound_igetattr
+
+ def unbound_getattr(self, name, context=None):
+ if name == 'im_func':
+ return [self._proxied]
+ return Proxy.getattr(self, name, context)
+ UnboundMethod.getattr = unbound_getattr
diff --git a/testsuite/ext/ssl_protocols.py b/testsuite/ext/ssl_protocols.py
index 66068d2a9..a56293669 100644
--- a/testsuite/ext/ssl_protocols.py
+++ b/testsuite/ext/ssl_protocols.py
@@ -1,5 +1,5 @@
try:
- from logilab.astng import MANAGER, scoped_nodes, node_classes
+ from logilab.astng import MANAGER, builder, scoped_nodes, node_classes
PYLINT=0
except ImportError:
from astroid import MANAGER, scoped_nodes, node_classes
@@ -12,6 +12,14 @@ def ssl_transform(module):
def register(linter):
if PYLINT == 0:
- MANAGER.register_transformer(ssl_transform)
+ if hasattr(MANAGER, 'register_transformer'):
+ MANAGER.register_transformer(ssl_transform)
+ else:
+ safe = builder.ASTNGBuilder.string_build
+ def _string_build(self, data, modname='', path=None):
+ if modname == 'ssl':
+ data += '\n\nPROTOCOL_SSLv23 = 0\nPROTOCOL_TLSv1 = 0'
+ return safe(self, data, modname, path)
+ builder.ASTNGBuilder.string_build = _string_build
else:
MANAGER.register_transform(scoped_nodes.Module, ssl_transform)
diff --git a/testsuite/pylintrc.conf b/testsuite/pylintrc.conf
index 50ece77db..ce7e407df 100644
--- a/testsuite/pylintrc.conf
+++ b/testsuite/pylintrc.conf
@@ -19,7 +19,7 @@ persistent=no
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
-load-plugins=ext.exception_messages,ext.ssl_protocols
+load-plugins=ext.exception_messages,ext.ssl_protocols,ext.pylint_compat
[MESSAGES CONTROL]