⨠Add `module:function` syntax support for typer CLI
Adds support for specifying functions directly using colon syntax in the typer CLI, as used in pyproject console scripts entrypoint syntax, and projects like uvicorn/gunicorn.
Described in discussion #1274
Before:
$ typer 'autocli.one:step_1' run 123
Not a valid file or Python module: autocli.one:step_1
$ typer --func=step_1 'autocli.one' run 123 # Required explicit --func flag
Step 1: Processing with a=123, result=processed_123.txt
After:
$ typer 'autocli.one:step_1' run 123
Step 1: Processing with a=123, result=processed_123.txt
$ typer 'path/to/file.py:step_1' run 123 # Also works with file paths
Step 1: Processing with a=123, result=processed_123.txt
The change is pretty minimal - 4 lines added to maybe_update_state() to parse the colon syntax and set the function parameter on the click Context params dict which is then picked up in the existing part of the function afterwards.
Changes:
- [x] Feature: Parse
"module:function"and"/path/to/file.py:function"syntax intyper.cli:maybe_update_state - [x] Tests: Add coverage of both module and file path variants
- [x] Docs: Updated tutorial with examples
š Docs preview for commit 21374081c1807be913be579cecc1d7d6833b6ba4 at: https://27c4c869.typertiangolo.pages.dev
Modified Pages
- https://27c4c869.typertiangolo.pages.dev/tutorial/typer-command/ - (before)
Not sure why CI failed, maybe it needs a label added (triage)? Let me know if I can assist š
Rebased to update with trunk, all checks passed :smile:
š Docs preview for commit 88b4ffbad702723ec003e9bb2f13829b3f8d4603 at: https://d829fb58.typertiangolo.pages.dev
Modified Pages
- https://d829fb58.typertiangolo.pages.dev/tutorial/typer-command/ - (before)
Great, this looks ready @svlandeg :smile:
Thanks @lmmx! I'll try and review this soonish.
Oh great catch ! Yes we can check that, very good
import os
def maybe_update_state(ctx: click.Context) -> None:
path_or_module = ctx.params.get("path_or_module")
if path_or_module and ":" in path_or_module:
drive, _ = os.path.splitdrive(path_or_module)
if not drive: # avoid misinterpreting "C:\..." on Windows
module_part, func_part = path_or_module.rsplit(":", 1)
path_or_module = module_part
ctx.params.update({"func": func_part})
ctx.params["path_or_module"] = path_or_module
Hmm and Iād add an OS check to that condition gate too
No worries, maybe it felt like a good idea at the time but totally your call :relaxed: