views:

3189

answers:

7

I would very much like to integrate pylint into the build process for my python projects, but I have run into one show-stopper: One of the error types that I find extremely useful--:E1101: *%s %r has no %r member*--constantly reports errors when using common django fields, for example:

E1101:125:get_user_tags: Class 'Tag' has no 'objects' member

which is caused by this code:

def get_user_tags(username):
   """
   Gets all the tags that username has used.

   Returns a query set.
   """
   return Tag.objects.filter(  ## This line triggers the error.
       tagownership__users__username__exact=username).distinct()

# Here is the Tag class, models.Model is provided by Django:
class Tag(models.Model):
   """
   Model for user-defined strings that help categorize Events on
   on a per-user basis.
   """
   name = models.CharField(max_length=500, null=False, unique=True)

   def __unicode__(self):
       return self.name

How can I tune Pylint to properly take fields such as objects into account? (I've also looked into the Django source, and I have been unable to find the implementation of objects, so I suspect it is not "just" a class field. On the other hand, I'm fairly new to python, so I may very well have overlooked something.)

Edit: The only way I've found to tell pylint to not warn about these warnings is by blocking all errors of the type (E1101) which is not an acceptable solution, since that is (in my opinion) an extremely useful error. If there is another way, without augmenting the pylint source, please point me to specifics :)

See here for a summary of the problems I've had with pychecker and pyflakes -- they've proven to be far to unstable for general use. (In pychecker's case, the crashes originated in the pychecker code -- not source it was loading/invoking.)

+7  A: 

Because of how pylint works (it examines the source itself, without letting Python actually execute it) it's very hard for pylint to figure out how metaclasses and complex baseclasses actually affect a class and its instances. The 'pychecker' tool is a bit better in this regard, because it does actually let Python execute the code; it imports the modules and examines the resulting objects. However, that approach has other problems, because it does actually let Python execute the code :-)

You could extend pylint to teach it about the magic Django uses, or to make it understand metaclasses or complex baseclasses better, or to just ignore such cases after detecting one or more features it doesn't quite understand. I don't think it would be particularly easy. You can also just tell pylint to not warn about these things, through special comments in the source, command-line options or a .pylintrc file.

Thomas Wouters
+4  A: 

Try running pylint with

pylint --ignored-classes=Tags

If that works, add all the other Django classes - possibly using a script, in say, python :P

The documentation for --ignore-classes is:

--ignored-classes=<members names>
List of classes names for which member attributes should not be checked (useful for classes with attributes dynamicaly set). [current: %default]

I should add this is not a particular elegant solution in my view, but it should work.

freespace
It only works if I never make any errors in those classes ;). I want to avoid ignoring code if at all possible -- I think it is a very bad idea to have different parts of the codebase analyzed an different degrees of scrutiny. I will forget which is which, and make false assumptions when debugging
rcreswick
+6  A: 

I resigned from using pylint/pychecker in favor of using pyflakes with Django code - it just tries to import module and reports any problem it finds, like unused imports or uninitialized local names.

zgoda
interesting -- I'll give pyflakes another look.
rcreswick
PyChecker catches much less than pylint. http://www.doughellmann.com/articles/CompletelyDifferent-2008-03-linters/index.html
Justin Lilly
+7  A: 

This is not a solution, but you can add objects = models.Manager() to your Django models without changing any behavior.

I myself only use pyflakes, primarily due to some dumb defaults in pylint and laziness on my part (not wanting to look up how to change the defaults).

AdamKG
Ah... thanks for the tip. I may try just adding that to Model.models in the local copy of the django source, and see if that does it.
rcreswick
I think this a great solution because it doesn't compromise on warnings.
Tom Leys
+2  A: 

So far I have found no real solution to that but work around:

  • In our company we require a pylint score > 8. This allows coding practices pylint doesn't understand while ensuring that the code isn't too "unusual". So far we havn't seen any instance where E1101 kept us from reaching a score of 8 or higher.
  • Our 'make check' targets filter out "for has no 'objects' member" messages to remove most of the distraction caused by pylint not understanding Django.
mdorseif
+16  A: 

I use the following: pylint --generated-members=objects

Any more? This did the trick for the objects warnig.
Yorgos Pagles
+5  A: 

django-lint is a nice tool which wraps pylint with django specific settings : http://chris-lamb.co.uk/projects/django-lint/

gurney alex
I like the idea of a Django-specific pylint, but it seems a big buggy last time I tried it.
Wernight
Also it's not available via PyPI and the website doesn't seem to give enough info like: What's the current version?
Wernight