Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.5.0] - 2026-01-27

### Changed

- `typer` is now optional dependency, and will not be installed by default.
Packages using `typer` should now explicitly install `typer` as a dependency.
([#55](https://github.com/pyodide/pyodide-cli/pull/55))

## [0.4.0] - 2025-09-07

### Changed
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ You can register a subcommand in the `pyodide` CLI in your own package by:
do_something = "<your-package>.cli:main"
```

where in this example `main` needs to be a function with type annotations
that can be converted to a CLI with [typer](https://typer.tiangolo.com/).
where in this example `main` needs to be either:
- A [click](https://click.palletsprojects.com/) command/group (recommended)
- A [typer](https://typer.tiangolo.com/) app or function (requires `typer` to be installed)


## License
Expand Down
21 changes: 15 additions & 6 deletions pyodide_cli/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@
from importlib.metadata import Distribution, EntryPoint
from importlib.metadata import distribution as importlib_distribution
from importlib.metadata import entry_points
from typing import override
from typing import TYPE_CHECKING, override

import click
import typer

from . import __version__

if TYPE_CHECKING:
import typer

try:
import typer # noqa: F811

TYPER_AVAILABLE = True
except ImportError:
TYPER_AVAILABLE = False


class OriginGroup(click.Group):
"""A click Group to support grouped command help message by its origin."""
Expand Down Expand Up @@ -154,9 +163,9 @@ def register_plugins():
pkgname = _entrypoint_to_pkgname(ep)
if isinstance(module, click.Command):
cmd = module
elif isinstance(module, typer.Typer):
elif TYPER_AVAILABLE and isinstance(module, typer.Typer):
cmd = typer.main.get_command(module)
elif callable(module):
elif TYPER_AVAILABLE and callable(module):
typer_kwargs = getattr(module, "typer_kwargs", {})
app = typer.Typer()
app.command(
Expand All @@ -176,9 +185,9 @@ def main():


if "sphinx" in sys.modules and __name__ != "__main__":
# Create the typer click object to generate docs with sphinx-click
# Create the click object to generate docs with sphinx-click
register_plugins()
typer_click_object = cli
click_object = cli

if __name__ == "__main__":
main()
6 changes: 2 additions & 4 deletions pyodide_cli/tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ def test_cli_version(plugins):


def test_click_click_object_defintion():
# By default the typer-click-object is not defined
# Run in a separate process to make s
q = Queue()

def func(q: Queue, with_sphinx=False):
Expand All @@ -56,13 +54,13 @@ def func(q: Queue, with_sphinx=False):
p.start()
p.join()
app_dir = q.get()
assert "typer_click_object" not in app_dir
assert "click_object" not in app_dir

p = Process(target=func, args=(q,), kwargs={"with_sphinx": True})
p.start()
p.join()
app_dir = q.get()
assert "typer_click_object" in app_dir
assert "click_object" in app_dir


def test_plugin_origin(plugins):
Expand Down
7 changes: 5 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ classifiers = [
]
requires-python = ">= 3.12"
dependencies = [
"typer",
"click",
"rich",
]

Expand All @@ -28,7 +28,10 @@ Homepage = "https://github.com/pyodide/pyodide"
Documentation = "https://pyodide.org/en/stable/"

[project.optional-dependencies]
test = ["pytest"]
test = [
"pytest",
"typer",
]

[tool.hatch.version]
source = "vcs"
Expand Down