.. -*- coding: utf-8 -*- project logilab-astng ===================== :creation date: 2006/09/26 Python Abstract Syntax Tree New Generation The aim of this module is to provide a common base representation of python source code for projects such as pychecker, pyreverse, pylint... Well, actually the development of this library is essentialy governed by pylint's needs. It rebuilds the abstract syntax tree created by the *_ast* or *compiler.ast* module, using ASTNG nodes, and creates additional nodes by inspecting living object. version 0.16.1 -------------- :publication date: 2006/09/25 :expected date: n/a version 0.16.2 -------------- :publication date: 2006/11/16 :expected date: n/a ticket #3133: py2.3 compat ~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved GenExpr import is breaking python 2.3 compat ticket #3137: update to avoid deprecation warnings with logilab-common 0.21 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 0.250 :state: resolved version 0.16.3 -------------- :publication date: 2006/11/23 :expected date: n/a ticket #3165: simple inference for subscription and loop assigments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.500 :state: resolved :: def test_simple_subscript(self): data = ''' a = [1, 2, 3][0] b = (1, 2, 3)[1] c = (1, 2, 3)[-1] d = a + b + c print d ''' astng = builder.string_build(data, __name__, __file__) self.failUnlessEqual([i.value for i in get_name_node(astng, 'a', -1).infer()], [1]) self.failUnlessEqual([i.value for i in get_name_node(astng, 'b', -1).infer()], [2]) self.failUnlessEqual([i.value for i in get_name_node(astng, 'c', -1).infer()], [3]) # kill me #self.failUnlessEqual([i.value for i in get_name_node(astng, 'd', -1).infer()], # [6]) def test_simple_for(self): data = ''' for a in [1, 2, 3]: print a for b,c in [(1,2), (3,4)]: print b print c print [(d,e) for e,d in ([1,2], [3,4])] ''' astng = builder.string_build(data, __name__, __file__) self.failUnlessEqual([i.value for i in get_name_node(astng, 'a', -1).infer()], [1, 2, 3]) self.failUnlessEqual([i.value for i in get_name_node(astng, 'b', -1).infer()], [1, 3]) self.failUnlessEqual([i.value for i in get_name_node(astng, 'c', -1).infer()], [2, 4]) self.failUnlessEqual([i.value for i in get_name_node(astng, 'd', -1).infer()], [2, 4]) self.failUnlessEqual([i.value for i in get_name_node(astng, 'e', -1).infer()], [1, 3]) def test_simple_for_genexpr(self): if sys.version_info < (2, 4): return data = ''' print ((d,e) for e,d in ([1,2], [3,4])) ''' astng = builder.string_build(data, __name__, __file__) self.failUnlessEqual([i.value for i in get_name_node(astng, 'd', -1).infer()], [2, 4]) self.failUnlessEqual([i.value for i in get_name_node(astng, 'e', -1).infer()], [1, 3]) version 0.17.0 -------------- more inference ! :publication date: 2007/03/01 :expected date: n/a ticket #3291: failure of inference on overloaded operators ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved http://lists.logilab.org/pipermail/python-projects/2006-December/001087.html probably the cause of :eid:`3216` but filed separately in case it is different Comments :: On 2007/02/19 12:33 - sthenault wrote : the submitted test case is now handled by astng, but it doesn't resolve the original numarray problem since it still doesn't manage to get the type returned by randint (ie both int and a YES object are returned) ticket #3561: "open" builtin not inferable ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved ticket #3289: python runs FileA.funcA() but pylint thinks it is using the Test.FileA list ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved http://lists.logilab.org/pipermail/python-projects/2006-December/001114.html ticket #3261: can't find a decorator, when it is defined as a member of the class where it is used ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved :: class TC(object): def deco(func): return func @deco def func(self): pass This one now results in :: pylintbug.py:1: [E0602, TC.func] Undefined variable 'deco' while deco is defined and the reference does not occure in line 1 (this is another bug actually...) ticket #3531: Type inference on factory classmethod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 1.000 :state: resolved Maarten ter Huurne posted :: class Super(object): @classmethod def instance(cls): return cls() class Sub(Super): def method(self): print 'method called' Sub.instance().method() It prints: :: E1101: 10: Instance of 'Super' has no 'method' member The return type of "Sub.instance()" is "Sub", not "Super", so the method call is valid, as you can see when you run this program. So it seems that ASTNG infers the wrong type: "cls" is the class on which the class method is called, which is not necessarily the class in which it is defined. Comments :: On 2007/02/09 09:17 - sthenault wrote : huum, remember astng inference is dumb. I guess it should at least see that it may be wrong and return a YES object as well so that pylint don't issue a false positive. ticket #2453: handle external modification of a class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 0.750 :state: resolved for instance :: def new_class_method(self, blabla): XXXX classe.new_method = new_class_method should add new_method to classe's dict. This has to be handled with care since : * when one is looking a class, it may find local statements which are not in the same class / module * bootstrap problem version 0.17.1 -------------- :publication date: 2007/06/07 :expected date: n/a ticket #3651: crash when callable as defaut arg ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved Marteen ter Huur reported : If I feed the following program to PyLint: :: def f(g = lambda: None): g().x It crashes on the statement "i = self.argnames.index(argname)" in ASTNG, because "argname" does not exist in "self.argnames". ticket #3670: subscription inference crash in some cases ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved Marteen ter Huur reported : When checking the following program with rpython enabled: :: def f(x): a = ()[x] I get the following error : :: File "/usr/lib/python2.4/site-packages/logilab/astng/inference.py", line 661, in tl_getitem return self.nodes[index] TypeError: tuple indices must be integers ticket #3673: Lambda instance has no attribute 'pytype' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved Comments :: On 2007/06/08 13:55 - afayolle wrote : I don't know how to validate the resulution of this bug. ticket #3701: crash on numpy ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved `pylint logilab.hmm.hmm` is crashing for instance version 0.17.2 -------------- :publication date: 2008/01/14 :expected date: n/a ticket #4057: py2.5: "with" statement unsupported ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved and that may at least cause some crash like Marc Rintsh reported : :: line 377, in assend_ass_type return self.parent.ass_type() AttributeError: With instance has no attribute 'ass_type' version 0.17.3 -------------- :publication date: 2008/09/10 :expected date: n/a ticket #5955: bugfixes ~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.250 :state: resolved see ChangeLog version 0.17.4 -------------- :publication date: 2008/11/20 :expected date: n/a ticket #5010: pb w/ py2.5 absolute import ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.200 :state: resolved Here is a simplified example that exhibits the problem. Parent is the parent package to sub-packages A and B. Sub-Package A: Parent/A/__init__.py contains "import a" Parent/A/a.py contains: :: from __future__ import absolute_import from ..B import b class aClass(b.bClass): def __init__(self): b.bClass.__init__(self) def foo(self): print self.x print self.y print self.z Sub-Package B: Parent/B/__init__.py contains "import b" Parent/B/b.py contains: :: class bClass: def __init__(self): self.x = 0 self.y = [] self.z = '' The Parent package is located in my sys.path. The above code runs just fine: :: >>> import Parent.A >>> a = Parent.A.a.aClass(1) >>> a.foo() 0 However, when I run pylint for A/a.py it gives me :: F0401: 9: Unable to import 'B.b' (No module named B) and therefore of course the ensuing errors: E1101: 14:aClass.foo: Instance of 'aClass' has no 'x' member E1101: 15:aClass.foo: Instance of 'aClass' has no 'y' member E1101: 16:aClass.foo: Instance of 'aClass' has no 'z' member If I change the import syntax in Parent/A/a.py to use "from Parent.B import b" all errors go away. This seems to indicate a problem with intra-sub-package relative imports. ticket #5571: Crash on module-level @staticmethod/@classmethod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.100 :state: resolved Maarten reported: When running pylint on this program: :: @staticmethod def f(): pass I get the following exception trace: :: Traceback (most recent call last): File "/usr/bin/pylint", line 4, in lint.Run(sys.argv[1:]) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 901, in __init__ linter.check(args) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 492, in check self.check_astng_module(astng, checkers) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 602, in check_astng_module if implements(checker, IASTNGChecker)]) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 619, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 619, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 616, in astng_events checker.visit(astng) File "/usr/lib/python2.5/site-packages/logilab/astng/utils.py", line 84, in visit method(node) File "/usr/lib/python2.5/site-packages/pylint/checkers/classes.py", line 206, in visit_function self._check_first_arg_for_type(node, klass.type == 'metaclass') AttributeError: Module instance has no attribute 'type' Although it is a bit unusual to have a static method at the module level, the Python interpreter accepts it. The same crash happens on @classmethod when used at the model level. I had a look at checkers/classes.py to see if fixing it would be easy, but it wasn't clear to me what the proper approach would be: - let is_method() should return False in cases like this - don't assume that a method's parent is always a class As a quick fix, I settled on the latter: :: klass_type = getattr(klass, 'type', None) # "klass" might not be a class And replace "klass.type" by "klass_type", once in checkers/classes.py and once in checkers/variables.py. ticket #6015: W0631 false positive (Using possibly undefined loop variable) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.200 :state: resolved On the following program: print [ i for i in range(10) ] print [ i for i in range(10) ] I get the warning: W: 2: Using possibly undefined loop variable 'i' Versions: pylint 0.15.0, astng 0.17.3, common 0.35.0 Python 2.5.1 (r251:54863, Mar 7 2008, 03:41:45) [GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] Looking at the implementation of W0631 (in checkers/variables.py), the first step is to get the list of assignment statements for variable "i" using "node.lookup(name)[1]". When I print the value of this expression for line 2 of the test case above, it contains two assignments: the "for" on line 1 and the "for" on line 2. However, since "i" is used inside the "for" on line 2, the assignment is guaranteed to be from line 2 as well: if the sequenced that is iterated through is empty, the expression "i" would not be evaluated. So I think lookup() from astng is returning the wrong result: if a loop variable is used inside the expression part of a list comprehension / generator expression, it is guaranteed to be defined by that same list comprehension / generator expression. version 0.18.0 -------------- :publication date: 2009/03/20 :expected date: n/a ticket #4589: No line number for Lambda ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.000 :state: resolved :: On 11/19/07, Jeremy Hylton wrote: > This is a bug report for pylint version 0.13.2. We've got a custom > checker that adds a message for lambda nodes that are too long. In > some cases (perhaps all?) the node passed to add_message() has > fromlineno set to None. In those cases, the line number for the > warning message is 1. I see there's some commented out code in > add_message() that seems to concern itself with the same problem. I > have that changing add_message to consider lineno as well seemed to > fix our problem. > > def add_message(self, msg_id, line=None, node=None, args=None): > """add the message corresponding to the given id. > > If provided, msg is expanded using args > > astng checkers should provide the node argument, raw checkers should > provide the line argument. > """ > if line is None and node is not None: > line = node.fromlineno or node.lineno > > Is there a better way to fix this problem? ticket #904: integrates with python 2.5 AST changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 20.000 :state: resolved citing Neal Norwitz: I'm not sure if anyone here is following the AST discussion on python-dev, but it would be great if you had any input. pylint is a pretty big consumer of the compiler module and the decisions with respect to the AST could impact you. http://mail.python.org/pipermail/python-dev/2006-February/060994.html Comments :: On 2009/02/09 11:04 - eanclin wrote : using the _ast module (>=2.5) is necessary for py3k compatibility; on the other hand we want to stay compiler compatible. version 0.19.0 -------------- :publication date: 2009/03/25 :expected date: n/a ticket #4020: missing egg support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 1.000 :state: resolved for example, I have a module named 'itcc.core', more information as belows. :: $ python -c "import sys; import itcc.core; print sys.modules['itcc.core']" but pylint does not support this kind of module, and give E0611 on this. :: $ echo "import itcc.core" > bug.py $ pylint bug.py ************* Module bug C0111: 1: Missing docstring E0611: 1: No name 'core' in module 'itcc' W0611: 1: Unused import itcc NOTE: this is more likely a logilab-astng or logilab-common pb ticket #8603: 2.6 _ast nodes changed to type, can't be monkey-patched ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 1.000 :state: resolved ticket #3873: better handling of del statements ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.500 :state: resolved In the following code snippet, astng should be able to see that after the del statement, the deleted symbol is not reachable:: class Frobble: pass Frobble.mumble = True del Frobble def run(): f = Frobble() ticket #8724: could somewhat understant the property decorator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 0.200 :state: resolved eg return results of calling the decorated function. version 0.19.1 -------------- :publication date: 2009/08/27 :expected date: n/a ticket #8946: infinite recursion during inference ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.500 :state: rejected Brian reported on python-projects I have a pylint bug to report (actually probably astng). The type inferencing step gets into an infinite recursive loop under a certain condition, which I have isolated: :: mkdir P echo " def p(): from P import M M.foo = None " > P/__init__.py echo " import P P.foo = None " > P/M.py pylint P All good the first time through (no .pyc files). Now run pylint again (__init__.pyc left by first run)... OOPS! Changing "from P import M" to "import P.M as M" makes the problem go away as well. This is with pylint-0.18.0, logilab-astng-0.19.0, logilab-common-0.39.0, and python-2.5 under Linux 2.6.18-8.1.10.el5.x86_64. ticket #10020: twhen building from living object, __name__ may be None ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.100 :state: resolved erroenously, but we shouldn't fail ticket #8771: crash on yield expression ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 1.000 :state: resolved Maarteen on python-projects... Please consider this program: .. sourcecode:: python def f(): yield 45 x = yield 123 When running pylint on it, it crashes with this backtrace:: Traceback (most recent call last): File "/usr/bin/pylint", line 4, in lint.Run(sys.argv[1:]) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 881, in __init__ linter.check(args) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 500, in check self.check_astng_module(astng, checkers) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 577, in check_astng_module if implements(checker, IASTNGChecker)]) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 594, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 594, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 594, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/usr/lib/python2.5/site-packages/pylint/lint.py", line 591, in astng_events checker.visit(astng) File "/usr/lib/python2.5/site-packages/logilab/astng/utils.py", line 320, in visit method(node) File "/usr/lib/python2.5/site-packages/pylint/checkers/format.py", line 267, in visit_default prev_sibl = node.previous_sibling() File "/usr/lib/python2.5/site-packages/logilab/astng/nodes.py", line 251, in previous_sibling stmts = self.parent.child_sequence(self) File "/usr/lib/python2.5/site-packages/logilab/astng/nodes.py", line 216, in child_sequence raise ASTNGError(msg % (repr(child), repr(self))) logilab.astng._exceptions.ASTNGError: Could not found <_ast.Yield object at 0x1034890> in <_ast.Assign object at 0x1034810>'s children In previous_sibling(), the Yield node is looked up in its parent. That works for line 2 where yield is used as a statement, but fails for line 3 where yield is used as an expression. The _ast module always considers yield an expression (both for the line 2 and line 3 case). Taking that as inspiration, I moved "Yield" from STMT_NODES to ALL_NODES in "nodes.py" in astng. That fixes the crash, but I don't know if there is other code that will break when "yield" is never considered a statement. By the way, the docstring of previous_sibling() looks like it belongs with next_sibling() and vice versa. Comments :: On 2009/03/27 09:53 - sthenault wrote : maarteen follow-ups: I found a false positive caused by "yield" not being considered a statement: .. sourcecode:: python def f(seq): for val in seq: pass for val in seq: yield val :: W0631: 5:f: Using possibly undefined loop variable 'val' If I revert the change I made to astng, the warning goes away. Also, if I replace "yield" by "print", the warning goes away. Another false positive: .. sourcecode:: python def f(): x = 12 yield x :: E0601: 3:f: Using variable 'x' before assignment This false positive disappears when I revert the changes I made in "nodes.py", but then the crashes return on other parts of the code. So I'll continue looking for a better workaround. Any suggestions how to approach this would be most welcome. ticket #9891: help(logilab.astng) throws TypeError ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.200 :state: resolved :: >>> import logilab.astng >>> help(logilab.astng) Traceback (most recent call last): File "", line 1, in File "/usr/lib/python2.5/site.py", line 342, in __call__ return pydoc.help(*args, **kwds) File "/usr/lib/python2.5/pydoc.py", line 1647, in __call__ self.help(request) File "/usr/lib/python2.5/pydoc.py", line 1691, in help else: doc(request, 'Help on %s:') File "/usr/lib/python2.5/pydoc.py", line 1482, in doc pager(title % desc + '\n\n' + text.document(object, name)) File "/usr/lib/python2.5/pydoc.py", line 324, in document if inspect.ismodule(object): return self.docmodule(*args) File "/usr/lib/python2.5/pydoc.py", line 1071, in docmodule inspect.getclasstree(classlist, 1), name)] File "/usr/lib/python2.5/inspect.py", line 656, in getclasstree for parent in c.__bases__: TypeError: '_Yes' object is not iterable ticket #10024: line numbering bug with try/except/finally ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.200 :state: resolved ticket #9588: false positive E1101 for augmented assignment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.200 :state: resolved Tetsushi reported: I encountered a false positive E1101 for augmented assignment. See the following sample code. .. sourcecode:: python """ False positive case of E1101: The error is triggered when the attribute set in the base class is modified with augmented assignment in a derived class. """ class BaseClass(object): "The base class" def __init__(self): "Set an attribute." self.e1101 = 1 class FalsePositiveClass(BaseClass): "The first derived class which triggers the false positive" def __init__(self): "Augmented assignment triggers E1101." BaseClass.__init__(self) self.e1101 += 1 def countup(self): "Consequently this also triggers E1101." self.e1101 += 1 class NegativeClass(BaseClass): "The second derived class, which does not trigger the error E1101" def __init__(self): "Ordinary assignment is OK." BaseClass.__init__(self) self.e1101 = self.e1101 + 1 def countup(self): "No problem." self.e1101 += 1 :pylint: 0.18.0 :astng: 0.19.0 :common: 0.41.0 :Python: 2.5.4 ticket #5568: py2.5 relative import support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 0.500 :state: deprecated Comments :: On 2008/09/17 11:58 - eanclin wrote : check Marteen patch in pylint which add some support for new relative import syntax. On 2008/11/19 13:40 - sthenault wrote : part of the job is done (see :eid:`5010`) though some stuff missing. For instance when "from __future__ import absolute_import" is there, non explicit relative imports should fail. version 0.19.2 -------------- :publication date: 2009/12/18 :expected date: n/a ticket #18311: pylint is slower with astng 0.19.1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.000 :state: rejected With logilab-astng 0.19.1, pylint is significantly slower when dealing with multiple files at a time. The following tests use pylint 0.18.0 and logilab-astng 0.19.1 and logilab-astng 0.19.0, but the effect is also very obvious with pylint 0.18.1. Timing values on one of my projects:: $ time ~/tmp/pylint-0.18.0-0.19.0/bin/pylint -r n [A-F]*py > /dev/null No config file found, using default configuration real 0m11.053s user 0m10.673s sys 0m0.340s $ time ~/tmp/pylint-0.18.0-0.19.1/bin/pylint -r n [A-F]*py > /dev/null No config file found, using default configuration real 0m17.977s user 0m17.549s sys 0m0.412s $ ls [A-F]*py | wc -l 12 The time for 0.19.1 shows significant growth - for 14 files, the times are 12s for 0.19.0, but 22s for 0.19.1, and for all 16 files, 14s versus 50s. Memory usage for pylint with 0.19.1 seems larger as well (based on watching top), but I haven't measured that accurately, The project in question uses gtk quite extensively, which may be a factor in triggering this bug - the slowdown is less noticeable on my non-gtk projects. Comments :: On 2009/11/25 12:03 - drnlmza wrote : Two additional notes. I've found that the gtk examples are a good test case for demonstrating this bug. There is a memory leak involved as well - trying to run pylint on Sutekh (http://sutekh.wiki.sourceforge.net/), a pygtk project I'm involved in, crashes with a MemoryError using 0.19.1. > On 2009/11/25 19:47 - pydavid wrote : > I tried pylint on Sutekh. With 0.19.1 I confirm your observation as it took > 5155 seconds. With 0.19.0 I wasn't able to test as this release is broken. > With Mercurial tip it run fine in 77 seconds. On 2010/01/14 14:29 - afayolle wrote : Debian bug report was closed as unreproduceable with 0.19.3. ticket #13944: false positive for class/instance attributes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.200 :state: validation pending .. sourcecode:: python class Klass: aa = 0 bb = 0 cc = 0 def incr(self, val): if val > self.aa: val = self.aa if val < self.bb: val = self.bb self.aa += val self.cc += val issues:: E: 14:Klass.incr: Instance of 'Klass' has no 'aa' member E: 15:Klass.incr: Instance of 'Klass' has no 'aa' member E: 18:Klass.incr: Instance of 'Klass' has no 'aa' member E: 20:Klass.incr: Instance of 'Klass' has no 'cc' member Comments :: On 2009/11/23 19:54 - sthenault wrote : really? ticket #9515: strange message for non-class "Class baz has no egg member" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.500 :state: validation pending :: $ cat foo.py def foo(self, bar): def baz(): pass def qux(): return baz spam = bar(None, qux) spam.egg() $ pylint foo.py ************* Module foo C: 1: Black listed name "foo" C: 1: Missing docstring C: 1:foo: Black listed name "foo" C: 1:foo: Missing docstring C: 1:foo: Black listed name "bar" C: 1:foo: Black listed name "bar" C: 2:foo.baz: Black listed name "baz" C: 2:foo.baz: Missing docstring C: 4:foo.qux: Missing docstring E: 7:foo: Class 'baz' has no 'egg' member W: 1:foo: Unused argument 'self' Sorry, but this is wrong. baz is a function, not a class. Furthermore I fail to see the connection between spam and baz. Could you explain and/or fix this? Helmut ticket #18773: inference bug on class members ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.500 :state: validation pending Now to the issue at hand: Running pylint 0.18.1 (with Python 2.5.4, logilab_astng-0.19.1 and logilab_common-0.44.0) for the attached test.py generates following error (E1101 I believe):: E: 37:DataManager.TestFunc: Instance of 'DataManager' has no 'project' member This message is generated for the last line of the following snippet: .. sourcecode:: python class DataManager(object): def __init__(self): self.app = get_active_application() def TestFunc(self): app = self.app print app.project As you can see, it incorrectly reports app as DataManager instance (it is be Application instance instead - see the attached file). Also, Application class in fact has a 'project' member variable. Code itself has commented-out demonstration how to work around this error message - essentially it comprises of not using global function to acquire the Application instance. .. sourcecode:: python active_application = None def get_active_application(): global active_application return active_application class Application(object): def __init__(self): global active_application active_application = self self.project = None class Project(object): def __init__(self): pass class DataManager(object): def __init__(self, app=None): # # This causes error to be generated. Using "self.app = app" # instead will not. # self.app = get_active_application() #self.app = app print app # Suppress possible unused variable warning def TestFunc(self): app = self.app print app.project def main(): app = Application() app.project = Project() data_manager = DataManager(app) data_manager.TestFunc() main() ticket #18958: fix spelling mistakes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.100 :state: validation pending http://lists.logilab.org/pipermail/python-projects/2009-November/002100.html ticket #18953: Inference fails with augmented assignment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.500 :state: validation pending http://lists.logilab.org/pipermail/python-projects/2009-November/002088.html Comments :: On 2009/11/24 11:08 - sthenault wrote : much probably an astng pb version 0.19.3 -------------- :publication date: 2009/12/21 :expected date: n/a ticket #19415: dumb name error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.100 :state: validation pending version 0.20.0 -------------- :publication date: 2010/03/24 :expected date: n/a ticket #18186: astng crash on python2.6 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 3.000 :state: validation pending __bases__ modification produces a crash with python2.6 : traceback :: $ python2.6 ~/src/pylint/lint.py t.py Traceback (most recent call last): File "src/pylint/lint.py", line 31, in from pylint.checkers import utils File "src/pylint/checkers/__init__.py", line 39, in from logilab.astng.utils import ASTWalker File "src/logilab/astng/__init__.py", line 58, in from logilab.astng.nodes import * File "src/logilab/astng/nodes.py", line 133, in cls.__bases__ = (StmtMixIn, NodeNG) + cls.__bases__ TypeError: __bases__ assignment: 'StmtMixIn' object layout differs from 'stmt' Comments :: On 2009/11/23 19:21 - sthenault wrote : notice this is only in the code repository, not in any published release On 2009/11/26 17:58 - eanclin wrote : We have no simple solution for that. So we will rebuild entire tree. This will simplify a lot the astng code. ticket #19641: "maximum recursion depth exceeded" messages w/ python 2.6 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 1.000 :state: validation pending Daniel Harding reported on python-projects. This past June problems were reported with seeing messages like the following on stderr when running pylint: :: Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in ignored At the time it was attributed to a bug in Python 2.6.2. However, after upgrading to Python 2.6.4 I still saw the problem, so decided to investigate further, and eventually tracked it down to an infinite recursion in logilab-astng I have attached a Python file which triggers the problem. The call stack which produces the message is as follows: :: 0 File "C:\Python26\Scripts\pylint.bat", line 12, in lint.Run(sys.argv[1:]) 1 File "C:\Python26\lib\site-packages\pylint-0.18.1-py2.6.egg\pylint\lint.py", line 884, in __init__ linter.check(args) 2 File "C:\Python26\lib\site-packages\pylint-0.18.1-py2.6.egg\pylint\lint.py", line 501, in check self.check_astng_module(astng, checkers) 3 File "C:\Python26\lib\site-packages\pylint-0.18.1-py2.6.egg\pylint\lint.py", line 578, in check_astng_module if implements(checker, IASTNGChecker)]) 4 File "C:\Python26\lib\site-packages\pylint-0.18.1-py2.6.egg\pylint\lint.py", line 595, in astng_events self.astng_events(child, checkers, _reversed_checkers) 5 File "C:\Python26\lib\site-packages\pylint-0.18.1-py2.6.egg\pylint\lint.py", line 595, in astng_events self.astng_events(child, checkers, _reversed_checkers) 6 File "C:\Python26\lib\site-packages\pylint-0.18.1-py2.6.egg\pylint\lint.py", line 592, in astng_events checker.visit(astng) 7 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\utils.py", line 320, in visit method(node) 8 File "C:\Python26\lib\site-packages\pylint-0.18.1-py2.6.egg\pylint\checkers\typecheck.py", line 207, in visit_callfunc called = safe_infer(node.func) 9 File "C:\Python26\lib\site-packages\pylint-0.18.1-py2.6.egg\pylint\checkers\utils.py", line 38, in safe_infer value = inferit.next() 10 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): 11 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\infutils.py", line 231, in wrapper for node in func(*args, **kwargs): 12 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\inference.py", line 281, in infer_getattr for obj in owner.igetattr(self.attrname, context): 13 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\infutils.py", line 265, in igetattr self._wrap_attr(self.getattr(name, context, lookupclass=False), context), 14 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\infutils.py", line 248, in getattr return self._proxied.instance_attr(name, context) 15 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\inference.py", line 53, in _set_proxied if not hasattr(const, '__proxied'): 16 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\infutils.py", line 44, in __getattr__ return getattr(self._proxied, name) 17 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\inference.py", line 53, in _set_proxied if not hasattr(const, '__proxied'): 18 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\infutils.py", line 44, in __getattr__ return getattr(self._proxied, name) 19 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\inference.py", line 53, in _set_proxied if not hasattr(const, '__proxied'): 20 File "C:\Python26\lib\site-packages\logilab_astng-0.19.1-py2.6.egg\logilab\astng\infutils.py", line 44, in __getattr__ return getattr(self._proxied, name) and so on... What is happening is that Instance.getattr (entry 14 in the call stack) is accessing the _proxied attribute of the node. This attribute is actually a property whose getter is the _set_proxied function (entry 15 in the call stack). The first thing this function does is call hasattr on the node to see if it has a __proxied attribute. Because this attribute does not yet exist on the node, the node's __getattr__ method is invoked (entry 16 in the call stack). It in turn attempts to call getattr on its _proxied attribute. This in turn invokes the _proxied property's _set_proxied function (entry 17 in the call stack), resulting in infinite recursion. To reproduce, run :: pylint -r n -f parseable bug.py on the attached bug.py. I've also attached my .pylintrc. Here's the output from running pylint --version on my system:: pylint.bat 0.18.1, astng 0.19.1, common 0.45.2 Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] I don't understand what the inference system is doing well enough to know how to fix the problem, but hopefully this will give someone enough information to work on it. Comments :: On 2010/01/15 09:21 - sthenault wrote : ads by barry: I've definitely hit the same problem with the latest pylint, and I agree it has something to do with getattrs. If the devs need another test case, you can use the Mailman 3 source code: 'bzr branch lp:mailman' On 2010/01/21 14:23 - sthenault wrote : benjamin reported a while ago a similar issue : In fact I tested it a little more and it happens whenever I use some object from Panda3D (http://www.panda3d.org) Here's the code I tested which uses some object from Panda3D. It's the only test I did that gives this result .. sourcecode:: python from pandac.PandaModules import WindowProperties def main() : props = WindowProperties().getDefault() # props.setSize(800,600) return props if __name__ == '__main__': main() If I don't call "getDefault" or "setSize", I have no problem though. On 2010/02/13 02:10 - forest wrote : I get the same error, often repeated many times, from pylint 0.19.0 with python 2.6.4. This (slightly different) error also comes up a lot: Exception RuntimeError: 'maximum recursion depth exceeded in __subclasscheck__' in ignored Here is a test program which triggers the problem: def read_config( f): lines = ['junk'] for line in f: line = line.split('#', 1)[0].rstrip() # remove comments and newlines if len(line) != 0 and not line[0].isspace(): lines.append(line) # start a new config item else: lines[-1] += line # continue the previous config item pairs = [(line.split(None, 1) + [None])[:2] for line in lines] return pairs[1:] On 2010/02/15 13:36 - sthenault wrote : see for (much) more info: https://bugs.launchpad.net/pylint/+bug/456870 On 2010/04/13 10:55 - anon wrote : The error with the panda example from Benjamin is not exactly the same. And I tried with the latest revision of pylint/astng and it's still present. The traceback is : File "/usr/local/lib/python2.6/dist-packages/logilab_astng-0.20.0-py2.6.egg/logilab/astng/bases.py", line 402, in root return self.parent.root() File "/usr/local/lib/python2.6/dist-packages/logilab_astng-0.20.0-py2.6.egg/logilab/astng/bases.py", line 402, in root return self.parent.root() File "/usr/local/lib/python2.6/dist-packages/logilab_astng-0.20.0-py2.6.egg/logilab/astng/bases.py", line 402, in root return self.parent.root() File "/usr/local/lib/python2.6/dist-packages/logilab_astng-0.20.0-py2.6.egg/logilab/astng/bases.py", line 402, in root return self.parent.root() RuntimeError: maximum recursion depth exceeded ticket #20759: crash on pyreverse UNARY_OP_METHOD KeyError '~' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.100 :state: validation pending Following code will reproduce the crash:: import pyparsing as pyp class MyClass(MyBase): def xyz(self): rbrace = pyp.Literal("}").suppress() stmt = (~rbrace + keyword + ~lbrace) ticket #20464: Checking code raises “TypeError: '_Yes' object is not iterable” ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 1.000 :state: validation pending :From: Michael Hanselmann Hello Using this pylint version:: $ pylint --version pylint 0.19.0, astng 0.19.3, common 0.46.0 Python 2.5.2 The following cut-down version of a larger script raises “TypeError: '_Yes' object is not iterable”. The script as given wouldn't work, but it reproduces the error in pylint. If I change “xyz = ["foobar=%s" % options.ca,] + A + B” to “xyz = A + B + ["foobar=%s" % options.ca,]”, pylint doesn't fail with a backtrace. While the same exception, this does not seem to be a duplicate of . The full backtrace is at the end of this e-mail. .. sourcecode:: python import optparse A = [] B = [] def Test(mode): xyz = [ "foobar=%s" % options.ca, ] + A + B if options.bind is not None: xyz.append("bind=%s" % options.bind) def main(): global options parser = optparse.OptionParser() (options, args) = parser.parse_args() ticket #8348: implement Visitors / refactoring ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 5.000 :state: validation pending ASTNG needs to be refactorized to have a better readability; for instance there should be an InferenceVisitor and maybe a LookupVisitor. Comments :: On 2009/09/14 19:45 - eanclin wrote : A part of the road has been done by (1) introducing a class for each node and reducing the "monkey patching"; (2) removing the extend_class method and instead modifying the __bases__ attribute On 2010/03/17 15:21 - eanclin wrote : Another part has been done by rebuilding the tree: http://www.logilab.org/ticket/18186 ticket #21980: [Python-modules-team] Bug#573229 : Pylint hangs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.200 :state: validation pending Pylint hangs on trivial programs like this:: from matplotlib.figure import Figure Figure().add_subplot(111).xaxis ticket #20760: crash on pyreverse : AttributeError: 'Subscript' object has no attribute 'infer_lhs' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.100 :state: validation pending Following code will reproduce the crash:: class MyClass: def MyFunc(self): result['value'] -= min(result['value'], sum([row[2] for row in xyz])) version 0.20.1 -------------- :publication date: 2010/05/11 :expected date: n/a ticket #6144: pyreverse crashes on Transolution-0_4b5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.300 :state: validation pending :: parsing transolution/tm/server/__init__.py... parsing ~/var/src/Transolution-0_4b5/transolution/tm/server/__init__.py... parsing ~/var/src/Transolution-0_4b5/transolution/tm/server/estreen.py... parsing ~/var/src/Transolution-0_4b5/transolution/tm/server/basic.py... parsing ~/var/src/Transolution-0_4b5/transolution/tm/server/tm_gui.py... Traceback (most recent call last): File "/usr/bin/pyreverse", line 4, in main.Run(sys.argv[1:]) File "~/src/pylint/pyreverse/main.py", line 120, in __init__ PyreverseCommand(args) File "~/src/pylint/pyreverse/main.py", line 99, in __init__ self.run(args) File "~/src/pylint/pyreverse/main.py", line 109, in run diadefs = handler.get_diadefs(project, linker) File "~/src/pylint/pyreverse/diadefslib.py", line 225, in get_diadefs diagrams = DefaultDiadefGenerator(linker, self).visit(project) File "~/src/logilab/astng/utils.py", line 350, in visit self.visit(local_node) File "~/src/logilab/astng/utils.py", line 344, in visit methods[0](node) File "~/src/pylint/pyreverse/diadefslib.py", line 158, in visit_module self.linker.visit(node) File "~/src/logilab/astng/utils.py", line 350, in visit self.visit(local_node) File "~/src/logilab/astng/utils.py", line 344, in visit methods[0](node) File "~/src/logilab/astng/inspector.py", line 179, in visit_assname already_infered = frame.locals_type[node.name] AttributeError: 'FunctionDef' object has no attribute 'locals_type' ticket #22973: pylint crashes due to astng problem with child_sequence ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.100 :state: validation pending I am using pylint to verify my code. Pylint will analyze most of my scripts successfully, but one causes pylint to fail. Here is the traceback output: Traceback (most recent call last): File "/appl/bwc/local/bin/pylint", line 5, in ? pkg_resources.run_script('pylint==0.20.0', 'pylint') File "/appl/bwc/local/lib/python2.4/site-packages/setuptools-0.6c11-py2.4.egg/pkg_resources.py", line 489, in run_script self.require(requires)[0].run_script(script_name, ns) File "/appl/bwc/local/lib/python2.4/site-packages/setuptools-0.6c11-py2.4.egg/pkg_resources.py", line 1207, in run_script execfile(script_filename, namespace, namespace) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/EGG-INFO/scripts/pylint", line 4, in ? lint.Run(sys.argv[1:]) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/lint.py", line 885, in __init__ linter.check(args) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/lint.py", line 496, in check self.check_astng_module(astng, checkers) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/lint.py", line 572, in check_astng_module self.astng_events(astng, [checker for checker in checkers File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/lint.py", line 590, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/lint.py", line 590, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/lint.py", line 590, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/lint.py", line 590, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/lint.py", line 587, in astng_events checker.visit(astng) File "/appl/bwc/local/lib/python2.4/site-packages/logilab_astng-0.20.0-py2.4.egg/logilab/astng/utils.py", line 307, in visit method(node) File "/appl/bwc/local/lib/python2.4/site-packages/pylint-0.20.0-py2.4.egg/pylint/checkers/format.py", line 265, in visit_default prev_sibl = node.previous_sibling() File "/appl/bwc/local/lib/python2.4/site-packages/logilab_astng-0.20.0-py2.4.egg/logilab/astng/mixins.py", line 51, in previous_sibling stmts = self.parent.child_sequence(self) File "/appl/bwc/local/lib/python2.4/site-packages/logilab_astng-0.20.0-py2.4.egg/logilab/astng/bases.py", line 416, in child_sequence raise ASTNGError(msg % (repr(child), repr(self))) logilab.astng._exceptions.ASTNGError: Could not found in 's children Comments :: On 2010/04/07 21:53 - davebyrne wrote : I was able to find a small file that exhibits the issue. I pulled this out of a larger file, so it gets a few errors for items that are not defined. But it also get the crash as well. def compress_file(filename, filedate): ''' Needs Documentation ''' if filename[COMPRESSION[2]:] == COMPRESSION[1]: strippedfile = os.path.basename(filename[:COMPRESSION[2]]) else: strippedfile = os.path.basename(filename) compressedfile = strippedfile + COMPRESSION[1] if (os.access(strippedfile, os.F_OK) and not os.access(compressedfile, os.F_OK)): __logobj__.printlog('Compressing ' + strippedfile) cmdstr = '%s %s' % (COMPRESSION[0], strippedfile) os.system(cmdstr) On 2010/04/07 21:57 - davebyrne wrote : Actually, here is an slightly more simplified version: COMPRESSION = ('bzip2', '.bz2', -4) def compress_file(filename, filedate): ''' Needs Documentation ''' if filename[COMPRESSION[2]:] == COMPRESSION[1]: strippedfile = os.path.basename(filename[:COMPRESSION[2]]) else: strippedfile = os.path.basename(filename) > On 2010/04/08 15:03 - mailbot wrote : > thanks! I just fixed it. On 2010/04/08 12:50 - eanclin wrote : This occurs only on python2.4. ticket #19422: test/fulltest.sh can't find runtests.py ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.100 :state: validation pending Hello, the file test/fulltest.sh refers to a script called runtests.py $ grep 'runtests.py' test/fulltest.sh python$ver runtests.py python$ver -OO runtests.py but this is not distributed in the tarball: $ tar tf logilab-astng_0.19.3.orig.tar.gz | grep runtests.py $ without it, fulltest.sh (the right way to run tests, right?) can't be executed. In pylint I've seen this hunk: - python$ver runtests.py + python$ver `which pytest` probably it will fix this problem too. version 0.21.0 -------------- :expected date: n/a ticket #22100: fix infinite recursion with refactored astng ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: bug :load: 0.500 :state: open an infinite recursion on refactored astng occurs when pylint runs over refactored astng Comments :: On 2010/03/23 15:30 - eanclin wrote : This appears only when we run pylint from "logilab" or when astng is a symbolic link /home/user/astng -> ~/src/logilab/astng. What happens is: * some astng modules (like builder and patchcomptransformer) go two times into the manager._cache, one time as "", the other as "logilab.astng." . * the patchcomptransformer generates situation where a Class seems to be its own grandparent * but now the grandparent is the class with same name of the other "patchcomptransformer" module; hence we get a loop of length 4 and don't catch the grandpa situation which is usually catched in the *ancestors* method ticket #8796: support setuptools namespace packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 2.000 :state: open setuptoos introduce the notion of 'namespace' package allowing to have sub-parts of a same package splitted into several eggs (eg what's used to build proper eggs for logilab'subpackages...) this should be understood by pylint/astng? Comments :: On 2009/03/30 15:24 - anon wrote : The minimal sample below creates this output ("source lint_ns.sh"), note that the code itself works (prints the paste module's repr), but pylint can't see said module: pylint 0.18.0, astng 0.19.0, common 0.39.0 Python 2.5.2 (r252:60911, Nov 14 2008, 19:46:32) [GCC 4.3.2] ************* Module paste.lint_ns C: 1: Missing docstring E: 1: No name 'script' in module 'paste' F: 1: Unable to import 'paste.script' (No module named script) I could not reproduce the "TypeError: '_Yes' object is unindexable" I get with a more complex project, let's hope that disappears when all modules can be found. ==> lint_ns.sh <== # must be sourced! if test ! -d bin; then virtualenv2.5 --no-site-packages . . bin/activate PYTHONPATH=. bin/python ./setup.py develop -U fi bin/python -m paste.lint_ns bin/pylint --version bin/pylint -rn paste ==> setup.py <== from setuptools import setup setup( name = "lint_ns", version = "0.1", packages = ["paste.lint_ns"], namespace_packages = ["paste"], install_requires = [ "setuptools==0.6c9", "PasteScript>=1.6.2", "pylint==0.18.0", #"logilab.pylintinstaller==0.1.1", ], ) ==> paste/__init__.py <== """Namespace package.""" __import__('pkg_resources').declare_namespace(__name__) ==> paste/lint_ns/__init__.py <== from paste.script import templates if __name__ == "__main__": print repr(templates)
> On 2009/03/30 15:29 - sthenault wrote : > huum that's the one I was mainly interested in :(
> On 2010/01/06 11:46 - kevingill wrote : > I experienced this problem using the zope system. Zope uses large numbers or > namespace eggs. > > I work around it by modifying _module_file in modutils.py > > before the line : > > > while modpath: > > > insert: > > > try: > > _, mp_filename, mp_desc = find_module(os.sep.join(modpath), path) > > except ImportError: > > if checkeggs: > > return _search_zip(modpath, pic)[:2] > > raise > > mtype = mp_desc[2] > > return mtype, mp_filename > > > This returns the correct name for imports from namespace eggs. It may mess up > .zip eggs. It lowers the quality of the import error message.
ticket #8766: support for namedtuple ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 0.500 :state: open Maarteen in python-projects: on the following program pylint issues a false positive: .. sourcecode:: python from urlparse import urlparse print urlparse('http://www.logilab.org/project/pylint').path :: E1101: 2: Instance of 'ParseResult' has no 'path' member Here astng correctly infers that urlparse() returns a ParseResult instance, but doesn't know that ParseResult has a "path" member. This is the line in urlparse.py that defines ParseResult: .. sourcecode:: python class ParseResult(namedtuple('ParseResult', 'scheme netloc path params query fragment'), ResultMixin): The namedtuple() function is new in Python 2.6 and is documented here: http://docs.python.org/library/collections.html#collections.namedtuple The class using namedtuple() explicitly lists the members it acquires; it would be very useful if pylint would consider these members present. ticket #8774: iterator / generator / next method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 0.500 :state: open pylint does not seem to know that an iterator has a member called "next": .. sourcecode:: python def count(): n = 0 while True: yield n n += 1 i = count() print i.next() print i.next() print i.next() ticket #905: proper metaclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :type: enhancement :load: 1.000 :state: open Comments :: On 2008/01/14 14:40 - sthenault wrote : http://lists.logilab.org/pipermail/python-projects/2007-October/001325.html