Search code examples
pythonsqlalchemypep8

Expressing IS NOT NULL without causing a PEP8 error


At a certain point in my project, I need to query a SQLAlchemy object for columns that are NOT NULL. In my code, I do:

session.query(MyModel).filter(MyModel.my_column != None).all()

...and it works great. Problem is, whenever I run pep8 or one of the other linters on the file, it raises an error E711: Comparison to None should be if cond is not None:. I agree with the spirit of this guideline, and as such I don't want to silence the warning just because of one little line.

Is there another way to write this? Preferably one where we don't have to dig into the func module?


Solution

  • PEP8 isn't meant to be followed to the letter.

    You're recommended to use is None instead of == None because is cannot be overloaded (unlike ==):

    >>> class Bad(object):
    ...     def __eq__(self, other):
    ...         return True
    ...
    >>> instance = Bad()
    >>> instance == None
    True
    >>> instance is None
    False
    

    In your case you want to use the overloaded == operator, so the warning is incorrect.

    There are three ways of making the warning go away:

    1. You can disable that particular warning for that single line:

      • For Flake8/PyFlakes:

        session.query(MyModel).filter(MyModel.my_column != None).all()  # noqa: E711
        
      • For Pylint:

        session.query(MyModel).filter(MyModel.my_column != None).all()  # pylint: disable=singleton-comparison
        
    2. You can avoid using the equality operator by directly calling the class's __eq__ (for ==) and __ne__ (for !=) methods:

      session.query(MyModel).filter(MyModel.my_column.__ne__(None)).all()
      
    3. You can use .is_ and .isnot:

      session.query(MyModel).filter(MyModel.my_column.isnot(None)).all()
      

      Note that .is_ and .isnot are not the same as == and !=. MyModel.my_column != x can mean both IS NOT NULL and != x depending on the value of x and your database, so solutions 1 and 2 are probably better unless you really don't like using __-methods and know the type of the right-hand-side of your expression.