WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 6c894eb

Browse files
authored
Stable (#3159)
2 parents f67abc6 + f4a1bd4 commit 6c894eb

File tree

10 files changed

+270
-172
lines changed

10 files changed

+270
-172
lines changed

CHANGES.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
.. currentmodule:: click
22

3+
Unreleased
4+
5+
- Fix handling of ``flag_value`` when ``is_flag=False`` to allow such options to be
6+
used without an explicit value. :issue:`3084`
7+
38
Version 8.3.1
49
--------------
510

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
Packaging Entry Points
2-
======================
1+
# Packaging Entry Points
2+
3+
```{eval-rst}
4+
.. currentmodule:: click
5+
```
36

47
It's recommended to write command line utilities as installable packages with
58
entry points instead of telling users to run ``python hello.py``.
@@ -14,74 +17,72 @@ function. These are known as "entry points". The installer knows how to create
1417
an executable regardless of the operating system, so it will work on Linux,
1518
Windows, MacOS, etc.
1619

17-
18-
Project Files
19-
-------------
20+
## Project Files
2021

2122
To install your app with an entry point, all you need is the script and a
2223
``pyproject.toml`` file. Here's an example project directory:
2324

24-
.. code-block:: text
25-
26-
hello-project/
27-
src/
28-
hello/
29-
__init__.py
30-
hello.py
31-
pyproject.toml
25+
```text
26+
hello-project/
27+
src/
28+
hello/
29+
__init__.py
30+
hello.py
31+
pyproject.toml
32+
```
3233

3334
Contents of ``hello.py``:
3435

36+
```{eval-rst}
3537
.. click:example::
36-
3738
import click
3839
3940
@click.command()
4041
def cli():
4142
"""Prints a greeting."""
4243
click.echo("Hello, World!")
44+
```
4345

4446
Contents of ``pyproject.toml``:
4547

46-
.. code-block:: toml
48+
```toml
49+
[project]
50+
name = "hello"
51+
version = "1.0.0"
52+
description = "Hello CLI"
53+
requires-python = ">=3.11"
54+
dependencies = [
55+
"click>=8.1",
56+
]
4757

48-
[project]
49-
name = "hello"
50-
version = "1.0.0"
51-
description = "Hello CLI"
52-
requires-python = ">=3.11"
53-
dependencies = [
54-
"click>=8.1",
55-
]
58+
[project.scripts]
59+
hello = "hello.hello:cli"
5660

57-
[project.scripts]
58-
hello = "hello.hello:cli"
59-
60-
[build-system]
61-
requires = ["flit_core<4"]
62-
build-backend = "flit_core.buildapi"
61+
[build-system]
62+
requires = ["flit_core<4"]
63+
build-backend = "flit_core.buildapi"
64+
```
6365

6466
The magic is in the ``project.scripts`` section. Each line identifies one executable
6567
script. The first part before the equals sign (``=``) is the name of the script that
6668
should be generated, the second part is the import path followed by a colon
6769
(``:``) with the function to call (the Click command).
6870

69-
70-
Installation
71-
------------
71+
## Installation
7272

7373
When your package is installed, the installer will create an executable script
7474
based on the configuration. During development, you can install in editable
7575
mode using the ``-e`` option. Remember to use a virtual environment!
7676

77-
.. code-block:: console
78-
79-
$ python -m venv .venv
80-
$ . .venv/bin/activate
81-
$ pip install -e .
77+
```console
78+
$ python -m venv .venv
79+
$ . .venv/bin/activate
80+
$ pip install -e .
81+
```
8282

8383
Afterwards, your command should be available:
8484

85-
.. click:run::
86-
87-
invoke(cli, prog_name="hello")
85+
```console
86+
$ hello
87+
Hello, World!
88+
```

docs/exceptions.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
(exception-handling-exit-codes)=
2+
3+
# Exception Handling and Exit Codes
4+
5+
```{eval-rst}
6+
.. currentmodule:: click
7+
```
8+
9+
Click internally uses exceptions to signal various error conditions that
10+
the user of the application might have caused. Primarily this is things
11+
like incorrect usage.
12+
13+
```{contents}
14+
:depth: 1
15+
:local:
16+
```
17+
18+
## Where are Errors Handled?
19+
20+
Click's main error handling is happening in {meth}`Command.main`. In
21+
there it handles all subclasses of {exc}`ClickException` as well as the
22+
standard {exc}`EOFError` and {exc}`KeyboardInterrupt` exceptions. The
23+
latter are internally translated into an {exc}`Abort`.
24+
25+
The logic applied is the following:
26+
27+
1. If an {exc}`EOFError` or {exc}`KeyboardInterrupt` happens, reraise it
28+
as {exc}`Abort`.
29+
2. If a {exc}`ClickException` is raised, invoke the
30+
{meth}`ClickException.show` method on it to display it and then exit
31+
the program with {attr}`ClickException.exit_code`.
32+
3. If an {exc}`Abort` exception is raised print the string ``Aborted!``
33+
to standard error and exit the program with exit code ``1``.
34+
4. If it goes through well, exit the program with exit code ``0``.
35+
36+
## What if I Don't Want That?
37+
38+
Generally you always have the option to invoke the {meth}`Command.invoke`
39+
method yourself. For instance if you have a {class}`Command` you can
40+
invoke it manually like this:
41+
42+
```python
43+
ctx = command.make_context("command-name", ["args", "go", "here"])
44+
with ctx:
45+
result = command.invoke(ctx)
46+
```
47+
48+
In this case exceptions will not be handled at all and bubbled up as you
49+
would expect.
50+
51+
Starting with Click 3.0 you can also use the {meth}`Command.main` method
52+
but disable the standalone mode which will do two things: disable
53+
exception handling and disable the implicit {func}`sys.exit` at the end.
54+
55+
So you can do something like this:
56+
57+
```python
58+
command.main(
59+
["command-name", "args", "go", "here"],
60+
standalone_mode=False,
61+
)
62+
```
63+
64+
## Which Exceptions Exist?
65+
66+
Click has two exception bases: {exc}`ClickException` which is raised for
67+
all exceptions that Click wants to signal to the user and {exc}`Abort`
68+
which is used to instruct Click to abort the execution.
69+
70+
A {exc}`ClickException` has a {meth}`ClickException.show` method which
71+
can render an error message to stderr or the given file object. If you
72+
want to use the exception yourself for doing something check the API docs
73+
about what else they provide.
74+
75+
The following common subclasses exist:
76+
77+
- {exc}`UsageError` to inform the user that something went wrong.
78+
- {exc}`BadParameter` to inform the user that something went wrong with
79+
a specific parameter. These are often handled internally in Click and
80+
augmented with extra information if possible. For instance if those
81+
are raised from a callback Click will automatically augment it with
82+
the parameter name if possible.
83+
- {exc}`FileError` this is an error that is raised by the
84+
{class}`FileType` if Click encounters issues opening the file.
85+
86+
(help-page-exit-codes)=
87+
88+
## Help Pages and Exit Codes
89+
90+
Triggering the a help page intentionally (by passing in ``--help``)
91+
returns exit code 0. If a help page is displayed due to incorrect user
92+
input, the program returns exit code 2. See {ref}`exit-codes` for more
93+
general information.
94+
95+
For clarity, here is an example.
96+
97+
```{eval-rst}
98+
.. click:example::
99+
100+
@click.group('printer_group')
101+
def printer_group():
102+
pass
103+
104+
@printer_group.command('printer')
105+
@click.option('--this')
106+
def printer(this):
107+
if this:
108+
click.echo(this)
109+
110+
.. click:run::
111+
invoke(printer_group, args=['--help'])
112+
113+
The above invocation returns exit code 0.
114+
115+
.. click:run::
116+
invoke(printer_group, args=[])
117+
```
118+
119+
The above invocation returns exit code 2 since the user invoked the command incorrectly. However, since this is such a common error when first using a command, Click invokes the help page for the user. To see that `printer-group` is an invalid invocation, turn `no_args_is_help` off.
120+
121+
```{eval-rst}
122+
.. click:example::
123+
124+
@click.group('printer_group', no_args_is_help=False)
125+
def printer_group():
126+
pass
127+
128+
@printer_group.command('printer')
129+
@click.option('--this')
130+
def printer(this):
131+
if this:
132+
click.echo(this)
133+
134+
.. click:run::
135+
invoke(printer_group, args=[])
136+
```

docs/exceptions.rst

Lines changed: 0 additions & 126 deletions
This file was deleted.

0 commit comments

Comments
 (0)