Files
2026-06-01 21:42:05 +00:00

51 lines
3.3 KiB
Markdown

# Click source notes
Repo: `pallets/click`
Local checkout: `/home/ubuntu/repos/rodin-sources/click`
## Why this repo is useful
- Click is a strong source for CLI API design: stable top-level exports, context-passing conventions, and user-facing exception behavior.
- It is especially useful because the implementation ties API design directly to operator experience at the terminal.
## The package root is a curated facade with compatibility shims
### Repeated evidence
- `src/click/__init__.py:10-75` re-exports commands, decorators, exceptions, types, and terminal helpers from internal modules.
- `src/click/__init__.py:77-124` uses `__getattr__` to keep deprecated compatibility names (`BaseCommand`, `MultiCommand`, `OptionParser`, `__version__`) working while emitting warnings.
### Why it matters
Repeated signal: mature libraries often keep the package root stable even while internal layout evolves. Click treats the package root as the user-facing API and places compatibility logic there deliberately.
### Caveat / counterexample
Compatibility shims are useful, but they are debt. Click's use of deprecation warnings is the important pattern: keep compatibility explicit and time-bounded rather than silently permanent.
## Command state is passed through context objects, not globals
### Repeated evidence
- `docs/complex.md:53-61` explains that callbacks do not receive context unless they opt in, and that `Context.invoke` mediates invocation.
- `docs/complex.md:92-99` shows a root command storing application state on `ctx.obj`.
- `docs/complex.md:107-113` states directly that `Context.obj` is the place commands are supposed to remember what they need to pass to children.
- `src/click/decorators.py:51-93` implements `make_pass_decorator(...)` by searching the linked context chain for the nearest object of the desired type and invoking the callback with it.
### Why it matters
Repeated signal: Click favors explicit, nestable context propagation over module globals or hidden singletons. That matters for complex CLIs with subcommands and plugins.
### Caveat / counterexample
`docs/complex.md:143-163` points out the interleaved-command problem: plugin layers can replace `ctx.obj`. That is why `make_pass_decorator(...)` exists; plain `pass_obj` is not always enough once commands are nested by third parties.
## Exceptions encode user-visible behavior, not just categorization
### Repeated evidence
- `src/click/exceptions.py:35-65` defines `ClickException` with an exit code, cached color behavior, and a `show()` method for terminal rendering.
- `src/click/exceptions.py:68-111` defines `UsageError` with a different exit code and help-aware rendering that prints usage plus a "Try '--help'" hint when context is available.
- `src/click/exceptions.py:114-118` documents `BadParameter` as a subtype that gains parameter context automatically.
### Why it matters
Repeated signal: in CLI libraries, exceptions often need to carry exit semantics and presentation rules, not just messages. Click's hierarchy is built around what the operator should see next.
## Pattern candidates supported by this repo
- expose a stable package-level facade over internal modules
- use explicit compatibility shims with deprecation warnings
- pass CLI state through typed/named context objects rather than globals
- design exception types around exit behavior and user guidance