Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-typer-slim for
openSUSE:Factory checked in at 2025-10-23 16:35:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-typer-slim (Old)
and /work/SRC/openSUSE:Factory/.python-typer-slim.new.1980 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-typer-slim"
Thu Oct 23 16:35:36 2025 rev:19 rq:1312887 version:0.20.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-typer-slim/python-typer-slim.changes
2025-09-26 22:25:13.647793095 +0200
+++
/work/SRC/openSUSE:Factory/.python-typer-slim.new.1980/python-typer-slim.changes
2025-10-23 16:36:01.366795595 +0200
@@ -1,0 +2,7 @@
+Tue Oct 21 17:40:20 UTC 2025 - Matthias Bach <[email protected]> - 0.20.0
+
+- Update to 0.20.0
+ * Enable command suggestions on typo by default.
+ * Add support for Python 3.14.
+
+-------------------------------------------------------------------
Old:
----
typer_slim-0.19.2.tar.gz
New:
----
typer_slim-0.20.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-typer-slim.spec ++++++
--- /var/tmp/diff_new_pack.4o9YTL/_old 2025-10-23 16:36:02.670850628 +0200
+++ /var/tmp/diff_new_pack.4o9YTL/_new 2025-10-23 16:36:02.686851304 +0200
@@ -20,7 +20,7 @@
%{?sle15_python_module_pythons}
Name: python-typer-slim
-Version: 0.19.2
+Version: 0.20.0
Release: 0
Summary: Typer, build great CLIs. Easy to code. Based on Python type
hints
License: MIT
++++++ typer_slim-0.19.2.tar.gz -> typer_slim-0.20.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/PKG-INFO
new/typer_slim-0.20.0/PKG-INFO
--- old/typer_slim-0.19.2/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/typer_slim-0.20.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: typer-slim
-Version: 0.19.2
+Version: 0.20.0
Summary: Typer, build great CLIs. Easy to code. Based on Python type hints.
Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= <[email protected]>
Classifier: Intended Audience :: Information Technology
@@ -22,6 +22,7 @@
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
Classifier: License :: OSI Approved :: MIT License
Project-URL: Homepage, https://github.com/fastapi/typer
Project-URL: Documentation, https://typer.tiangolo.com
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/typer_slim-0.19.2/docs_src/commands/index/tutorial005.py
new/typer_slim-0.20.0/docs_src/commands/index/tutorial005.py
--- old/typer_slim-0.19.2/docs_src/commands/index/tutorial005.py
1970-01-01 01:00:00.000000000 +0100
+++ new/typer_slim-0.20.0/docs_src/commands/index/tutorial005.py
2025-10-20 19:03:27.981639400 +0200
@@ -0,0 +1,17 @@
+import typer
+
+app = typer.Typer(suggest_commands=True)
+
+
[email protected]()
+def create():
+ typer.echo("Creating...")
+
+
[email protected]()
+def delete():
+ typer.echo("Deleting...")
+
+
+if __name__ == "__main__":
+ app()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/pyproject.toml
new/typer_slim-0.20.0/pyproject.toml
--- old/typer_slim-0.19.2/pyproject.toml 2025-09-23 11:47:28.214899000
+0200
+++ new/typer_slim-0.20.0/pyproject.toml 2025-10-20 19:03:33.792339600
+0200
@@ -32,6 +32,7 @@
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
"License :: OSI Approved :: MIT License",
]
dependencies = [
@@ -39,7 +40,7 @@
"typing-extensions >= 3.7.4.3",
]
readme = "README.md"
-version = "0.19.2"
+version = "0.20.0"
[project.urls]
Homepage = "https://github.com/fastapi/typer"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/requirements-docs.txt
new/typer_slim-0.20.0/requirements-docs.txt
--- old/typer_slim-0.19.2/requirements-docs.txt 2025-09-23 11:47:25.081859600
+0200
+++ new/typer_slim-0.20.0/requirements-docs.txt 2025-10-20 19:03:27.988541100
+0200
@@ -1,6 +1,6 @@
-e .
-mkdocs-material==9.6.20
+mkdocs-material==9.6.22
mdx-include >=1.4.1,<2.0.0
mkdocs-redirects>=1.2.1,<1.3.0
pyyaml >=5.3.1,<7.0.0
@@ -15,5 +15,5 @@
# griffe-typingdoc==0.2.5
# For griffe, it formats with black
# black==24.3.0
-mkdocs-macros-plugin==1.3.9
+mkdocs-macros-plugin==1.4.0
markdown-include-variants==0.0.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/requirements-tests.txt
new/typer_slim-0.20.0/requirements-tests.txt
--- old/typer_slim-0.19.2/requirements-tests.txt 2025-09-23
11:47:25.081859600 +0200
+++ new/typer_slim-0.20.0/requirements-tests.txt 2025-10-20
19:03:27.988541100 +0200
@@ -5,8 +5,8 @@
coverage[toml] >=6.2,<8.0
pytest-xdist >=1.32.0,<4.0.0
pytest-sugar >=0.9.4,<1.2.0
-mypy ==1.4.1
-ruff ==0.13.1
+mypy ==1.11.2
+ruff ==0.14.0
# Needed explicitly by typer-slim
rich >=10.11.0
shellingham >=1.3.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/scripts/deploy_docs_status.py
new/typer_slim-0.20.0/scripts/deploy_docs_status.py
--- old/typer_slim-0.19.2/scripts/deploy_docs_status.py 2025-09-23
11:47:25.081859600 +0200
+++ new/typer_slim-0.20.0/scripts/deploy_docs_status.py 2025-10-20
19:03:27.988541100 +0200
@@ -1,7 +1,8 @@
import logging
import re
+from typing import Literal
-from github import Github
+from github import Auth, Github
from pydantic import BaseModel, SecretStr
from pydantic_settings import BaseSettings
@@ -14,7 +15,7 @@
deploy_url: str | None = None
commit_sha: str
run_id: int
- is_done: bool = False
+ state: Literal["pending", "success", "error"] = "pending"
class LinkData(BaseModel):
@@ -27,7 +28,7 @@
settings = Settings()
logging.info(f"Using config: {settings.model_dump_json()}")
- g = Github(settings.github_token.get_secret_value())
+ g = Github(auth=Auth.Token(settings.github_token.get_secret_value()))
repo = g.get_repo(settings.github_repository)
use_pr = next(
(pr for pr in repo.get_pulls() if pr.head.sha == settings.commit_sha),
None
@@ -38,24 +39,35 @@
commits = list(use_pr.get_commits())
current_commit = [c for c in commits if c.sha == settings.commit_sha][0]
run_url =
f"https://github.com/{settings.github_repository}/actions/runs/{settings.run_id}"
- if settings.is_done and not settings.deploy_url:
+ if settings.state == "pending":
current_commit.create_status(
- state="success",
- description="No Docs Changes",
+ state="pending",
+ description="Deploying Docs",
context="deploy-docs",
target_url=run_url,
)
- logging.info("No docs changes found")
+ logging.info("No deploy URL available yet")
return
+ if settings.state == "error":
+ current_commit.create_status(
+ state="error",
+ description="Error Deploying Docs",
+ context="deploy-docs",
+ target_url=run_url,
+ )
+ logging.info("Error deploying docs")
+ return
+ assert settings.state == "success"
if not settings.deploy_url:
current_commit.create_status(
- state="pending",
- description="Deploying Docs",
+ state="success",
+ description="No Docs Changes",
context="deploy-docs",
target_url=run_url,
)
- logging.info("No deploy URL available yet")
+ logging.info("No docs changes found")
return
+ assert settings.deploy_url
current_commit.create_status(
state="success",
description="Docs Deployed",
@@ -84,7 +96,9 @@
links.append(link)
links.sort(key=lambda x: x.preview_link)
- message = f"📝 Docs preview for commit {settings.commit_sha} at:
{deploy_url}"
+ header = "## 📝 Docs preview"
+ message = header
+ message += f"\n\nLast commit {settings.commit_sha} at: {deploy_url}"
if links:
message += "\n\n### Modified Pages\n\n"
@@ -94,7 +108,17 @@
message += "\n"
print(message)
- use_pr.as_issue().create_comment(message)
+ issue = use_pr.as_issue()
+ comments = list(issue.get_comments())
+ for comment in comments:
+ if (
+ comment.body.startswith(header)
+ and comment.user.login == "github-actions[bot]"
+ ):
+ comment.edit(message)
+ break
+ else:
+ issue.create_comment(message)
logging.info("Finished")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/tests/test_suggest_commands.py
new/typer_slim-0.20.0/tests/test_suggest_commands.py
--- old/typer_slim-0.19.2/tests/test_suggest_commands.py 1970-01-01
01:00:00.000000000 +0100
+++ new/typer_slim-0.20.0/tests/test_suggest_commands.py 2025-10-20
19:03:27.990808000 +0200
@@ -0,0 +1,98 @@
+import typer
+from typer.testing import CliRunner
+
+runner = CliRunner()
+
+
+def test_typo_suggestion_enabled():
+ """Test that typo suggestions work when enabled"""
+ app = typer.Typer()
+
+ @app.command()
+ def create(): # pragma: no cover
+ typer.echo("Creating...")
+
+ @app.command()
+ def delete(): # pragma: no cover
+ typer.echo("Deleting...")
+
+ result = runner.invoke(app, ["crate"])
+ assert result.exit_code != 0
+ assert "No such command" in result.output
+ assert "Did you mean 'create'?" in result.output
+
+
+def test_typo_suggestion_multiple_matches():
+ """Test that multiple suggestions are shown when there are multiple close
matches"""
+ app = typer.Typer()
+
+ @app.command()
+ def create(): # pragma: no cover
+ typer.echo("Creating...")
+
+ @app.command()
+ def createnew(): # pragma: no cover
+ typer.echo("Creating new...")
+
+ result = runner.invoke(app, ["crate"])
+ assert result.exit_code != 0
+ assert "No such command" in result.output
+ assert "Did you mean" in result.output
+ assert "create" in result.output and "createnew" in result.output
+
+
+def test_typo_suggestion_no_matches():
+ """Test that no suggestions are shown when there are no close matches"""
+ app = typer.Typer()
+
+ @app.command()
+ def create(): # pragma: no cover
+ typer.echo("Creating...")
+
+ @app.command()
+ def delete(): # pragma: no cover
+ typer.echo("Deleting...")
+
+ result = runner.invoke(app, ["xyz"])
+ assert result.exit_code != 0
+ assert "No such command" in result.output
+ assert "Did you mean" not in result.output
+
+
+def test_typo_suggestion_exact_match_works():
+ """Test that exact matches still work normally"""
+ app = typer.Typer()
+
+ @app.command()
+ def create():
+ typer.echo("Creating...")
+
+ @app.command()
+ def delete():
+ typer.echo("Deleting...")
+
+ result = runner.invoke(app, ["create"])
+ assert result.exit_code == 0
+ assert "Creating..." in result.output
+
+ result = runner.invoke(app, ["delete"])
+ assert result.exit_code == 0
+ assert "Deleting..." in result.output
+
+
+def test_typo_suggestion_disabled():
+ """Test that typo suggestions can be explicitly disabled"""
+ app = typer.Typer(suggest_commands=False)
+
+ @app.command()
+ def create(): # pragma: no cover
+ typer.echo("Creating...")
+
+ @app.command()
+ def delete(): # pragma: no cover
+ typer.echo("Deleting...")
+
+ result = runner.invoke(app, ["crate"])
+ assert result.exit_code != 0
+ assert "No such command" in result.output
+ assert "Did you mean" not in result.output
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/typer_slim-0.19.2/tests/test_tutorial/test_commands/test_index/test_tutorial005.py
new/typer_slim-0.20.0/tests/test_tutorial/test_commands/test_index/test_tutorial005.py
---
old/typer_slim-0.19.2/tests/test_tutorial/test_commands/test_index/test_tutorial005.py
1970-01-01 01:00:00.000000000 +0100
+++
new/typer_slim-0.20.0/tests/test_tutorial/test_commands/test_index/test_tutorial005.py
2025-10-20 19:03:27.993790900 +0200
@@ -0,0 +1,24 @@
+from typer.testing import CliRunner
+
+from docs_src.commands.index import tutorial005 as mod
+
+app = mod.app
+runner = CliRunner()
+
+
+def test_creates_successfully():
+ """Verify the example runs without errors"""
+ result = runner.invoke(app, ["create"])
+ assert result.exit_code == 0
+ assert "Creating..." in result.output
+
+ result = runner.invoke(app, ["delete"])
+ assert result.exit_code == 0
+ assert "Deleting..." in result.output
+
+
+def test_shows_suggestion():
+ """Verify command suggestions appear for typos"""
+ result = runner.invoke(app, ["crate"])
+ assert result.exit_code != 0
+ assert "Did you mean 'create'?" in result.output
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/typer/__init__.py
new/typer_slim-0.20.0/typer/__init__.py
--- old/typer_slim-0.19.2/typer/__init__.py 2025-09-23 11:47:25.092859700
+0200
+++ new/typer_slim-0.20.0/typer/__init__.py 2025-10-20 19:03:27.999488600
+0200
@@ -1,6 +1,6 @@
"""Typer, build great CLIs. Easy to code. Based on Python type hints."""
-__version__ = "0.19.2"
+__version__ = "0.20.0"
from shutil import get_terminal_size as get_terminal_size
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/typer/core.py
new/typer_slim-0.20.0/typer/core.py
--- old/typer_slim-0.19.2/typer/core.py 2025-09-23 11:47:25.093859700 +0200
+++ new/typer_slim-0.20.0/typer/core.py 2025-10-20 19:03:27.999779200 +0200
@@ -3,6 +3,7 @@
import inspect
import os
import sys
+from difflib import get_close_matches
from enum import Enum
from gettext import gettext as _
from typing import (
@@ -22,7 +23,6 @@
import click
import click.core
import click.formatting
-import click.parser
import click.shell_completion
import click.types
import click.utils
@@ -750,11 +750,13 @@
# Rich settings
rich_markup_mode: MarkupMode = DEFAULT_MARKUP_MODE,
rich_help_panel: Union[str, None] = None,
+ suggest_commands: bool = True,
**attrs: Any,
) -> None:
super().__init__(name=name, commands=commands, **attrs)
self.rich_markup_mode: MarkupMode = rich_markup_mode
self.rich_help_panel = rich_help_panel
+ self.suggest_commands = suggest_commands
def format_options(
self, ctx: click.Context, formatter: click.HelpFormatter
@@ -772,6 +774,23 @@
self, ctx_args=ctx_args, prog_name=prog_name,
complete_var=complete_var
)
+ def resolve_command(
+ self, ctx: click.Context, args: List[str]
+ ) -> Tuple[Optional[str], Optional[click.Command], List[str]]:
+ try:
+ return super().resolve_command(ctx, args)
+ except click.UsageError as e:
+ if self.suggest_commands:
+ available_commands = list(self.commands.keys())
+ if available_commands and args:
+ typo = args[0]
+ matches = get_close_matches(typo, available_commands)
+ if matches:
+ suggestions = ", ".join(f"{m!r}" for m in matches)
+ message = e.message.rstrip(".")
+ e.message = f"{message}. Did you mean {suggestions}?"
+ raise
+
def main(
self,
args: Optional[Sequence[str]] = None,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/typer_slim-0.19.2/typer/main.py
new/typer_slim-0.20.0/typer/main.py
--- old/typer_slim-0.19.2/typer/main.py 2025-09-23 11:47:25.093859700 +0200
+++ new/typer_slim-0.20.0/typer/main.py 2025-10-20 19:03:27.999779200 +0200
@@ -135,6 +135,7 @@
# Rich settings
rich_markup_mode: MarkupMode = Default(DEFAULT_MARKUP_MODE),
rich_help_panel: Union[str, None] = Default(None),
+ suggest_commands: bool = True,
pretty_exceptions_enable: bool = True,
pretty_exceptions_show_locals: bool = True,
pretty_exceptions_short: bool = True,
@@ -142,6 +143,7 @@
self._add_completion = add_completion
self.rich_markup_mode: MarkupMode = rich_markup_mode
self.rich_help_panel = rich_help_panel
+ self.suggest_commands = suggest_commands
self.pretty_exceptions_enable = pretty_exceptions_enable
self.pretty_exceptions_show_locals = pretty_exceptions_show_locals
self.pretty_exceptions_short = pretty_exceptions_short
@@ -330,6 +332,7 @@
TyperInfo(typer_instance),
pretty_exceptions_short=typer_instance.pretty_exceptions_short,
rich_markup_mode=typer_instance.rich_markup_mode,
+ suggest_commands=typer_instance.suggest_commands,
)
return group
@@ -456,6 +459,7 @@
group_info: TyperInfo,
*,
pretty_exceptions_short: bool,
+ suggest_commands: bool,
rich_markup_mode: MarkupMode,
) -> TyperGroup:
assert group_info.typer_instance, (
@@ -475,6 +479,7 @@
sub_group_info,
pretty_exceptions_short=pretty_exceptions_short,
rich_markup_mode=rich_markup_mode,
+ suggest_commands=suggest_commands,
)
if sub_group.name:
commands[sub_group.name] = sub_group
@@ -523,6 +528,7 @@
rich_markup_mode=rich_markup_mode,
# Rich settings
rich_help_panel=solved_info.rich_help_panel,
+ suggest_commands=suggest_commands,
)
return group