    def from_kwargs(self, **kwargs):
        """Parse query from Pythonic keyword arguments

        Examples
        --------
        >>> from rocketry.pybox.query import parser
        >>> qry = parser.from_kwargs(
        ...     mydate=('2021-07-01', '2021-07-15'),
        ...     mykey='this'
        ... )
        >>> str(qry)
        "((<mydate> >= '2021-07-01') & (<mydate> <= '2021-07-15') & (<mykey> == 'this'))"
        """
        statement = None

        for key, val in kwargs.items():
            if isinstance(val, tuple):
                # A range
                min_, max_ = val
                if min_ is not None and max_ is not None:
                    substatement = GreaterEqual(Key(key), min_) & LessEqual(Key(key), max_)
                elif min_ is not None:
                    substatement = GreaterEqual(Key(key), min_)
                elif max_ is not None:
                    substatement = LessEqual(Key(key), max_)
                else:
                    continue
            elif isinstance(val, list):
                substatement = Any(*(Key(key) == subval for subval in val))
            else:
                substatement = Equal(Key(key), val)

            if statement is None:
                statement = substatement
            else:
                statement &= substatement

        if statement is None:
            return true
        return statement
Parse query from Pythonic keyword arguments

Examples
--------
>>> from rocketry.pybox.query import parser
>>> qry = parser.from_kwargs(
...     mydate=('2021-07-01', '2021-07-15'),
...     mykey='this'
... )
>>> str(qry)
"((<mydate> >= '2021-07-01') & (<mydate> <= '2021-07-15') & (<mykey> == 'this'))"
rocketry/pybox/query/parse.py