Repository: ibis-project/ibis

Issue:
docs: printing a memtable with a map freezes in interactive mode, document allowed input
### What happened?

```
import ibis
ibis.options.interactive = True
t = ibis.memtable({"a": [ibis.map({"a": 1, "b": 2})]})
t
```

Freezes up my Python process and doesn't print anything.

### What version of ibis are you using?

On current master branch.

### What backend(s) are you using, if any?

the default one, so DuckDB?

### Relevant log output

_No response_

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct


Discussion:
Can you try without the `ibis.map`?

memtable should only be constructed with non-ibis contents: a pandas DataFrame, a pyarrow Table, a list of dicts of non-ibis python objects etc.
It appears to work without the `ibis.map` wrapper:

```
In [1]: import ibis

In [2]: ibis.options.interactive = True

In [3]: t = ibis.memtable({"a": [{"a": 1, "b": 2}]})

In [4]: t
Out[4]:
┏━━━━━━━━━━━━━━━━━━━━━━┓
┃ a                    ┃
┡━━━━━━━━━━━━━━━━━━━━━━┩
│ map<string, int8>    │
├──────────────────────┤
│ {'a': 1, 'b': 2}     │
└──────────────────────┘
```
I'm not sure how aggressive we want to be about this. Recursively scanning every element of every column might be prohibitively expensive, but maybe there's a less costly approach?
It does work without the `ibis.map` wrapper if there is only one valid element. With more than one I get:

```python
>>> t = ibis.memtable({"a": [{"a": 1, "b": 2}, {"a": 2}, None]})
>>> t
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/willjones/Documents/ibis/ibis/expr/types/core.py", line 56, in __repr__
    simple_console.print(self)
  File "/Users/willjones/mambaforge/envs/ibis-dev/lib/python3.10/site-packages/rich/console.py", line 1698, in print
    extend(render(renderable, render_options))
  File "/Users/willjones/mambaforge/envs/ibis-dev/lib/python3.10/site-packages/rich/console.py", line 1310, in render
    render_iterable = renderable.__rich_console__(self, _options)  # type: ignore[union-attr]
  File "/Users/willjones/Documents/ibis/ibis/expr/types/relations.py", line 266, in __rich_console__
    table = to_rich_table(self, width)
  File "/Users/willjones/Documents/ibis/ibis/expr/types/pretty.py", line 229, in to_rich_table
    result = table.limit(nrows + 1).execute()
  File "/Users/willjones/Documents/ibis/ibis/expr/types/core.py", line 303, in execute
    return self._find_backend(use_default=True).execute(
  File "/Users/willjones/Documents/ibis/ibis/backends/base/sql/__init__.py", line 254, in execute
    result = self.fetch_from_cursor(cursor, schema)
  File "/Users/willjones/Documents/ibis/ibis/backends/duckdb/__init__.py", line 690, in fetch_from_cursor
    return schema.apply_to(df)
  File "/Users/willjones/Documents/ibis/ibis/expr/schema.py", line 267, in apply_to
    new_col = convert(col_dtype, dtype, col)
  File "/Users/willjones/mambaforge/envs/ibis-dev/lib/python3.10/site-packages/multipledispatch/dispatcher.py", line 278, in __call__
    return func(*args, **kwargs)
  File "/Users/willjones/Documents/ibis/ibis/backends/pandas/client.py", line 202, in convert_struct_to_dict
    return column.map(convert_element)
  File "/Users/willjones/mambaforge/envs/ibis-dev/lib/python3.10/site-packages/pandas/core/series.py", line 4539, in map
    new_values = self._map_values(arg, na_action=na_action)
  File "/Users/willjones/mambaforge/envs/ibis-dev/lib/python3.10/site-packages/pandas/core/base.py", line 890, in _map_values
    new_values = map_f(values, mapper)
  File "pandas/_libs/lib.pyx", line 2924, in pandas._libs.lib.map_infer
  File "/Users/willjones/Documents/ibis/ibis/backends/pandas/client.py", line 198, in convert_element
    if values is None or isinstance(values, dict) or pd.isna(values):
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
```
I think this is probably something we can address in docs, but not programmatically. We don't really have a ton of control over what people **try** to put into `ibis.memtable` nor can we guard against all of the weird behavior that may result.
/take

Resolving patch:
diff --git a/ibis/expr/api.py b/ibis/expr/api.py
--- a/ibis/expr/api.py
+++ b/ibis/expr/api.py
@@ -319,8 +319,13 @@ def memtable(
     data
         Any data accepted by the `pandas.DataFrame` constructor or a `pyarrow.Table`.
 
+        Examples of acceptable objects are a `pandas.DataFrame`, a `pyarrow.Table`,
+        a list of dicts of non-ibis Python objects, etc.
+        `ibis` objects, like `MapValue`, will result in an error.
+
         Do not depend on the underlying storage type (e.g., pyarrow.Table), it's subject
         to change across non-major releases.
+
     columns
         Optional [`Iterable`][typing.Iterable] of [`str`][str] column names.
     schema


Test patch: