subject
[Python-projects] Check imported modules attributes
date
Hello,2005/06/20 13:40
I just downloaded PyLint this morning, and tried it on my code.
This tool is really impressive... Nice job!
My first impression is that I have a lot of work to get a note that is not
negative...
Then, I tried to make it detect some errors in my code,
and I was surprised that PyLint doesn't detect simple (IMO)
errors like
import sys
sys.this_is_an_error
So I hacked a bit, and came with an additional test, that checks
attribute access: for each GetAttr node, if the left-hand side
is a module, the right-hand name must belong to the module.
Here are my mods to the checkers package:
(BTW, PyLint's code is very clear, and easy to modify. Bravo again!)
[in pylint/checkers/variable.py, at the end of the MSGS dict:]
'E0623': ('Unresolved name %r in module %r',
'Used when a name cannot be found in a module.'),
[in pylint/checkers/variable.py, class VariablesChecker:]
def leave_getattr(self, node):
"""check modules attribute accesses"""
# This function is a "leave_" because when parsing 'a.b.c'
# we want to check the innermost expression first.
module_names = []
expr = node.expr
# In the case of "package.module.name", retrieve the base package
while isinstance(expr, astng.Getattr):
module_names.insert(0, expr.attrname)
expr = expr.expr
if not isinstance(expr, astng.Name):
# Base expression is not a Name, don't check
return
module_names.insert(0, expr.name)
module = node
for name in module_names:
try:
module = module.resolve(name)
except astng.ResolveError:
# This error is either a unknown variable,
# or a missing module attribute. Both cases
# are already reported.
return
if not isinstance(module, astng.Module):
# Not a module, don't check
return
# locate the attribute inside the module
try:
module.resolve(node.attrname)
except astng.ResolveError:
module_name = '.'.join(module_names)
self.add_message('E0623', args=(node.attrname, module_name),
node=node)
OK, this is straightforward and almost works.
The difficult part is that the tests relies on the imported modules
to be parsed correctly. When using my new test on PyLint's code itself,
I saw it report errors on missing "sys.stdout" and "re.finditer"...
The first one was easy to find: when building the astng from a living
module,
functions, classes, and descriptors are taken, but not "regular" variables.
Here is a quick hack:
[in logilab/common/astng/builder.py, at the end of object_build:]
else:
# All other objects: just give a name
from compiler.ast import EmptyNode
data = EmptyNode() # XXX is it the right node?
data.name = name
# Keeping a reference to any object may have unexpected
results...
# data.value = member
node.add_local_node(data)
For "re.finditer", I don't have any solution yet. The function is defined
like this:
[in sre.py:]
if sys.hexversion >= 0x02020000:
def finditer(pattern, string):
...
An idea would be to import the module instead of trying to parse it.
I know this was removed some releases ago, but I suggest that at least
standard library modules could be "really" imported.
Well, sorry for this long post.
But I think that this kind of checks would avoid a lot of errors, specially
when imported modules are to change...
Thanks again for this tool,
--
Amaury Forgeot d'Arc
Ubix Development
www.ubitrade.com
_______________________________________________
Python-Projects mailing list
Python-Projects@lists.logilab.org
http://lists.logilab.org/mailman/listinfo/python-projects
