Repository: Textualize/rich

Issue:
[BUG] Double rendering of notebook output with `rich>=12.6.0`
- [x] I've checked [docs](https://rich.readthedocs.io/en/latest/introduction.html) and [closed issues](https://github.com/Textualize/rich/issues?q=is%3Aissue+is%3Aclosed) for possible solutions.
- [x] I can't find my issue in the [FAQ](https://github.com/Textualize/rich/blob/master/FAQ.md).

**Describe the bug**
It appears the double rendering issue referenced in #1737 has returned starting in version 12.6.0.

With a poetry environment given by:

```toml
[tool.poetry]
name = "rich-bug-repro"
version = "0.0.1"
description = "..."
authors = ["John Doe"]

[tool.poetry.dependencies]
python = "^3.9"
jupyter = "^1.0.0"
rich = {version = "x.x.x", extras=["jupyter"]}  # fill out with desired version
```

a simple reproducing example is (from a jupyter notebook)

```python
from rich.progress import track
import time

for i in track(range(100)):
    time.sleep(0.01)
```

when `version` is set to any of `12.6.0,13.0.0,13.0.1` in the `pyproject.toml` above, the output of this example looks like

![image](https://user-images.githubusercontent.com/14932242/211386667-5eec044c-778a-4c1e-87d0-156fab83e7cb.png)

When using `<12.6.0`, you get the expected
![image](https://user-images.githubusercontent.com/14932242/211387105-cf666de3-716c-4040-8d2a-2faf1de70a65.png)

Note that this is strictly a jupyter problem: for any of these versions, running e.g.
```console
python -c 'from rich.progress import track;import time;[time.sleep(0.01) for _ in track(range(100))]'
```
results in just a single progress bar being printed, as expected.

**Platform**
<details>
<summary>Click to expand</summary>

What platform (Win/Linux/Mac) are you running on? What terminal software are you using?
Linux, both natively and in WSL2 on Windows.

I may ask you to copy and paste the output of the following commands. It may save some time if you do it now.

If you're using Rich in a terminal:

```
python -m rich.diagnose
pip freeze | grep rich
```

If you're using Rich in a Jupyter Notebook, run the following snippet in a cell
and paste the output in your bug report.

```python
from rich.diagnose import report
report()
```
```console
╭────────────────────── <class 'rich.console.Console'> ──────────────────────╮
│ A high level console interface.                                            │
│                                                                            │
│ ╭────────────────────────────────────────────────────────────────────────╮ │
│ │ <console width=115 ColorSystem.TRUECOLOR>                              │ │
│ ╰────────────────────────────────────────────────────────────────────────╯ │
│                                                                            │
│     color_system = 'truecolor'                                             │
│         encoding = 'utf-8'                                                 │
│             file = <ipykernel.iostream.OutStream object at 0x7f3f783203d0> │
│           height = 100                                                     │
│    is_alt_screen = False                                                   │
│ is_dumb_terminal = False                                                   │
│   is_interactive = True                                                    │
│       is_jupyter = True                                                    │
│      is_terminal = True                                                    │
│   legacy_windows = False                                                   │
│         no_color = False                                                   │
│          options = ConsoleOptions(                                         │
│                        size=ConsoleDimensions(width=115, height=100),      │
│                        legacy_windows=False,                               │
│                        min_width=1,                                        │
│                        max_width=115,                                      │
│                        is_terminal=True,                                   │
│                        encoding='utf-8',                                   │
│                        max_height=100,                                     │
│                        justify=None,                                       │
│                        overflow=None,                                      │
│                        no_wrap=False,                                      │
│                        highlight=None,                                     │
│                        markup=None,                                        │
│                        height=None                                         │
│                    )                                                       │
│            quiet = False                                                   │
│           record = False                                                   │
│         safe_box = True                                                    │
│             size = ConsoleDimensions(width=115, height=100)                │
│        soft_wrap = False                                                   │
│           stderr = False                                                   │
│            style = None                                                    │
│         tab_size = 8                                                       │
│            width = 115                                                     │
╰────────────────────────────────────────────────────────────────────────────╯
╭─── <class 'rich._windows.WindowsConsoleFeatures'> ────╮
│ Windows features available.                           │
│                                                       │
│ ╭───────────────────────────────────────────────────╮ │
│ │ WindowsConsoleFeatures(vt=False, truecolor=False) │ │
│ ╰───────────────────────────────────────────────────╯ │
│                                                       │
│ truecolor = False                                     │
│        vt = False                                     │
╰───────────────────────────────────────────────────────╯
╭────── Environment Variables ───────╮
│ {                                  │
│     'TERM': 'xterm-color',         │
│     'COLORTERM': None,             │
│     'CLICOLOR': '1',               │
│     'NO_COLOR': None,              │
│     'TERM_PROGRAM': None,          │
│     'COLUMNS': None,               │
│     'LINES': None,                 │
│     'JUPYTER_COLUMNS': None,       │
│     'JUPYTER_LINES': None,         │
│     'JPY_PARENT_PID': '2054',      │
│     'VSCODE_VERBOSE_LOGGING': None │
│ }                                  │
╰────────────────────────────────────╯
platform="Linux"
```
</details>



Discussion:
What software are you using to run the Notebook? Jupyter notebook, Jupyter lab, VSCode ? 
I had the same problem, was using Jupyter lab.
Ok, just checked again, and the problem exists with both jupyter-lab and notebook. Don't use VSCode, so don't know about that. In my case, both running on Linux, in a (newly created) conda-environment, if that makes any difference.

Resolving patch:
diff --git a/rich/console.py b/rich/console.py
--- a/rich/console.py
+++ b/rich/console.py
@@ -711,11 +711,6 @@ def __init__(
         self._force_terminal = None
         if force_terminal is not None:
             self._force_terminal = force_terminal
-        else:
-            # If FORCE_COLOR env var has any value at all, we force terminal.
-            force_color = self._environ.get("FORCE_COLOR")
-            if force_color is not None:
-                self._force_terminal = True
 
         self._file = file
         self.quiet = quiet
@@ -949,6 +944,15 @@ def is_terminal(self) -> bool:
             # Return False for Idle which claims to be a tty but can't handle ansi codes
             return False
 
+        if self.is_jupyter:
+            # return False for Jupyter, which may have FORCE_COLOR set
+            return False
+
+        # If FORCE_COLOR env var has any value at all, we assume a terminal.
+        force_color = self._environ.get("FORCE_COLOR")
+        if force_color is not None:
+            self._force_terminal = True
+
         isatty: Optional[Callable[[], bool]] = getattr(self.file, "isatty", None)
         try:
             return False if isatty is None else isatty()


Test patch:
diff --git a/tests/test_console.py b/tests/test_console.py
--- a/tests/test_console.py
+++ b/tests/test_console.py
@@ -971,3 +971,11 @@ def test_force_color(env_value):
     # means is_terminal returns True.
     console = Console(file=io.StringIO(), _environ={"FORCE_COLOR": env_value})
     assert console.is_terminal
+
+
+def test_force_color_jupyter():
+    # FORCE_COLOR above doesn't happen in a Jupyter kernel
+    console = Console(
+        file=io.StringIO(), _environ={"FORCE_COLOR": "1"}, force_jupyter=True
+    )
+    assert not console.is_terminal