Skip to content

Using AND (&) with a predicate that returns None incorrectly returns True #165

@sjdemartini

Description

@sjdemartini

When using & to combine predicates, if one of the predicates returns None (a falsey value), the overall predicate will mistakenly/confusingly return True. This is not consistent with running the predicate by itself or ORed with other predicates.

This behavior can be demonstrated with the following test added to test_predicates.py—the final assertion fails:

    def test_returns_none(self):
        @predicate
        def returns_none(arg1, arg2):
            return None

        # Just the predicate (works)
        assert not returns_none(2, 3)

        # OR the predicate with itself (works)
        p_OR = returns_none | returns_none
        assert not p_OR()

        # AND the predicate with a truthy-predicate (FAILS)
        p_AND = always_true & returns_none
        assert not p_AND()

I noticed this in production in my app, where my logic in one predicate was doing return obj and obj.boolean_field, expecting that if obj were None, it'd still be treated as False in all contexts. It took me a while to figure out what was going on. I didn't feel sure about where/how to fix this in django-rules, but hope the above example will help to resolve quickly if possible. Thanks in advance (and thanks for building this great library)!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions