This removes empty elements so we don't have to go into an if/else chain here, especially when adding more predicates in the future. Same thing with the following line:

    predicate_product = filter(None, list(itertools.product(*product_input)))

because:

    >>> list(itertools.product())
    [()]