# Buggy code
def __getitem__(self, key):
    row_loc, col_loc, ndim, self.row_scaler, self.col_scaler = _parse_tuple(key)
    if isinstance(row_loc, slice) and row_loc == slice(None):
        # If we're only slicing columns, handle the case with `__getitem__`
        if not isinstance(col_loc, slice):
            # Boolean indexers can just be sliced into the columns object and
            # then passed to `__getitem__`
            if is_boolean_array(col_loc):
                col_loc = self.df.columns[col_loc]
            return self.df.__getitem__(col_loc)
        else:
            result_slice = self.df.columns.slice_locs(col_loc.start, col_loc.stop)
            return self.df.iloc[:, slice(*result_slice)]

    row_lookup, col_lookup = self._compute_lookup(row_loc, col_loc)
    if any(i == -1 for i in row_lookup) or any(i == -1 for i in col_lookup):
        raise KeyError(
            "Passing list-likes to .loc or [] with any missing labels is no longer "
            "supported, see https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#deprecate-loc-reindex-listlike"
        )
    result = super(_LocIndexer, self).__getitem__(row_lookup, col_lookup, ndim)
    if isinstance(result, Series):
        result._parent = self.df
        result._parent_axis = 0
    # Pandas drops the levels that are in the `loc`, so we have to as well.
    if hasattr(result, "index") and isinstance(result.index, pandas.MultiIndex):
        if (
            isinstance(result, Series)
            and not isinstance(col_loc, slice)
            and all(col_loc[i] in result.index.levels[i] for i in range(len(col_loc)))
        ):
            result.index = result.index.droplevel(list(range(len(col_loc))))
        elif all(row_loc[i] in result.index.levels[i] for i in range(len(row_loc))):
            result.index = result.index.droplevel(list(range(len(row_loc))))
    if (
        hasattr(result, "columns")
        and not isinstance(col_loc, slice)
        and isinstance(result.columns, pandas.MultiIndex)
        and all(col_loc[i] in result.columns.levels[i] for i in range(len(col_loc)))
    ):
        result.columns = result.columns.droplevel(list(range(len(col_loc))))
    return result


# Traceback (TypeError)
Python 3.8.3 (default, Jun  9 2020, 17:49:41)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
import modin.pandas as pandas
foo = pandas.DataFrame({"col": [1,2,3,4]})
UserWarning: Distributing <class 'dict'> object. This may take some time.
foo
col
0    1
1    2
2    3
3    4
foo.loc[lambda val: val.col%2==0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/root/.cache/pypoetry/virtualenvs/onepassword-etl-NcjVOHQt-py3.8/src/modin/modin/pandas/indexing.py", line 252, in __getitem__
row_lookup, col_lookup = self._compute_lookup(row_loc, col_loc)
File "/root/.cache/pypoetry/virtualenvs/onepassword-etl-NcjVOHQt-py3.8/src/modin/modin/pandas/indexing.py", line 345, in _compute_lookup
row_lookup = self.qc.index.get_indexer_for(row_loc)
File "/root/.cache/pypoetry/virtualenvs/onepassword-etl-NcjVOHQt-py3.8/lib/python3.8/site-packages/pandas/core/indexes/base.py", line 4502, in get_indexer_for
return self.get_indexer(target, **kwargs)
File "/root/.cache/pypoetry/virtualenvs/onepassword-etl-NcjVOHQt-py3.8/lib/python3.8/site-packages/pandas/core/indexes/range.py", line 358, in get_indexer
return super().get_indexer(
File "/root/.cache/pypoetry/virtualenvs/onepassword-etl-NcjVOHQt-py3.8/lib/python3.8/site-packages/pandas/core/indexes/base.py", line 2709, in get_indexer
target = ensure_index(target)
File "/root/.cache/pypoetry/virtualenvs/onepassword-etl-NcjVOHQt-py3.8/lib/python3.8/site-packages/pandas/core/indexes/base.py", line 5358, in ensure_index
return Index(index_like)
File "/root/.cache/pypoetry/virtualenvs/onepassword-etl-NcjVOHQt-py3.8/lib/python3.8/site-packages/pandas/core/indexes/base.py", line 438, in __new__
subarr = com.asarray_tuplesafe(data, dtype=object)
File "/root/.cache/pypoetry/virtualenvs/onepassword-etl-NcjVOHQt-py3.8/lib/python3.8/site-packages/pandas/core/common.py", line 222, in asarray_tuplesafe
values = list(values)
TypeError: 'function' object is not iterable


# Fixed code
def __getitem__(self, key):
    if callable(key):
        return self.__getitem__(key(self.df))
    row_loc, col_loc, ndim, self.row_scaler, self.col_scaler = _parse_tuple(key)
    if isinstance(row_loc, slice) and row_loc == slice(None):
        # If we're only slicing columns, handle the case with `__getitem__`
        if not isinstance(col_loc, slice):
            # Boolean indexers can just be sliced into the columns object and
            # then passed to `__getitem__`
            if is_boolean_array(col_loc):
                col_loc = self.df.columns[col_loc]
            return self.df.__getitem__(col_loc)
        else:
            result_slice = self.df.columns.slice_locs(col_loc.start, col_loc.stop)
            return self.df.iloc[:, slice(*result_slice)]

    row_lookup, col_lookup = self._compute_lookup(row_loc, col_loc)
    if any(i == -1 for i in row_lookup) or any(i == -1 for i in col_lookup):
        raise KeyError(
            "Passing list-likes to .loc or [] with any missing labels is no longer "
            "supported, see https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#deprecate-loc-reindex-listlike"
        )
    result = super(_LocIndexer, self).__getitem__(row_lookup, col_lookup, ndim)
    if isinstance(result, Series):
        result._parent = self.df
        result._parent_axis = 0
    # Pandas drops the levels that are in the `loc`, so we have to as well.
    if hasattr(result, "index") and isinstance(result.index, pandas.MultiIndex):
        if (
            isinstance(result, Series)
            and not isinstance(col_loc, slice)
            and all(col_loc[i] in result.index.levels[i] for i in range(len(col_loc)))
        ):
            result.index = result.index.droplevel(list(range(len(col_loc))))
        elif all(row_loc[i] in result.index.levels[i] for i in range(len(row_loc))):
            result.index = result.index.droplevel(list(range(len(row_loc))))
    if (
        hasattr(result, "columns")
        and not isinstance(col_loc, slice)
        and isinstance(result.columns, pandas.MultiIndex)
        and all(col_loc[i] in result.columns.levels[i] for i in range(len(col_loc)))
    ):
        result.columns = result.columns.droplevel(list(range(len(col_loc))))
    return result