Repository: magmax/python-inquirer

Issue:
Tuples as list choices can't be hashed when containing a dict
In 3.2.1, the following worked:
```
>>> import inquirer
>>> test = [('aa', {'a': 1}), ('bb', {'b':2})]
>>> inquirer.list_input('Which?', carousel=True, choices=test)
[?] Which?: bb
   aa
 > bb

{'b': 2}
```

Whereas in 3.2.2 (and 3.2.3) this doesn't:

```
>>> import inquirer
>>> test = [('aa', {'a': 1}), ('bb', {'b':2})]
>>> inquirer.list_input('Which?', carousel=True, choices=test)
[?] Which?:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "App/.venv/lib/python3.11/site-packages/inquirer/shortcuts.py", line 32, in list_input
    return render.render(question)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "App/.venv/lib/python3.11/site-packages/inquirer/render/console/__init__.py", line 38, in render
    return self._event_loop(render)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "App/.venv/lib/python3.11/site-packages/inquirer/render/console/__init__.py", line 49, in _event_loop
    self._print_hint(render)
  File "App/.venv/lib/python3.11/site-packages/inquirer/render/console/__init__.py", line 96, in _print_hint
    hint = render.get_hint()
           ^^^^^^^^^^^^^^^^^
  File "App/.venv/lib/python3.11/site-packages/inquirer/render/console/_list.py", line 23, in get_hint
    hint = self.question.hints[choice]
           ~~~~~~~~~~~~~~~~~~~^^^^^^^^
  File "App/.venv/lib/python3.11/site-packages/inquirer/questions.py", line 37, in __hash__
    return hash(self.tuple)
           ^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'dict'
```

The reason is that [`TaggedValue`'s `hash`](https://github.com/magmax/python-inquirer/blob/a4a6615981a1716a9c11e4f775794c4712d46bf5/src/inquirer/questions.py#L37) function tries to hash whole tuple passed. Would it be enough to hash just the string representation (i.e. `hash(self.tag)`), instead of the whole tuple? I'd say the list of choices should provide unique string descriptions for every item (although it might technically not be necessary when passing `hints=` as well?)

Comments:

Patch:
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 2ea1b1f..be3d7aa 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,3 +1,3 @@
-furo==2023.9.10
+furo==2024.1.29
 sphinx==7.2.5
 myst_parser==2.0.0
diff --git a/src/inquirer/questions.py b/src/inquirer/questions.py
index 741d778..e1fb427 100644
--- a/src/inquirer/questions.py
+++ b/src/inquirer/questions.py
@@ -60,7 +60,7 @@ class Question:
         self._validate = validate
         self.answers = {}
         self.show_default = show_default
-        self.hints = hints or {}
+        self.hints = hints
         self._other = other
 
         if self._other:
diff --git a/src/inquirer/render/console/__init__.py b/src/inquirer/render/console/__init__.py
index 7e0d84d..70ed668 100644
--- a/src/inquirer/render/console/__init__.py
+++ b/src/inquirer/render/console/__init__.py
@@ -93,7 +93,9 @@ class ConsoleRender:
 
     def _print_hint(self, render):
         msg_template = "{t.move_up}{t.clear_eol}{color}{msg}"
-        hint = render.get_hint()
+        hint = ""
+        if render.question.hints is not None:
+            hint = render.get_hint()
         color = self._theme.Question.mark_color
         if hint:
             self.print_str(


Test patch:
diff --git a/tests/integration/console_render/test_list.py b/tests/integration/console_render/test_list.py
index c4b2e74..7cd3dea 100644
--- a/tests/integration/console_render/test_list.py
+++ b/tests/integration/console_render/test_list.py
@@ -165,3 +165,19 @@ class ListRenderTest(unittest.TestCase, helper.BaseTestCase):
         sut.render(question)
 
         self.assertInStdout("Bar")
+
+    def test_taggedValue_with_dict(self):
+        stdin = helper.event_factory(key.DOWN, key.ENTER)
+        message = "Foo message"
+        variable = "Bar variable"
+        choices = [
+            ("aa", {"a": 1}),
+            ("bb", {"b": 2}),
+        ]
+
+        question = questions.List(variable, message, choices=choices)
+
+        sut = ConsoleRender(event_generator=stdin)
+        sut.render(question)
+
+        self.assertInStdout("bb")