Repository: streamlit/streamlit

Issue:
Calling repr on current thread leads to RecursionError
### Summary

Calling str or repr on current thread leads to `RecursionError: maximum recursion depth exceeded while getting the repr of an object`

### Steps to reproduce

Code snippet:

```
import streamlit as st
import threading

thread = threading.current_thread()
st.info('Weird case %s' % thread)
```

Steps to reproduce the bug:

1. Save above code as app.py
2. Run `streamlit run app.py`


**Expected behavior:**

The current thread details should be shown.
```
$ python -c "import threading; thread = threading.current_thread(); print('%s' % thread)"
<_MainThread(MainThread, started 140179378095936)>
```

**Actual behavior:**

We get a RecursionError:
```
$ streamlit run app.py

  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://<ipv4>:8501

2021-12-14 13:25:08.486 Traceback (most recent call last):
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/script_runner.py", line 354, in _run_script
    exec(code, module.__dict__)
  File "/u/foo/st_reproducer/app.py", line 5, in <module>
    st.info('Weird case %s' % thread)
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/report_thread.py", line 209, in __repr__
    return util.repr_(self)
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in repr_
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in <listcomp>
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/script_runner.py", line 137, in __repr__
    return util.repr_(self)
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in repr_
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in <listcomp>
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/report_thread.py", line 209, in __repr__
    return util.repr_(self)
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in repr_
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in <listcomp>
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/script_runner.py", line 137, in __repr__
    return util.repr_(self)
  ...
  ...
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in repr_
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in <listcomp>
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/report.py", line 99, in __repr__
    return util.repr_(self)
  File "/usr/local/python/python-3.9/latest/lib64/python3.9/site-packages/streamlit/util.py", line 106, in repr_
    args = ", ".join([f"{k}={repr(v)}" for (k, v) in cls.__dict__.items()])
RecursionError: maximum recursion depth exceeded while calling a Python object

```

### Is this a regression?
I do not think so. Able to reproduce this with at least one Streamlit version<1.1.0 as well as under Python 3.7.

### Debug info

- Streamlit version: 1.1.0
- Python version: 3.9.7
- Installed using pip
- OS version: Red Hat Enterprise Linux Server release 7.9 (Maipo)
- Browser version: Chrome 96.0

### Additional information

This is preventing us from using packages which internally calls repr(thread), so any workaround suggestion would also be good to know until there is a fix.


Discussion:

Resolving patch:
diff --git a/lib/streamlit/report_thread.py b/lib/streamlit/report_thread.py
--- a/lib/streamlit/report_thread.py
+++ b/lib/streamlit/report_thread.py
@@ -205,9 +205,6 @@ def __init__(
             uploaded_file_mgr=uploaded_file_mgr,
         )
 
-    def __repr__(self) -> str:
-        return util.repr_(self)
-
 
 def add_report_ctx(
     thread: Optional[threading.Thread] = None, ctx: Optional[ReportContext] = None


Test patch:
diff --git a/lib/tests/streamlit/repr_test.py b/lib/tests/streamlit/repr_test.py
--- a/lib/tests/streamlit/repr_test.py
+++ b/lib/tests/streamlit/repr_test.py
@@ -22,3 +22,11 @@ def __repr__(self):
     foo = Foo()
     foo.bar = "bar"
     assert repr(foo) == "Foo(bar='bar')"
+
+
+def test_repr_thread_class():
+    import threading
+
+    thread = threading.current_thread()
+    # This should return a non empty string and not raise an exception.
+    assert str(thread) is not None