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
 

Reply via email to