From 6f59517852a96dc7c57c03c432d35115787afb13 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 6 Feb 2026 15:36:26 +0100 Subject: [PATCH 01/10] update docs for typer-slim --- README.md | 18 ++---------------- docs/features.md | 9 +-------- docs/index.md | 18 ++---------------- docs/tutorial/package.md | 6 ------ docs/tutorial/typer-command.md | 10 ++-------- 5 files changed, 7 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 5a1d648270..bc206cc8ab 100644 --- a/README.md +++ b/README.md @@ -367,23 +367,9 @@ By default it also comes with extra standard dependencies: ### `typer-slim` -If you don't want the extra standard optional dependencies, install `typer-slim` instead. +There used to be a slimmedd-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command. -When you install with: - -```bash -pip install typer -``` - -...it includes the same code and dependencies as: - -```bash -pip install "typer-slim[standard]" -``` - -The `standard` extra dependencies are `rich` and `shellingham`. - -**Note**: The `typer` command is only included in the `typer` package. +However, since version 0.22.0, we have stopped supporting this, and `typer-slim` now simply installs (all of) Typer. ## License diff --git a/docs/features.md b/docs/features.md index 5a8643fa35..02f7d71046 100644 --- a/docs/features.md +++ b/docs/features.md @@ -54,20 +54,13 @@ The resulting CLI apps created with **Typer** have the nice features of many "pr Auto completion works when you create a package (installable with `pip`). Or when using the `typer` command. -**Typer** uses `shellingham` to auto-detect the current shell when installing completion. If you don't want to include `shellingham`, install `typer-slim`. +**Typer** uses `shellingham` to auto-detect the current shell when installing completion. **Typer** will automatically create 2 *CLI options*: * `--install-completion`: Install completion for the current shell. * `--show-completion`: Show completion for the current shell, to copy it or customize the installation. -If you didn't add `shellingham` (if you installed `pip install typer-slim`) those *CLI options* take a value with the name of the shell to install completion for, e.g.: - -* `--install-completion bash`. -* `--show-completion powershell`. - -Then you can tell the user to install completion after installing your CLI program and the rest will just work. - /// /// tip diff --git a/docs/index.md b/docs/index.md index 12520fe0f5..5adeead825 100644 --- a/docs/index.md +++ b/docs/index.md @@ -373,23 +373,9 @@ By default it also comes with extra standard dependencies: ### `typer-slim` -If you don't want the extra standard optional dependencies, install `typer-slim` instead. +There used to be a slimmedd-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command. -When you install with: - -```bash -pip install typer -``` - -...it includes the same code and dependencies as: - -```bash -pip install "typer-slim[standard]" -``` - -The `standard` extra dependencies are `rich` and `shellingham`. - -**Note**: The `typer` command is only included in the `typer` package. +However, since version 0.22.0, we have stopped supporting this, and `typer-slim` now simply installs (all of) Typer. ## License diff --git a/docs/tutorial/package.md b/docs/tutorial/package.md index 617c93cd0b..e58256b428 100644 --- a/docs/tutorial/package.md +++ b/docs/tutorial/package.md @@ -681,12 +681,6 @@ You just have to pass it the module to import (`rick_portal_gun.main`) and it wi By specifying the `--name` of the program it will be able to use it while generating the docs. -/// tip - -If you installed `typer-slim` and don't have the `typer` command, you can use `python -m typer` instead. - -/// - ### Publish a new version with the docs Now you can publish a new version with the updated docs. diff --git a/docs/tutorial/typer-command.md b/docs/tutorial/typer-command.md index 8f186c1855..ee07f1260d 100644 --- a/docs/tutorial/typer-command.md +++ b/docs/tutorial/typer-command.md @@ -18,13 +18,7 @@ pip install typer ...it includes the `typer` command. -If you don't want to have the `typer` command, you can install instead: - -```bash -pip install typer-slim -``` - -You can still use it by calling the Typer library as a module with: +If you don't want to use the `typer` command, you can call the Typer library as a module with: ```bash python -m typer @@ -261,7 +255,7 @@ $ typer some_script.py utils docs /// tip -If you installed only `typer-slim` and you don't have the `typer` command, you can still generate docs with: +If you don't want to use the `typer` command, you can still generate docs with: ```console $ python -m typer some_script.py utils docs From fbced39305afe8e9ac1a98158b52c01314f0d700 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 6 Feb 2026 15:46:13 +0100 Subject: [PATCH 02/10] few more fixes in the docs --- README.md | 2 +- docs/index.md | 2 +- docs/tutorial/install.md | 10 ---------- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index bc206cc8ab..f271cfab82 100644 --- a/README.md +++ b/README.md @@ -367,7 +367,7 @@ By default it also comes with extra standard dependencies: ### `typer-slim` -There used to be a slimmedd-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command. +There used to be a slimmed-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command. However, since version 0.22.0, we have stopped supporting this, and `typer-slim` now simply installs (all of) Typer. diff --git a/docs/index.md b/docs/index.md index 5adeead825..214c22ffa0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -373,7 +373,7 @@ By default it also comes with extra standard dependencies: ### `typer-slim` -There used to be a slimmedd-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command. +There used to be a slimmed-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command. However, since version 0.22.0, we have stopped supporting this, and `typer-slim` now simply installs (all of) Typer. diff --git a/docs/tutorial/install.md b/docs/tutorial/install.md index 09ee0cfc2c..1a50e24681 100644 --- a/docs/tutorial/install.md +++ b/docs/tutorial/install.md @@ -16,18 +16,8 @@ Successfully installed typer click shellingham rich By default, `typer` comes with `rich` and `shellingham`. -/// note - -If you are an advanced user and want to opt out of these default extra dependencies, you can instead install `typer-slim`. - ```bash pip install typer ``` -...includes the same optional dependencies as: - -```bash -pip install "typer-slim[standard]" -``` - /// From 129d7b5ec619ad544a399cf8476fb668a2966429 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 6 Feb 2026 15:50:55 +0100 Subject: [PATCH 03/10] add typer as dependency of typer-slim --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 61790b949e..95c21614dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -110,6 +110,9 @@ sync-dependencies = [ [tool.tiangolo._internal-slim-build.packages.typer-slim.project] name = "typer-slim" +dependencies = [ + "typer", +] [tool.tiangolo._internal-slim-build.packages.typer] include-optional-dependencies = ["standard"] From 2f6708c4a9141aef8d7130027dd5e194e1085826 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 6 Feb 2026 16:06:03 +0100 Subject: [PATCH 04/10] assume shellingham is always present --- typer/_completion_shared.py | 20 +++++++------------- typer/completion.py | 3 +-- typer/core.py | 3 +-- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/typer/_completion_shared.py b/typer/_completion_shared.py index 4c4d79dda7..2d56c2a41b 100644 --- a/typer/_completion_shared.py +++ b/typer/_completion_shared.py @@ -6,10 +6,7 @@ from typing import Optional, Union import click -from typer.core import HAS_SHELLINGHAM - -if HAS_SHELLINGHAM: - import shellingham +import shellingham class Shells(str, Enum): @@ -246,14 +243,11 @@ def _get_shell_name() -> Union[str, None]: returned. """ name: Union[str, None] # N.B. shellingham is untyped - if HAS_SHELLINGHAM: - try: - # N.B. detect_shell returns a tuple of (shell name, shell command). - # We only need the name. - name, _cmd = shellingham.detect_shell() # noqa: TID251 - except shellingham.ShellDetectionFailure: # pragma: no cover - name = None - else: - name = None # pragma: no cover + try: + # N.B. detect_shell returns a tuple of (shell name, shell command). + # We only need the name. + name, _cmd = shellingham.detect_shell() # noqa: TID251 + except shellingham.ShellDetectionFailure: # pragma: no cover + name = None return name diff --git a/typer/completion.py b/typer/completion.py index db87f83e3f..0d621e411d 100644 --- a/typer/completion.py +++ b/typer/completion.py @@ -7,7 +7,6 @@ from ._completion_classes import completion_init from ._completion_shared import Shells, _get_shell_name, get_completion_script, install -from .core import HAS_SHELLINGHAM from .models import ParamMeta from .params import Option from .utils import get_params_from_function @@ -18,7 +17,7 @@ def get_completion_inspect_parameters() -> tuple[ParamMeta, ParamMeta]: completion_init() test_disable_detection = os.getenv("_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION") - if HAS_SHELLINGHAM and not test_disable_detection: + if not test_disable_detection: parameters = get_params_from_function(_install_completion_placeholder_function) else: parameters = get_params_from_function( diff --git a/typer/core.py b/typer/core.py index d0d888ccf0..83f6b0a316 100644 --- a/typer/core.py +++ b/typer/core.py @@ -29,9 +29,8 @@ MARKUP_MODE_KEY = "TYPER_RICH_MARKUP_MODE" HAS_RICH = importlib.util.find_spec("rich") is not None -HAS_SHELLINGHAM = importlib.util.find_spec("shellingham") is not None -if HAS_RICH: +if USE_RICH: DEFAULT_MARKUP_MODE: MarkupMode = "rich" else: # pragma: no cover DEFAULT_MARKUP_MODE = None From d0385748874b29791391255ead7565de868e6d8f Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 6 Feb 2026 16:15:45 +0100 Subject: [PATCH 05/10] change HAS_RICH to USE_RICH and read from env var TYPER_USE_RICH --- tests/assets/type_error_no_rich.py | 2 +- tests/assets/type_error_no_rich_short_disable.py | 2 +- tests/test_corner_cases.py | 2 +- .../test_arguments/test_envvar/test_tutorial001.py | 2 +- .../test_arguments/test_help/test_tutorial001.py | 2 +- .../test_arguments/test_help/test_tutorial008.py | 2 +- .../test_optional/test_tutorial001.py | 2 +- .../test_optional/test_tutorial003.py | 2 +- .../test_callback/test_tutorial001.py | 2 +- .../test_required/test_tutorial001_tutorial002.py | 2 +- .../test_bool/test_tutorial002.py | 2 +- .../test_number/test_tutorial001.py | 4 ++-- .../test_terminating/test_tutorial003.py | 2 +- typer/cli.py | 4 ++-- typer/core.py | 14 +++++++------- typer/main.py | 4 ++-- 16 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/assets/type_error_no_rich.py b/tests/assets/type_error_no_rich.py index 71e767dd0a..a8a6a36f5c 100644 --- a/tests/assets/type_error_no_rich.py +++ b/tests/assets/type_error_no_rich.py @@ -1,7 +1,7 @@ import typer import typer.main -typer.main.HAS_RICH = False +typer.main.USE_RICH = False app = typer.Typer() diff --git a/tests/assets/type_error_no_rich_short_disable.py b/tests/assets/type_error_no_rich_short_disable.py index 0c75055eb9..c986ecd9c7 100644 --- a/tests/assets/type_error_no_rich_short_disable.py +++ b/tests/assets/type_error_no_rich_short_disable.py @@ -1,7 +1,7 @@ import typer import typer.main -typer.main.HAS_RICH = False +typer.main.USE_RICH = False app = typer.Typer(pretty_exceptions_short=False) diff --git a/tests/test_corner_cases.py b/tests/test_corner_cases.py index dfef7ddb60..60e51671a6 100644 --- a/tests/test_corner_cases.py +++ b/tests/test_corner_cases.py @@ -18,7 +18,7 @@ def test_hidden_option(): def test_hidden_option_no_rich(monkeypatch: pytest.MonkeyPatch): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py index 93363ed35c..d9f6b9de4f 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py @@ -34,7 +34,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] [NAME]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py index 9ec3ecf813..c79d236b8f 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py @@ -34,7 +34,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] NAME" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py index b21d41ef0f..89ba7023c1 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py @@ -33,7 +33,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] [NAME]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py index ceb2935548..f27bbeeb42 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py @@ -37,7 +37,7 @@ def test_call_no_arg_standalone(mod: ModuleType): def test_call_no_arg_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): # Mainly for coverage - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app) assert result.exit_code != 0 assert "Error: Missing argument 'NAME'" in result.output diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py index 47502038d7..eaeb29afcf 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py @@ -26,7 +26,7 @@ def test_call_no_arg_standalone(): def test_call_no_arg_no_rich(monkeypatch: pytest.MonkeyPatch): # Mainly for coverage - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(app) assert result.exit_code != 0 assert "Error: Missing argument 'NAME'" in result.output diff --git a/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py b/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py index dc7f082ca0..05a7438109 100644 --- a/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py @@ -21,7 +21,7 @@ def test_help(): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "Manage users in the awesome CLI app." in result.output diff --git a/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py index 65c49d9e79..8e85150831 100644 --- a/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py @@ -46,7 +46,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--lastname" in result.output diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py index 9c1040c255..fe439779ff 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py @@ -36,7 +36,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--accept" in result.output diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py index 2c03fee7e2..6b7a47e815 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py @@ -34,7 +34,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--age" in result.output @@ -67,7 +67,7 @@ def test_invalid_age(mod: ModuleType): def test_invalid_score(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(mod.app, ["5", "--age", "20", "--score", "100.5"]) assert result.exit_code != 0 assert "Invalid value for '--score'" in result.output diff --git a/tests/test_tutorial/test_terminating/test_tutorial003.py b/tests/test_tutorial/test_terminating/test_tutorial003.py index f1fcac68fb..030ae63863 100644 --- a/tests/test_tutorial/test_terminating/test_tutorial003.py +++ b/tests/test_tutorial/test_terminating/test_tutorial003.py @@ -33,7 +33,7 @@ def test_root_no_standalone(): def test_root_no_rich(monkeypatch: pytest.MonkeyPatch): # Mainly for coverage - monkeypatch.setattr(typer.core, "HAS_RICH", False) + monkeypatch.setattr(typer.core, "USE_RICH", False) result = runner.invoke(app, ["root"]) assert result.exit_code == 1 assert "The root user is reserved" in result.output diff --git a/typer/cli.py b/typer/cli.py index ef83bf87a0..392921528a 100644 --- a/typer/cli.py +++ b/typer/cli.py @@ -10,7 +10,7 @@ from click import Command, Group, Option from . import __version__ -from .core import HAS_RICH, MARKUP_MODE_KEY +from .core import USE_RICH, MARKUP_MODE_KEY default_app_names = ("app", "cli", "main") default_func_names = ("main", "cli", "app") @@ -202,7 +202,7 @@ def get_docs_for_click( rich_markup_mode = None if hasattr(ctx, "obj") and isinstance(ctx.obj, dict): rich_markup_mode = ctx.obj.get(MARKUP_MODE_KEY, None) - to_parse: bool = bool(HAS_RICH and (rich_markup_mode == "rich")) + to_parse: bool = bool(USE_RICH and (rich_markup_mode == "rich")) if obj.help: docs += f"{_parse_html(to_parse, obj.help)}\n\n" usage_pieces = obj.collect_usage_pieces(ctx) diff --git a/typer/core.py b/typer/core.py index 83f6b0a316..42889ea2cb 100644 --- a/typer/core.py +++ b/typer/core.py @@ -28,7 +28,7 @@ MarkupMode = Literal["markdown", "rich", None] MARKUP_MODE_KEY = "TYPER_RICH_MARKUP_MODE" -HAS_RICH = importlib.util.find_spec("rich") is not None +USE_RICH = os.getenv("TYPER_USE_RICH", True) if USE_RICH: DEFAULT_MARKUP_MODE: MarkupMode = "rich" @@ -206,7 +206,7 @@ def _main( if not standalone_mode: raise # Typer override - if HAS_RICH and rich_markup_mode is not None: + if USE_RICH and rich_markup_mode is not None: from . import rich_utils rich_utils.rich_format_error(e) @@ -238,7 +238,7 @@ def _main( if not standalone_mode: raise # Typer override - if HAS_RICH and rich_markup_mode is not None: + if USE_RICH and rich_markup_mode is not None: from . import rich_utils rich_utils.rich_abort_error() @@ -369,7 +369,7 @@ def get_help_record(self, ctx: click.Context) -> Optional[tuple[str, str]]: rich_markup_mode = None if hasattr(ctx, "obj") and isinstance(ctx.obj, dict): rich_markup_mode = ctx.obj.get(MARKUP_MODE_KEY, None) - if HAS_RICH and rich_markup_mode == "rich": + if USE_RICH and rich_markup_mode == "rich": # This is needed for when we want to export to HTML from . import rich_utils @@ -591,7 +591,7 @@ def _write_opts(opts: Sequence[str]) -> str: rich_markup_mode = None if hasattr(ctx, "obj") and isinstance(ctx.obj, dict): rich_markup_mode = ctx.obj.get(MARKUP_MODE_KEY, None) - if HAS_RICH and rich_markup_mode == "rich": + if USE_RICH and rich_markup_mode == "rich": # This is needed for when we want to export to HTML from . import rich_utils @@ -734,7 +734,7 @@ def main( ) def format_help(self, ctx: click.Context, formatter: click.HelpFormatter) -> None: - if not HAS_RICH or self.rich_markup_mode is None: + if not USE_RICH or self.rich_markup_mode is None: if not hasattr(ctx, "obj") or ctx.obj is None: ctx.ensure_object(dict) if isinstance(ctx.obj, dict): @@ -822,7 +822,7 @@ def main( ) def format_help(self, ctx: click.Context, formatter: click.HelpFormatter) -> None: - if not HAS_RICH or self.rich_markup_mode is None: + if not USE_RICH or self.rich_markup_mode is None: return super().format_help(ctx, formatter) from . import rich_utils diff --git a/typer/main.py b/typer/main.py index e8c6b9e429..e5930fc5f2 100644 --- a/typer/main.py +++ b/typer/main.py @@ -22,7 +22,7 @@ from .completion import get_completion_inspect_parameters from .core import ( DEFAULT_MARKUP_MODE, - HAS_RICH, + USE_RICH, MarkupMode, TyperArgument, TyperCommand, @@ -75,7 +75,7 @@ def except_hook( click_path = os.path.dirname(click.__file__) internal_dir_names = [typer_path, click_path] exc = exc_value - if HAS_RICH: + if USE_RICH: from . import rich_utils rich_tb = rich_utils.get_traceback(exc, exception_config, internal_dir_names) From 986103887216956ba17a8690a52f28921c908292 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:16:30 +0000 Subject: [PATCH 06/10] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typer/cli.py | 2 +- typer/core.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/typer/cli.py b/typer/cli.py index 392921528a..ac96b0d8ed 100644 --- a/typer/cli.py +++ b/typer/cli.py @@ -10,7 +10,7 @@ from click import Command, Group, Option from . import __version__ -from .core import USE_RICH, MARKUP_MODE_KEY +from .core import MARKUP_MODE_KEY, USE_RICH default_app_names = ("app", "cli", "main") default_func_names = ("main", "cli", "app") diff --git a/typer/core.py b/typer/core.py index 42889ea2cb..e0da8dc936 100644 --- a/typer/core.py +++ b/typer/core.py @@ -1,5 +1,4 @@ import errno -import importlib.util import inspect import os import sys From 58fe90269c1372a231743bad171f4f2b067e205e Mon Sep 17 00:00:00 2001 From: svlandeg Date: Mon, 9 Feb 2026 09:30:03 +0100 Subject: [PATCH 07/10] update docs --- README.md | 10 ++++------ docs/index.md | 8 +++----- docs/tutorial/commands/help.md | 9 ++++----- docs/tutorial/exceptions.md | 5 +++-- docs/tutorial/options-autocompletion.md | 2 +- docs/tutorial/options/help.md | 2 +- docs/tutorial/printing.md | 2 +- docs/tutorial/progressbar.md | 2 +- docs/tutorial/prompt.md | 2 +- 9 files changed, 19 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index f271cfab82..371dbf6f71 100644 --- a/README.md +++ b/README.md @@ -356,20 +356,18 @@ For a more complete example including more features, see the Click. - -By default it also comes with extra standard dependencies: +**Typer** stands on the shoulders of giants. It has three required dependencies: +* Click: a popular tool for building CLIs in Python. Typer is based on it. * rich: to show nicely formatted errors automatically. * shellingham: to automatically detect the current shell when installing completion. - * With `shellingham` you can just use `--install-completion`. - * Without `shellingham`, you have to pass the name of the shell to install completion for, e.g. `--install-completion bash`. ### `typer-slim` There used to be a slimmed-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command. -However, since version 0.22.0, we have stopped supporting this, and `typer-slim` now simply installs (all of) Typer. +However, since version 0.22.0, we have stopped supporting this, and `typer-slim` now simply installs (all of) Typer and its internal dependencies. +If you want to disable Rich globally, you can set an environmental variable "TYPER_USE_RICH" to `False`/`0`. ## License diff --git a/docs/index.md b/docs/index.md index 214c22ffa0..d4cccdc921 100644 --- a/docs/index.md +++ b/docs/index.md @@ -362,20 +362,18 @@ For a more complete example including more features, see the Click. - -By default it also comes with extra standard dependencies: +**Typer** stands on the shoulders of giants. It has three required dependencies: +* Click: a popular tool for building CLIs in Python. Typer is based on it. * rich: to show nicely formatted errors automatically. * shellingham: to automatically detect the current shell when installing completion. - * With `shellingham` you can just use `--install-completion`. - * Without `shellingham`, you have to pass the name of the shell to install completion for, e.g. `--install-completion bash`. ### `typer-slim` There used to be a slimmed-down version of Typer called `typer-slim`, which didn't include the dependencies `rich` and `shellingham`, nor the `typer` command. However, since version 0.22.0, we have stopped supporting this, and `typer-slim` now simply installs (all of) Typer. +If you want to disable Rich globally, you can set an environmental variable "TYPER_USE_RICH" to `False`/`0`. ## License diff --git a/docs/tutorial/commands/help.md b/docs/tutorial/commands/help.md index ae330341da..d82256464d 100644 --- a/docs/tutorial/commands/help.md +++ b/docs/tutorial/commands/help.md @@ -202,19 +202,18 @@ If there are multiple close matches, Typer will suggest them all. This feature u ## Rich Markdown and Markup -If you have **Rich** installed as described in [Printing and Colors](../printing.md){.internal-link target=_blank}, you can configure your app to enable markup text with the parameter `rich_markup_mode`. - -Then you can use more formatting in the docstrings and the `help` parameter for *CLI arguments* and *CLI options*. You will see more about it below. 👇 +Typer installs **Rich** to allow for more formatting in the docstrings and the `help` parameter for *CLI arguments* and *CLI options*. You will see more about it below. 👇 /// info -By default, `rich_markup_mode` is `None` if Rich is not installed, and `"rich"` if it is installed. In the latter case, you can set `rich_markup_mode` to `None` to disable rich text formatting. +You can disable rich text formatting by setting `rich_markup_mode` to `None` for your specific app. +Alternatively, you can disable it globally using an environmental variable "TYPER_USE_RICH" set to `False`/`0`. /// ### Rich Markup -If you set `rich_markup_mode="rich"` when creating the `typer.Typer()` app, you will be able to use Rich Console Markup in the docstring, and even in the help for the *CLI arguments* and options: +If you set `rich_markup_mode="rich"` when creating the `typer.Typer()` app (which is the default), you will be able to use Rich Console Markup in the docstring, and even in the help for the *CLI arguments* and options: {* docs_src/commands/help/tutorial004_an_py39.py hl[5,11,15:17,22,25,28] *} diff --git a/docs/tutorial/exceptions.md b/docs/tutorial/exceptions.md index 3a87da1ec3..cb1c457a3b 100644 --- a/docs/tutorial/exceptions.md +++ b/docs/tutorial/exceptions.md @@ -14,7 +14,7 @@ This code is broken because you can't sum a string and a number (`name + 3`). ## Exceptions with Rich -If you have **Rich** installed (for example if you installed `"typer[all]"`), **Typer** will use it to automatically show you nicely printed errors. +**Typer** will automatically use Rich to automatically show you nicely printed errors. It will **omit** all the parts of the traceback (the chain of things that called your function) that come from the internal parts in Typer and Click. @@ -47,7 +47,8 @@ $ python main.py ## Exceptions without Rich -If you don't have Rich installed, Typer will still do some tricks to show you the information **as clearly as possible**: +You can disable Rich globally using the environmental variable `TYPER_USE_RICH`. +In this case, Typer will still do some tricks to show you the information **as clearly as possible**:
diff --git a/docs/tutorial/options-autocompletion.md b/docs/tutorial/options-autocompletion.md index 773a439e06..a68cb7986a 100644 --- a/docs/tutorial/options-autocompletion.md +++ b/docs/tutorial/options-autocompletion.md @@ -300,7 +300,7 @@ Using `stderr=True` tells **Rich** that the output should be shown in "standard /// info -If you can't install and use Rich, you can also use `print(lastname, file=sys.stderr)` or `typer.echo("some text", err=True)` instead. +If you have disabled Rich, you can also use `print(lastname, file=sys.stderr)` or `typer.echo("some text", err=True)` instead. /// diff --git a/docs/tutorial/options/help.md b/docs/tutorial/options/help.md index 509823815f..e6a5dbafa6 100644 --- a/docs/tutorial/options/help.md +++ b/docs/tutorial/options/help.md @@ -54,7 +54,7 @@ Options: The same as with *CLI arguments*, you can put the help for some *CLI options* in different panels to be shown with the `--help` option. -If you have installed Rich as described in the docs for [Printing and Colors](../printing.md){.internal-link target=_blank}, you can set the `rich_help_panel` parameter to the name of the panel you want for each *CLI option*: +Using Rich, you can set the `rich_help_panel` parameter to the name of the panel you want for each *CLI option*: {* docs_src/options/help/tutorial002_an_py39.py hl[15,21] *} diff --git a/docs/tutorial/printing.md b/docs/tutorial/printing.md index c4a1582f40..7c8c4dea69 100644 --- a/docs/tutorial/printing.md +++ b/docs/tutorial/printing.md @@ -112,7 +112,7 @@ In general, **Typer** tends to be the entry point to your program, taking the fi **Rich** is useful for the parts that need to *display* information. Showing beautiful content on the screen. -The best results for your command line application would be achieved combining both **Typer** and **Rich**. +The best results for your command line application are achieved combining both **Typer** and **Rich**. ## "Standard Output" and "Standard Error" diff --git a/docs/tutorial/progressbar.md b/docs/tutorial/progressbar.md index 57b1fbd57e..a74906957e 100644 --- a/docs/tutorial/progressbar.md +++ b/docs/tutorial/progressbar.md @@ -75,7 +75,7 @@ If you can use Rich, use the information above, the Rich docs, and skip the rest /// -But if you can't use Rich, Typer (actually Click) comes with a simple utility to show progress bars. +But if you can't use Rich and have it disabled, Typer (actually Click) comes with a simple utility to show progress bars. /// info diff --git a/docs/tutorial/prompt.md b/docs/tutorial/prompt.md index 4bb119fd17..cc00041067 100644 --- a/docs/tutorial/prompt.md +++ b/docs/tutorial/prompt.md @@ -75,7 +75,7 @@ Aborted! ## Prompt with Rich -If you installed Rich as described in [Printing and Colors](printing.md){.internal-link target=_blank}, you can use Rich to prompt the user for input: +You can use Rich to prompt the user for input: {* docs_src/prompt/tutorial004_py39.py hl[2,9] *} From 2a906f7247a55cac15696d5add4bf79f054b0555 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 08:30:56 +0000 Subject: [PATCH 08/10] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 371dbf6f71..43ae5131df 100644 --- a/README.md +++ b/README.md @@ -366,7 +366,7 @@ For a more complete example including more features, see the Date: Mon, 9 Feb 2026 10:20:29 +0100 Subject: [PATCH 09/10] revert back to HAS_RICH --- tests/assets/type_error_no_rich.py | 2 +- tests/assets/type_error_no_rich_short_disable.py | 2 +- tests/test_corner_cases.py | 2 +- .../test_envvar/test_tutorial001.py | 2 +- .../test_arguments/test_help/test_tutorial001.py | 2 +- .../test_arguments/test_help/test_tutorial008.py | 2 +- .../test_optional/test_tutorial001.py | 2 +- .../test_optional/test_tutorial003.py | 2 +- .../test_callback/test_tutorial001.py | 2 +- .../test_tutorial001_tutorial002.py | 2 +- .../test_bool/test_tutorial002.py | 2 +- .../test_number/test_tutorial001.py | 4 ++-- .../test_terminating/test_tutorial003.py | 2 +- typer/cli.py | 4 ++-- typer/core.py | 16 ++++++++-------- typer/main.py | 4 ++-- 16 files changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/assets/type_error_no_rich.py b/tests/assets/type_error_no_rich.py index a8a6a36f5c..71e767dd0a 100644 --- a/tests/assets/type_error_no_rich.py +++ b/tests/assets/type_error_no_rich.py @@ -1,7 +1,7 @@ import typer import typer.main -typer.main.USE_RICH = False +typer.main.HAS_RICH = False app = typer.Typer() diff --git a/tests/assets/type_error_no_rich_short_disable.py b/tests/assets/type_error_no_rich_short_disable.py index c986ecd9c7..0c75055eb9 100644 --- a/tests/assets/type_error_no_rich_short_disable.py +++ b/tests/assets/type_error_no_rich_short_disable.py @@ -1,7 +1,7 @@ import typer import typer.main -typer.main.USE_RICH = False +typer.main.HAS_RICH = False app = typer.Typer(pretty_exceptions_short=False) diff --git a/tests/test_corner_cases.py b/tests/test_corner_cases.py index 60e51671a6..dfef7ddb60 100644 --- a/tests/test_corner_cases.py +++ b/tests/test_corner_cases.py @@ -18,7 +18,7 @@ def test_hidden_option(): def test_hidden_option_no_rich(monkeypatch: pytest.MonkeyPatch): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 diff --git a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py index d9f6b9de4f..93363ed35c 100644 --- a/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_envvar/test_tutorial001.py @@ -34,7 +34,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] [NAME]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py index c79d236b8f..9ec3ecf813 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial001.py @@ -34,7 +34,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] NAME" in result.output diff --git a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py index 89ba7023c1..b21d41ef0f 100644 --- a/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py +++ b/tests/test_tutorial/test_arguments/test_help/test_tutorial008.py @@ -33,7 +33,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "[OPTIONS] [NAME]" in result.output diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py index f27bbeeb42..ceb2935548 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial001.py @@ -37,7 +37,7 @@ def test_call_no_arg_standalone(mod: ModuleType): def test_call_no_arg_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): # Mainly for coverage - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app) assert result.exit_code != 0 assert "Error: Missing argument 'NAME'" in result.output diff --git a/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py b/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py index eaeb29afcf..47502038d7 100644 --- a/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py +++ b/tests/test_tutorial/test_arguments/test_optional/test_tutorial003.py @@ -26,7 +26,7 @@ def test_call_no_arg_standalone(): def test_call_no_arg_no_rich(monkeypatch: pytest.MonkeyPatch): # Mainly for coverage - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(app) assert result.exit_code != 0 assert "Error: Missing argument 'NAME'" in result.output diff --git a/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py b/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py index 05a7438109..dc7f082ca0 100644 --- a/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py +++ b/tests/test_tutorial/test_commands/test_callback/test_tutorial001.py @@ -21,7 +21,7 @@ def test_help(): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(app, ["--help"]) assert result.exit_code == 0 assert "Manage users in the awesome CLI app." in result.output diff --git a/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py index 8e85150831..65c49d9e79 100644 --- a/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_options/test_required/test_tutorial001_tutorial002.py @@ -46,7 +46,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--lastname" in result.output diff --git a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py index fe439779ff..9c1040c255 100644 --- a/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py +++ b/tests/test_tutorial/test_parameter_types/test_bool/test_tutorial002.py @@ -36,7 +36,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--accept" in result.output diff --git a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py index 6b7a47e815..2c03fee7e2 100644 --- a/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py +++ b/tests/test_tutorial/test_parameter_types/test_number/test_tutorial001.py @@ -34,7 +34,7 @@ def test_help(mod: ModuleType): def test_help_no_rich(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["--help"]) assert result.exit_code == 0 assert "--age" in result.output @@ -67,7 +67,7 @@ def test_invalid_age(mod: ModuleType): def test_invalid_score(monkeypatch: pytest.MonkeyPatch, mod: ModuleType): - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(mod.app, ["5", "--age", "20", "--score", "100.5"]) assert result.exit_code != 0 assert "Invalid value for '--score'" in result.output diff --git a/tests/test_tutorial/test_terminating/test_tutorial003.py b/tests/test_tutorial/test_terminating/test_tutorial003.py index 030ae63863..f1fcac68fb 100644 --- a/tests/test_tutorial/test_terminating/test_tutorial003.py +++ b/tests/test_tutorial/test_terminating/test_tutorial003.py @@ -33,7 +33,7 @@ def test_root_no_standalone(): def test_root_no_rich(monkeypatch: pytest.MonkeyPatch): # Mainly for coverage - monkeypatch.setattr(typer.core, "USE_RICH", False) + monkeypatch.setattr(typer.core, "HAS_RICH", False) result = runner.invoke(app, ["root"]) assert result.exit_code == 1 assert "The root user is reserved" in result.output diff --git a/typer/cli.py b/typer/cli.py index ac96b0d8ed..d39cfe588b 100644 --- a/typer/cli.py +++ b/typer/cli.py @@ -10,7 +10,7 @@ from click import Command, Group, Option from . import __version__ -from .core import MARKUP_MODE_KEY, USE_RICH +from .core import MARKUP_MODE_KEY, HAS_RICH default_app_names = ("app", "cli", "main") default_func_names = ("main", "cli", "app") @@ -202,7 +202,7 @@ def get_docs_for_click( rich_markup_mode = None if hasattr(ctx, "obj") and isinstance(ctx.obj, dict): rich_markup_mode = ctx.obj.get(MARKUP_MODE_KEY, None) - to_parse: bool = bool(USE_RICH and (rich_markup_mode == "rich")) + to_parse: bool = bool(HAS_RICH and (rich_markup_mode == "rich")) if obj.help: docs += f"{_parse_html(to_parse, obj.help)}\n\n" usage_pieces = obj.collect_usage_pieces(ctx) diff --git a/typer/core.py b/typer/core.py index e0da8dc936..3500090f64 100644 --- a/typer/core.py +++ b/typer/core.py @@ -27,9 +27,9 @@ MarkupMode = Literal["markdown", "rich", None] MARKUP_MODE_KEY = "TYPER_RICH_MARKUP_MODE" -USE_RICH = os.getenv("TYPER_USE_RICH", True) +HAS_RICH = os.getenv("TYPER_USE_RICH", True) -if USE_RICH: +if HAS_RICH: DEFAULT_MARKUP_MODE: MarkupMode = "rich" else: # pragma: no cover DEFAULT_MARKUP_MODE = None @@ -205,7 +205,7 @@ def _main( if not standalone_mode: raise # Typer override - if USE_RICH and rich_markup_mode is not None: + if HAS_RICH and rich_markup_mode is not None: from . import rich_utils rich_utils.rich_format_error(e) @@ -237,7 +237,7 @@ def _main( if not standalone_mode: raise # Typer override - if USE_RICH and rich_markup_mode is not None: + if HAS_RICH and rich_markup_mode is not None: from . import rich_utils rich_utils.rich_abort_error() @@ -368,7 +368,7 @@ def get_help_record(self, ctx: click.Context) -> Optional[tuple[str, str]]: rich_markup_mode = None if hasattr(ctx, "obj") and isinstance(ctx.obj, dict): rich_markup_mode = ctx.obj.get(MARKUP_MODE_KEY, None) - if USE_RICH and rich_markup_mode == "rich": + if HAS_RICH and rich_markup_mode == "rich": # This is needed for when we want to export to HTML from . import rich_utils @@ -590,7 +590,7 @@ def _write_opts(opts: Sequence[str]) -> str: rich_markup_mode = None if hasattr(ctx, "obj") and isinstance(ctx.obj, dict): rich_markup_mode = ctx.obj.get(MARKUP_MODE_KEY, None) - if USE_RICH and rich_markup_mode == "rich": + if HAS_RICH and rich_markup_mode == "rich": # This is needed for when we want to export to HTML from . import rich_utils @@ -733,7 +733,7 @@ def main( ) def format_help(self, ctx: click.Context, formatter: click.HelpFormatter) -> None: - if not USE_RICH or self.rich_markup_mode is None: + if not HAS_RICH or self.rich_markup_mode is None: if not hasattr(ctx, "obj") or ctx.obj is None: ctx.ensure_object(dict) if isinstance(ctx.obj, dict): @@ -821,7 +821,7 @@ def main( ) def format_help(self, ctx: click.Context, formatter: click.HelpFormatter) -> None: - if not USE_RICH or self.rich_markup_mode is None: + if not HAS_RICH or self.rich_markup_mode is None: return super().format_help(ctx, formatter) from . import rich_utils diff --git a/typer/main.py b/typer/main.py index e5930fc5f2..e8c6b9e429 100644 --- a/typer/main.py +++ b/typer/main.py @@ -22,7 +22,7 @@ from .completion import get_completion_inspect_parameters from .core import ( DEFAULT_MARKUP_MODE, - USE_RICH, + HAS_RICH, MarkupMode, TyperArgument, TyperCommand, @@ -75,7 +75,7 @@ def except_hook( click_path = os.path.dirname(click.__file__) internal_dir_names = [typer_path, click_path] exc = exc_value - if USE_RICH: + if HAS_RICH: from . import rich_utils rich_tb = rich_utils.get_traceback(exc, exception_config, internal_dir_names) From 28ef8047bc4cfca51a83af0926c84ce603a6c328 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 09:21:13 +0000 Subject: [PATCH 10/10] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typer/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typer/cli.py b/typer/cli.py index d39cfe588b..ef83bf87a0 100644 --- a/typer/cli.py +++ b/typer/cli.py @@ -10,7 +10,7 @@ from click import Command, Group, Option from . import __version__ -from .core import MARKUP_MODE_KEY, HAS_RICH +from .core import HAS_RICH, MARKUP_MODE_KEY default_app_names = ("app", "cli", "main") default_func_names = ("main", "cli", "app")