Compare commits

...

No commits in common. "debian/master" and "pristine-tar" have entirely different histories.

171 changed files with 12 additions and 24817 deletions

View file

@ -1,13 +0,0 @@
root = true
[*]
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
charset = utf-8
max_line_length = 88
[*.{yml,yaml,json,js,css,html}]
indent_size = 2

View file

@ -1,27 +0,0 @@
---
name: Bug report
about: Report a bug in Click (not other projects which depend on Click)
---
<!--
This issue tracker is a tool to address bugs in Click itself. Please use
Pallets Discord or Stack Overflow for questions about your own code.
Replace this comment with a clear outline of what the bug is.
-->
<!--
Describe how to replicate the bug.
Include a minimal reproducible example that demonstrates the bug.
Include the full traceback if there was an exception.
-->
<!--
Describe the expected behavior that should have happened but didn't.
-->
Environment:
- Python version:
- Click version:

View file

@ -1,11 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Security issue
url: security@palletsprojects.com
about: Do not report security issues publicly. Email our security contact.
- name: Questions
url: https://stackoverflow.com/questions/tagged/python-click?tab=Frequent
about: Search for and ask questions about your code on Stack Overflow.
- name: Questions and discussions
url: https://discord.gg/pallets
about: Discuss questions about your code on our Discord chat.

View file

@ -1,15 +0,0 @@
---
name: Feature request
about: Suggest a new feature for Click
---
<!--
Replace this comment with a description of what the feature should do.
Include details such as links relevant specs or previous discussions.
-->
<!--
Replace this comment with an example of the problem which this feature
would resolve. Is this problem solvable without changes to Click,
such as by subclassing or using an extension?
-->

View file

@ -1,9 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
day: "monday"
time: "16:00"
timezone: "UTC"

View file

@ -1,30 +0,0 @@
<!--
Before opening a PR, open a ticket describing the issue or feature the
PR will address. Follow the steps in CONTRIBUTING.rst.
Replace this comment with a description of the change. Describe how it
addresses the linked ticket.
-->
<!--
Link to relevant issues or previous PRs, one per line. Use "fixes" to
automatically close an issue.
-->
- fixes #<issue number>
<!--
Ensure each step in CONTRIBUTING.rst is complete by adding an "x" to
each box below.
If only docs were changed, these aren't relevant and can be removed.
-->
Checklist:
- [ ] Add tests that demonstrate the correct behavior of the change. Tests should fail without the change.
- [ ] Add or update relevant docs, in the docs folder and in code.
- [ ] Add an entry in `CHANGES.rst` summarizing the change and linking to the issue.
- [ ] Add `.. versionchanged::` entries in any relevant code docs.
- [ ] Run `pre-commit` hooks and fix any issues.
- [ ] Run `pytest` and `tox`, no tests failed.

View file

@ -1,15 +0,0 @@
name: 'Lock threads'
on:
schedule:
- cron: '0 0 * * *'
jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v3
with:
github-token: ${{ github.token }}
issue-inactive-days: 14
pr-inactive-days: 14

View file

@ -1,55 +0,0 @@
name: Tests
on:
push:
branches:
- main
- '*.x'
paths-ignore:
- 'docs/**'
- '*.md'
- '*.rst'
pull_request:
branches:
- main
- '*.x'
paths-ignore:
- 'docs/**'
- '*.md'
- '*.rst'
jobs:
tests:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- {name: Linux, python: '3.10', os: ubuntu-latest, tox: py310}
- {name: Windows, python: '3.10', os: windows-latest, tox: py310}
- {name: Mac, python: '3.10', os: macos-latest, tox: py310}
- {name: '3.11-dev', python: '3.11-dev', os: ubuntu-latest, tox: py311}
- {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39}
- {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38}
- {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37}
- {name: 'PyPy', python: 'pypy-3.7', os: ubuntu-latest, tox: pypy37}
- {name: Typing, python: '3.10', os: ubuntu-latest, tox: typing}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python }}
cache: 'pip'
cache-dependency-path: 'requirements/*.txt'
- name: update pip
run: |
pip install -U wheel
pip install -U setuptools
python -m pip install -U pip
- name: cache mypy
uses: actions/cache@v2
with:
path: ./.mypy_cache
key: mypy|${{ matrix.python }}|${{ hashFiles('setup.cfg') }}
if: matrix.tox == 'typing'
- run: pip install tox
- run: tox -e ${{ matrix.tox }}

16
.gitignore vendored
View file

@ -1,16 +0,0 @@
/.idea/
/.vscode/
.DS_Store/
/env/
/venv/
__pycache__/
*.pyc
*.egg-info/
/build/
/dist/
/.pytest_cache/
/.tox/
.coverage
.coverage.*
/htmlcov/
/docs/_build/

View file

@ -1,32 +0,0 @@
ci:
autoupdate_branch: "8.1.x"
autoupdate_schedule: monthly
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v2.32.0
hooks:
- id: pyupgrade
args: ["--py37-plus"]
- repo: https://github.com/asottile/reorder_python_imports
rev: v3.1.0
hooks:
- id: reorder-python-imports
args: ["--application-directories", "src"]
additional_dependencies: ["setuptools>60.9"]
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
hooks:
- id: flake8
additional_dependencies:
- flake8-bugbear
- flake8-implicit-str-concat
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
hooks:
- id: fix-byte-order-marker
- id: trailing-whitespace
- id: end-of-file-fixer

View file

@ -1,13 +0,0 @@
version: 2
build:
os: ubuntu-20.04
tools:
python: "3.10"
python:
install:
- requirements: requirements/docs.txt
- method: pip
path: .
sphinx:
builder: dirhtml
fail_on_warning: true

View file

@ -1,1044 +0,0 @@
.. currentmodule:: click
Version 8.1.3
-------------
Released 2022-04-28
- Use verbose form of ``typing.Callable`` for ``@command`` and
``@group``. :issue:`2255`
- Show error when attempting to create an option with
``multiple=True, is_flag=True``. Use ``count`` instead.
:issue:`2246`
Version 8.1.2
-------------
Released 2022-03-31
- Fix error message for readable path check that was mixed up with the
executable check. :pr:`2236`
- Restore parameter order for ``Path``, placing the ``executable``
parameter at the end. It is recommended to use keyword arguments
instead of positional arguments. :issue:`2235`
Version 8.1.1
-------------
Released 2022-03-30
- Fix an issue with decorator typing that caused type checking to
report that a command was not callable. :issue:`2227`
Version 8.1.0
-------------
Released 2022-03-28
- Drop support for Python 3.6. :pr:`2129`
- Remove previously deprecated code. :pr:`2130`
- ``Group.resultcallback`` is renamed to ``result_callback``.
- ``autocompletion`` parameter to ``Command`` is renamed to
``shell_complete``.
- ``get_terminal_size`` is removed, use
``shutil.get_terminal_size`` instead.
- ``get_os_args`` is removed, use ``sys.argv[1:]`` instead.
- Rely on :pep:`538` and :pep:`540` to handle selecting UTF-8 encoding
instead of ASCII. Click's locale encoding detection is removed.
:issue:`2198`
- Single options boolean flags with ``show_default=True`` only show
the default if it is ``True``. :issue:`1971`
- The ``command`` and ``group`` decorators can be applied with or
without parentheses. :issue:`1359`
- The ``Path`` type can check whether the target is executable.
:issue:`1961`
- ``Command.show_default`` overrides ``Context.show_default``, instead
of the other way around. :issue:`1963`
- Parameter decorators and ``@group`` handles ``cls=None`` the same as
not passing ``cls``. ``@option`` handles ``help=None`` the same as
not passing ``help``. :issue:`#1959`
- A flag option with ``required=True`` requires that the flag is
passed instead of choosing the implicit default value. :issue:`1978`
- Indentation in help text passed to ``Option`` and ``Command`` is
cleaned the same as using the ``@option`` and ``@command``
decorators does. A command's ``epilog`` and ``short_help`` are also
processed. :issue:`1985`
- Store unprocessed ``Command.help``, ``epilog`` and ``short_help``
strings. Processing is only done when formatting help text for
output. :issue:`2149`
- Allow empty str input for ``prompt()`` when
``confirmation_prompt=True`` and ``default=""``. :issue:`2157`
- Windows glob pattern expansion doesn't fail if a value is an invalid
pattern. :issue:`2195`
- It's possible to pass a list of ``params`` to ``@command``. Any
params defined with decorators are appended to the passed params.
:issue:`2131`.
- ``@command`` decorator is annotated as returning the correct type if
a ``cls`` argument is used. :issue:`2211`
- A ``Group`` with ``invoke_without_command=True`` and ``chain=False``
will invoke its result callback with the group function's return
value. :issue:`2124`
- ``to_info_dict`` will not fail if a ``ParamType`` doesn't define a
``name``. :issue:`2168`
- Shell completion prioritizes option values with option prefixes over
new options. :issue:`2040`
- Options that get an environment variable value using
``autoenvvar_prefix`` treat an empty value as ``None``, consistent
with a direct ``envvar``. :issue:`2146`
Version 8.0.4
-------------
Released 2022-02-18
- ``open_file`` recognizes ``Path("-")`` as a standard stream, the
same as the string ``"-"``. :issue:`2106`
- The ``option`` and ``argument`` decorators preserve the type
annotation of the decorated function. :pr:`2155`
- A callable default value can customize its help text by overriding
``__str__`` instead of always showing ``(dynamic)``. :issue:`2099`
- Fix a typo in the Bash completion script that affected file and
directory completion. If this script was generated by a previous
version, it should be regenerated. :issue:`2163`
- Fix typing for ``echo`` and ``secho`` file argument.
:issue:`2174, 2185`
Version 8.0.3
-------------
Released 2021-10-10
- Fix issue with ``Path(resolve_path=True)`` type creating invalid
paths. :issue:`2088`
- Importing ``readline`` does not cause the ``confirm()`` prompt to
disappear when pressing backspace. :issue:`2092`
- Any default values injected by ``invoke()`` are cast to the
corresponding parameter's type. :issue:`2089, 2090`
Version 8.0.2
-------------
Released 2021-10-08
- ``is_bool_flag`` is not set to ``True`` if ``is_flag`` is ``False``.
:issue:`1925`
- Bash version detection is locale independent. :issue:`1940`
- Empty ``default`` value is not shown for ``multiple=True``.
:issue:`1969`
- Fix shell completion for arguments that start with a forward slash
such as absolute file paths. :issue:`1929`
- ``Path`` type with ``resolve_path=True`` resolves relative symlinks
to be relative to the containing directory. :issue:`1921`
- Completion does not skip Python's resource cleanup when exiting,
avoiding some unexpected warning output. :issue:`1738, 2017`
- Fix type annotation for ``type`` argument in ``prompt`` function.
:issue:`2062`
- Fix overline and italic styles, which were incorrectly added when
adding underline. :pr:`2058`
- An option with ``count=True`` will not show "[x>=0]" in help text.
:issue:`2072`
- Default values are not cast to the parameter type twice during
processing. :issue:`2085`
- Options with ``multiple`` and ``flag_value`` use the flag value
instead of leaving an internal placeholder. :issue:`2001`
Version 8.0.1
-------------
Released 2021-05-19
- Mark top-level names as exported so type checking understand imports
in user projects. :issue:`1879`
- Annotate ``Context.obj`` as ``Any`` so type checking allows all
operations on the arbitrary object. :issue:`1885`
- Fix some types that weren't available in Python 3.6.0. :issue:`1882`
- Fix type checking for iterating over ``ProgressBar`` object.
:issue:`1892`
- The ``importlib_metadata`` backport package is installed on Python <
3.8. :issue:`1889`
- Arguments with ``nargs=-1`` only use env var value if no command
line values are given. :issue:`1903`
- Flag options guess their type from ``flag_value`` if given, like
regular options do from ``default``. :issue:`1886`
- Added documentation that custom parameter types may be passed
already valid values in addition to strings. :issue:`1898`
- Resolving commands returns the name that was given, not
``command.name``, fixing an unintended change to help text and
``default_map`` lookups. When using patterns like ``AliasedGroup``,
override ``resolve_command`` to change the name that is returned if
needed. :issue:`1895`
- If a default value is invalid, it does not prevent showing help
text. :issue:`1889`
- Pass ``windows_expand_args=False`` when calling the main command to
disable pattern expansion on Windows. There is no way to escape
patterns in CMD, so if the program needs to pass them on as-is then
expansion must be disabled. :issue:`1901`
Version 8.0.0
-------------
Released 2021-05-11
- Drop support for Python 2 and 3.5.
- Colorama is always installed on Windows in order to provide style
and color support. :pr:`1784`
- Adds a repr to Command, showing the command name for friendlier
debugging. :issue:`1267`, :pr:`1295`
- Add support for distinguishing the source of a command line
parameter. :issue:`1264`, :pr:`1329`
- Add an optional parameter to ``ProgressBar.update`` to set the
``current_item``. :issue:`1226`, :pr:`1332`
- ``version_option`` uses ``importlib.metadata`` (or the
``importlib_metadata`` backport) instead of ``pkg_resources``. The
version is detected based on the package name, not the entry point
name. The Python package name must match the installed package
name, or be passed with ``package_name=``. :issue:`1582`
- If validation fails for a prompt with ``hide_input=True``, the value
is not shown in the error message. :issue:`1460`
- An ``IntRange`` or ``FloatRange`` option shows the accepted range in
its help text. :issue:`1525`, :pr:`1303`
- ``IntRange`` and ``FloatRange`` bounds can be open (``<``) instead
of closed (``<=``) by setting ``min_open`` and ``max_open``. Error
messages have changed to reflect this. :issue:`1100`
- An option defined with duplicate flag names (``"--foo/--foo"``)
raises a ``ValueError``. :issue:`1465`
- ``echo()`` will not fail when using pytest's ``capsys`` fixture on
Windows. :issue:`1590`
- Resolving commands returns the canonical command name instead of the
matched name. This makes behavior such as help text and
``Context.invoked_subcommand`` consistent when using patterns like
``AliasedGroup``. :issue:`1422`
- The ``BOOL`` type accepts the values "on" and "off". :issue:`1629`
- A ``Group`` with ``invoke_without_command=True`` will always invoke
its result callback. :issue:`1178`
- ``nargs == -1`` and ``nargs > 1`` is parsed and validated for
values from environment variables and defaults. :issue:`729`
- Detect the program name when executing a module or package with
``python -m name``. :issue:`1603`
- Include required parent arguments in help synopsis of subcommands.
:issue:`1475`
- Help for boolean flags with ``show_default=True`` shows the flag
name instead of ``True`` or ``False``. :issue:`1538`
- Non-string objects passed to ``style()`` and ``secho()`` will be
converted to string. :pr:`1146`
- ``edit(require_save=True)`` will detect saves for editors that exit
very fast on filesystems with 1 second resolution. :pr:`1050`
- New class attributes make it easier to use custom core objects
throughout an entire application. :pr:`938`
- ``Command.context_class`` controls the context created when
running the command.
- ``Context.invoke`` creates new contexts of the same type, so a
custom type will persist to invoked subcommands.
- ``Context.formatter_class`` controls the formatter used to
generate help and usage.
- ``Group.command_class`` changes the default type for
subcommands with ``@group.command()``.
- ``Group.group_class`` changes the default type for subgroups
with ``@group.group()``. Setting it to ``type`` will create
subgroups of the same type as the group itself.
- Core objects use ``super()`` consistently for better support of
subclassing.
- Use ``Context.with_resource()`` to manage resources that would
normally be used in a ``with`` statement, allowing them to be used
across subcommands and callbacks, then cleaned up when the context
ends. :pr:`1191`
- The result object returned by the test runner's ``invoke()`` method
has a ``return_value`` attribute with the value returned by the
invoked command. :pr:`1312`
- Required arguments with the ``Choice`` type show the choices in
curly braces to indicate that one is required (``{a|b|c}``).
:issue:`1272`
- If only a name is passed to ``option()``, Click suggests renaming it
to ``--name``. :pr:`1355`
- A context's ``show_default`` parameter defaults to the value from
the parent context. :issue:`1565`
- ``click.style()`` can output 256 and RGB color codes. Most modern
terminals support these codes. :pr:`1429`
- When using ``CliRunner.invoke()``, the replaced ``stdin`` file has
``name`` and ``mode`` attributes. This lets ``File`` options with
the ``-`` value match non-testing behavior. :issue:`1064`
- When creating a ``Group``, allow passing a list of commands instead
of a dict. :issue:`1339`
- When a long option name isn't valid, use ``difflib`` to make better
suggestions for possible corrections. :issue:`1446`
- Core objects have a ``to_info_dict()`` method. This gathers
information about the object's structure that could be useful for a
tool generating user-facing documentation. To get the structure of
an entire CLI, use ``Context(cli).to_info_dict()``. :issue:`461`
- Redesign the shell completion system. :issue:`1484`, :pr:`1622`
- Support Bash >= 4.4, Zsh, and Fish, with the ability for
extensions to add support for other shells.
- Allow commands, groups, parameters, and types to override their
completions suggestions.
- Groups complete the names commands were registered with, which
can differ from the name they were created with.
- The ``autocompletion`` parameter for options and arguments is
renamed to ``shell_complete``. The function must take
``ctx, param, incomplete``, must do matching rather than return
all values, and must return a list of strings or a list of
``CompletionItem``. The old name and behavior is deprecated and
will be removed in 8.1.
- The env var values used to start completion have changed order.
The shell now comes first, such as ``{shell}_source`` rather
than ``source_{shell}``, and is always required.
- Completion correctly parses command line strings with incomplete
quoting or escape sequences. :issue:`1708`
- Extra context settings (``obj=...``, etc.) are passed on to the
completion system. :issue:`942`
- Include ``--help`` option in completion. :pr:`1504`
- ``ParameterSource`` is an ``enum.Enum`` subclass. :issue:`1530`
- Boolean and UUID types strip surrounding space before converting.
:issue:`1605`
- Adjusted error message from parameter type validation to be more
consistent. Quotes are used to distinguish the invalid value.
:issue:`1605`
- The default value for a parameter with ``nargs`` > 1 and
``multiple=True`` must be a list of tuples. :issue:`1649`
- When getting the value for a parameter, the default is tried in the
same section as other sources to ensure consistent processing.
:issue:`1649`
- All parameter types accept a value that is already the correct type.
:issue:`1649`
- For shell completion, an argument is considered incomplete if its
value did not come from the command line args. :issue:`1649`
- Added ``ParameterSource.PROMPT`` to track parameter values that were
prompted for. :issue:`1649`
- Options with ``nargs`` > 1 no longer raise an error if a default is
not given. Parameters with ``nargs`` > 1 default to ``None``, and
parameters with ``multiple=True`` or ``nargs=-1`` default to an
empty tuple. :issue:`472`
- Handle empty env vars as though the option were not passed. This
extends the change introduced in 7.1 to be consistent in more cases.
:issue:`1285`
- ``Parameter.get_default()`` checks ``Context.default_map`` to
handle overrides consistently in help text, ``invoke()``, and
prompts. :issue:`1548`
- Add ``prompt_required`` param to ``Option``. When set to ``False``,
the user will only be prompted for an input if no value was passed.
:issue:`736`
- Providing the value to an option can be made optional through
``is_flag=False``, and the value can instead be prompted for or
passed in as a default value.
:issue:`549, 736, 764, 921, 1015, 1618`
- Fix formatting when ``Command.options_metavar`` is empty. :pr:`1551`
- Revert adding space between option help text that wraps.
:issue:`1831`
- The default value passed to ``prompt`` will be cast to the correct
type like an input value would be. :pr:`1517`
- Automatically generated short help messages will stop at the first
ending of a phrase or double linebreak. :issue:`1082`
- Skip progress bar render steps for efficiency with very fast
iterators by setting ``update_min_steps``. :issue:`676`
- Respect ``case_sensitive=False`` when doing shell completion for
``Choice`` :issue:`1692`
- Use ``mkstemp()`` instead of ``mktemp()`` in pager implementation.
:issue:`1752`
- If ``Option.show_default`` is a string, it is displayed even if
``default`` is ``None``. :issue:`1732`
- ``click.get_terminal_size()`` is deprecated and will be removed in
8.1. Use :func:`shutil.get_terminal_size` instead. :issue:`1736`
- Control the location of the temporary directory created by
``CLIRunner.isolated_filesystem`` by passing ``temp_dir``. A custom
directory will not be removed automatically. :issue:`395`
- ``click.confirm()`` will prompt until input is given if called with
``default=None``. :issue:`1381`
- Option prompts validate the value with the option's callback in
addition to its type. :issue:`457`
- ``confirmation_prompt`` can be set to a custom string. :issue:`723`
- Allow styled output in Jupyter on Windows. :issue:`1271`
- ``style()`` supports the ``strikethrough``, ``italic``, and
``overline`` styles. :issue:`805, 1821`
- Multiline marker is removed from short help text. :issue:`1597`
- Restore progress bar behavior of echoing only the label if the file
is not a TTY. :issue:`1138`
- Progress bar output is shown even if execution time is less than 0.5
seconds. :issue:`1648`
- Progress bar ``item_show_func`` shows the current item, not the
previous item. :issue:`1353`
- The ``Path`` param type can be passed ``path_type=pathlib.Path`` to
return a path object instead of a string. :issue:`405`
- ``TypeError`` is raised when parameter with ``multiple=True`` or
``nargs > 1`` has non-iterable default. :issue:`1749`
- Add a ``pass_meta_key`` decorator for passing a key from
``Context.meta``. This is useful for extensions using ``meta`` to
store information. :issue:`1739`
- ``Path`` ``resolve_path`` resolves symlinks on Windows Python < 3.8.
:issue:`1813`
- Command deprecation notice appears at the start of the help text, as
well as in the short help. The notice is not in all caps.
:issue:`1791`
- When taking arguments from ``sys.argv`` on Windows, glob patterns,
user dir, and env vars are expanded. :issue:`1096`
- Marked messages shown by the CLI with ``gettext()`` to allow
applications to translate Click's built-in strings. :issue:`303`
- Writing invalid characters to ``stderr`` when using the test runner
does not raise a ``UnicodeEncodeError``. :issue:`848`
- Fix an issue where ``readline`` would clear the entire ``prompt()``
line instead of only the input when pressing backspace. :issue:`665`
- Add all kwargs passed to ``Context.invoke()`` to ``ctx.params``.
Fixes an inconsistency when nesting ``Context.forward()`` calls.
:issue:`1568`
- The ``MultiCommand.resultcallback`` decorator is renamed to
``result_callback``. The old name is deprecated. :issue:`1160`
- Fix issues with ``CliRunner`` output when using ``echo_stdin=True``.
:issue:`1101`
- Fix a bug of ``click.utils.make_default_short_help`` for which the
returned string could be as long as ``max_width + 3``. :issue:`1849`
- When defining a parameter, ``default`` is validated with
``multiple`` and ``nargs``. More validation is done for values being
processed as well. :issue:`1806`
- ``HelpFormatter.write_text`` uses the full line width when wrapping
text. :issue:`1871`
Version 7.1.2
-------------
Released 2020-04-27
- Revert applying shell quoting to commands for ``echo_with_pager``
and ``edit``. This was intended to allows spaces in commands, but
caused issues if the string was actually a command and arguments, or
on Windows. Instead, the string must be quoted manually as it should
appear on the command line. :issue:`1514`
Version 7.1.1
-------------
Released 2020-03-09
- Fix ``ClickException`` output going to stdout instead of stderr.
:issue:`1495`
Version 7.1
-----------
Released 2020-03-09
- Fix PyPI package name, "click" is lowercase again.
- Fix link in ``unicode_literals`` error message. :pr:`1151`
- Add support for colored output on UNIX Jupyter notebooks.
:issue:`1185`
- Operations that strip ANSI controls will strip the cursor hide/show
sequences. :issue:`1216`
- Remove unused compat shim for ``bytes``. :pr:`1195`
- Expand testing around termui, especially getchar on Windows.
:issue:`1116`
- Fix output on Windows Python 2.7 built with MSVC 14. :pr:`1342`
- Fix ``OSError`` when running in MSYS2. :issue:`1338`
- Fix ``OSError`` when redirecting to ``NUL`` stream on Windows.
:issue:`1065`
- Fix memory leak when parsing Unicode arguments on Windows.
:issue:`1136`
- Fix error in new AppEngine environments. :issue:`1462`
- Always return one of the passed choices for ``click.Choice``
:issue:`1277`, :pr:`1318`
- Add ``no_args_is_help`` option to ``click.Command``, defaults to
False :pr:`1167`
- Add ``show_default`` parameter to ``Context`` to enable showing
defaults globally. :issue:`1018`
- Handle ``env MYPATH=''`` as though the option were not passed.
:issue:`1196`
- It is once again possible to call ``next(bar)`` on an active
progress bar instance. :issue:`1125`
- ``open_file`` with ``atomic=True`` retains permissions of existing
files and respects the current umask for new files. :issue:`1376`
- When using the test ``CliRunner`` with ``mix_stderr=False``, if
``result.stderr`` is empty it will not raise a ``ValueError``.
:issue:`1193`
- Remove the unused ``mix_stderr`` parameter from
``CliRunner.invoke``. :issue:`1435`
- Fix ``TypeError`` raised when using bool flags and specifying
``type=bool``. :issue:`1287`
- Newlines in option help text are replaced with spaces before
re-wrapping to avoid uneven line breaks. :issue:`834`
- ``MissingParameter`` exceptions are printable in the Python
interpreter. :issue:`1139`
- Fix how default values for file-type options are shown during
prompts. :issue:`914`
- Fix environment variable automatic generation for commands
containing ``-``. :issue:`1253`
- Option help text replaces newlines with spaces when rewrapping, but
preserves paragraph breaks, fixing multiline formatting.
:issue:`834, 1066, 1397`
- Option help text that is wrapped adds an extra newline at the end to
distinguish it from the next option. :issue:`1075`
- Consider ``sensible-editor`` when determining the editor to use for
``click.edit()``. :pr:`1469`
- Arguments to system calls such as the executable path passed to
``click.edit`` can contains spaces. :pr:`1470`
- Add ZSH completion autoloading and error handling. :issue:`1348`
- Add a repr to ``Command``, ``Group``, ``Option``, and ``Argument``,
showing the name for friendlier debugging. :issue:`1267`
- Completion doesn't consider option names if a value starts with
``-`` after the ``--`` separator. :issue:`1247`
- ZSH completion escapes special characters in values. :pr:`1418`
- Add completion support for Fish shell. :pr:`1423`
- Decoding bytes option values falls back to UTF-8 in more cases.
:pr:`1468`
- Make the warning about old 2-arg parameter callbacks a deprecation
warning, to be removed in 8.0. This has been a warning since Click
2.0. :pr:`1492`
- Adjust error messages to standardize the types of quotes used so
they match error messages from Python.
Version 7.0
-----------
Released 2018-09-25
- Drop support for Python 2.6 and 3.3. :pr:`967, 976`
- Wrap ``click.Choice``'s missing message. :issue:`202`, :pr:`1000`
- Add native ZSH autocompletion support. :issue:`323`, :pr:`865`
- Document that ANSI color info isn't parsed from bytearrays in Python
2. :issue:`334`
- Document byte-stripping behavior of ``CliRunner``. :issue:`334`,
:pr:`1010`
- Usage errors now hint at the ``--help`` option. :issue:`393`,
:pr:`557`
- Implement streaming pager. :issue:`409`, :pr:`889`
- Extract bar formatting to its own method. :pr:`414`
- Add ``DateTime`` type for converting input in given date time
formats. :pr:`423`
- ``secho``'s first argument can now be ``None``, like in ``echo``.
:pr:`424`
- Fixes a ``ZeroDivisionError`` in ``ProgressBar.make_step``, when the
arg passed to the first call of ``ProgressBar.update`` is 0.
:issue:`447`, :pr:`1012`
- Show progressbar only if total execution time is visible. :pr:`487`
- Added the ability to hide commands and options from help. :pr:`500`
- Document that options can be ``required=True``. :issue:`514`,
:pr:`1022`
- Non-standalone calls to ``Context.exit`` return the exit code,
rather than calling ``sys.exit``. :issue:`667`, :pr:`533, 1098`
- ``click.getchar()`` returns Unicode in Python 3 on Windows,
consistent with other platforms. :issue:`537, 821, 822, 1088`,
:pr:`1108`
- Added ``FloatRange`` type. :pr:`538, 553`
- Added support for bash completion of ``type=click.Choice`` for
``Options`` and ``Arguments``. :issue:`535`, :pr:`681`
- Only allow one positional arg for ``Argument`` parameter
declaration. :issue:`568, 574`, :pr:`1014`
- Add ``case_sensitive=False`` as an option to Choice. :issue:`569`
- ``click.getchar()`` correctly raises ``KeyboardInterrupt`` on "^C"
and ``EOFError`` on "^D" on Linux. :issue:`583`, :pr:`1115`
- Fix encoding issue with ``click.getchar(echo=True)`` on Linux.
:pr:`1115`
- ``param_hint`` in errors now derived from param itself.
:issue:`598, 704`, :pr:`709`
- Add a test that ensures that when an argument is formatted into a
usage error, its metavar is used, not its name. :pr:`612`
- Allow setting ``prog_name`` as extra in ``CliRunner.invoke``.
:issue:`616`, :pr:`999`
- Help text taken from docstrings truncates at the ``\f`` form feed
character, useful for hiding Sphinx-style parameter documentation.
:pr:`629, 1091`
- ``launch`` now works properly under Cygwin. :pr:`650`
- Update progress after iteration. :issue:`651`, :pr:`706`
- ``CliRunner.invoke`` now may receive ``args`` as a string
representing a Unix shell command. :pr:`664`
- Make ``Argument.make_metavar()`` default to type metavar. :pr:`675`
- Add documentation for ``ignore_unknown_options``. :pr:`684`
- Add bright colors support for ``click.style`` and fix the reset
option for parameters ``fg`` and ``bg``. :issue:`703`, :pr:`809`
- Add ``show_envvar`` for showing environment variables in help.
:pr:`710`
- Avoid ``BrokenPipeError`` during interpreter shutdown when stdout or
stderr is a closed pipe. :issue:`712`, :pr:`1106`
- Document customizing option names. :issue:`725`, :pr:`1016`
- Disable ``sys._getframes()`` on Python interpreters that don't
support it. :pr:`728`
- Fix bug in test runner when calling ``sys.exit`` with ``None``.
:pr:`739`
- Clarify documentation on command line options. :issue:`741`,
:pr:`1003`
- Fix crash on Windows console. :issue:`744`
- Fix bug that caused bash completion to give improper completions on
chained commands. :issue:`754`, :pr:`774`
- Added support for dynamic bash completion from a user-supplied
callback. :pr:`755`
- Added support for bash completions containing spaces. :pr:`773`
- Allow autocompletion function to determine whether or not to return
completions that start with the incomplete argument. :issue:`790`,
:pr:`806`
- Fix option naming routine to match documentation and be
deterministic. :issue:`793`, :pr:`794`
- Fix path validation bug. :issue:`795`, :pr:`1020`
- Add test and documentation for ``Option`` naming: functionality.
:pr:`799`
- Update doc to match arg name for ``path_type``. :pr:`801`
- Raw strings added so correct escaping occurs. :pr:`807`
- Fix 16k character limit of ``click.echo`` on Windows. :issue:`816`,
:pr:`819`
- Overcome 64k character limit when writing to binary stream on
Windows 7. :issue:`825`, :pr:`830`
- Add bool conversion for "t" and "f". :pr:`842`
- ``NoSuchOption`` errors take ``ctx`` so that ``--help`` hint gets
printed in error output. :pr:`860`
- Fixed the behavior of Click error messages with regards to Unicode
on 2.x and 3.x. Message is now always Unicode and the str and
Unicode special methods work as you expect on that platform.
:issue:`862`
- Progress bar now uses stderr by default. :pr:`863`
- Add support for auto-completion documentation. :issue:`866`,
:pr:`869`
- Allow ``CliRunner`` to separate stdout and stderr. :pr:`868`
- Fix variable precedence. :issue:`873`, :pr:`874`
- Fix invalid escape sequences. :pr:`877`
- Fix ``ResourceWarning`` that occurs during some tests. :pr:`878`
- When detecting a misconfigured locale, don't fail if the ``locale``
command fails. :pr:`880`
- Add ``case_sensitive=False`` as an option to ``Choice`` types.
:pr:`887`
- Force stdout/stderr writable. This works around issues with badly
patched standard streams like those from Jupyter. :pr:`918`
- Fix completion of subcommand options after last argument
:issue:`919`, :pr:`930`
- ``_AtomicFile`` now uses the ``realpath`` of the original filename
so that changing the working directory does not affect it. :pr:`920`
- Fix incorrect completions when defaults are present :issue:`925`,
:pr:`930`
- Add copy option attrs so that custom classes can be re-used.
:issue:`926`, :pr:`994`
- "x" and "a" file modes now use stdout when file is ``"-"``.
:pr:`929`
- Fix missing comma in ``__all__`` list. :pr:`935`
- Clarify how parameters are named. :issue:`949`, :pr:`1009`
- Stdout is now automatically set to non blocking. :pr:`954`
- Do not set options twice. :pr:`962`
- Move ``fcntl`` import. :pr:`965`
- Fix Google App Engine ``ImportError``. :pr:`995`
- Better handling of help text for dynamic default option values.
:pr:`996`
- Fix ``get_winter_size()`` so it correctly returns ``(0,0)``.
:pr:`997`
- Add test case checking for custom param type. :pr:`1001`
- Allow short width to address cmd formatting. :pr:`1002`
- Add details about Python version support. :pr:`1004`
- Added deprecation flag to commands. :pr:`1005`
- Fixed issues where ``fd`` was undefined. :pr:`1007`
- Fix formatting for short help. :pr:`1008`
- Document how ``auto_envvar_prefix`` works with command groups.
:pr:`1011`
- Don't add newlines by default for progress bars. :pr:`1013`
- Use Python sorting order for ZSH completions. :issue:`1047`,
:pr:`1059`
- Document that parameter names are converted to lowercase by default.
:pr:`1055`
- Subcommands that are named by the function now automatically have
the underscore replaced with a dash. If you register a function
named ``my_command`` it becomes ``my-command`` in the command line
interface.
- Hide hidden commands and options from completion. :issue:`1058`,
:pr:`1061`
- Fix absolute import blocking Click from being vendored into a
project on Windows. :issue:`1068`, :pr:`1069`
- Fix issue where a lowercase ``auto_envvar_prefix`` would not be
converted to uppercase. :pr:`1105`
Version 6.7
-----------
Released 2017-01-06
- Make ``click.progressbar`` work with ``codecs.open`` files.
:pr:`637`
- Fix bug in bash completion with nested subcommands. :pr:`639`
- Fix test runner not saving caller env correctly. :pr:`644`
- Fix handling of SIGPIPE. :pr:`62`
- Deal with broken Windows environments such as Google App Engine's.
:issue:`711`
Version 6.6
-----------
Released 2016-04-04
- Fix bug in ``click.Path`` where it would crash when passed a ``-``.
:issue:`551`
Version 6.4
-----------
Released 2016-03-24
- Fix bug in bash completion where click would discard one or more
trailing arguments. :issue:`471`
Version 6.3
-----------
Released 2016-02-22
- Fix argument checks for interpreter invoke with ``-m`` and ``-c`` on
Windows.
- Fixed a bug that cased locale detection to error out on Python 3.
Version 6.2
-----------
Released 2015-11-27
- Correct fix for hidden progress bars.
Version 6.1
-----------
Released 2015-11-27
- Resolved an issue with invisible progress bars no longer rendering.
- Disable chain commands with subcommands as they were inherently
broken.
- Fix ``MissingParameter`` not working without parameters passed.
Version 6.0
-----------
Released 2015-11-24, codename "pow pow"
- Optimized the progressbar rendering to not render when it did not
actually change.
- Explicitly disallow ``nargs=-1`` with a set default.
- The context is now closed before it's popped from the stack.
- Added support for short aliases for the false flag on toggles.
- Click will now attempt to aid you with debugging locale errors
better by listing with the help of the OS what locales are
available.
- Click used to return byte strings on Python 2 in some unit-testing
situations. This has been fixed to correctly return unicode strings
now.
- For Windows users on Python 2, Click will now handle Unicode more
correctly handle Unicode coming in from the system. This also has
the disappointing side effect that filenames will now be always
unicode by default in the ``Path`` type which means that this can
introduce small bugs for code not aware of this.
- Added a ``type`` parameter to ``Path`` to force a specific string
type on the value.
- For users running Python on Windows the ``echo`` and ``prompt``
functions now work with full unicode functionality in the Python
windows console by emulating an output stream. This also applies to
getting the virtual output and input streams via
``click.get_text_stream(...)``.
- Unittests now always force a certain virtual terminal width.
- Added support for allowing dashes to indicate standard streams to
the ``Path`` type.
- Multi commands in chain mode no longer propagate arguments left over
from parsing to the callbacks. It's also now disallowed through an
exception when optional arguments are attached to multi commands if
chain mode is enabled.
- Relaxed restriction that disallowed chained commands to have other
chained commands as child commands.
- Arguments with positive nargs can now have defaults implemented.
Previously this configuration would often result in slightly
unexpected values be returned.
Version 5.1
-----------
Released 2015-08-17
- Fix a bug in ``pass_obj`` that would accidentally pass the context
too.
Version 5.0
-----------
Released 2015-08-16, codename "tok tok"
- Removed various deprecated functionality.
- Atomic files now only accept the ``w`` mode.
- Change the usage part of help output for very long commands to wrap
their arguments onto the next line, indented by 4 spaces.
- Fix a bug where return code and error messages were incorrect when
using ``CliRunner``.
- Added ``get_current_context``.
- Added a ``meta`` dictionary to the context which is shared across
the linked list of contexts to allow click utilities to place state
there.
- Introduced ``Context.scope``.
- The ``echo`` function is now threadsafe: It calls the ``write``
method of the underlying object only once.
- ``prompt(hide_input=True)`` now prints a newline on ``^C``.
- Click will now warn if users are using ``unicode_literals``.
- Click will now ignore the ``PAGER`` environment variable if it is
empty or contains only whitespace.
- The ``click-contrib`` GitHub organization was created.
Version 4.1
-----------
Released 2015-07-14
- Fix a bug where error messages would include a trailing ``None``
string.
- Fix a bug where Click would crash on docstrings with trailing
newlines.
- Support streams with encoding set to ``None`` on Python 3 by barfing
with a better error.
- Handle ^C in less-pager properly.
- Handle return value of ``None`` from ``sys.getfilesystemencoding``
- Fix crash when writing to unicode files with ``click.echo``.
- Fix type inference with multiple options.
Version 4.0
-----------
Released 2015-03-31, codename "zoom zoom"
- Added ``color`` parameters to lots of interfaces that directly or
indirectly call into echoing. This previously was always
autodetection (with the exception of the ``echo_via_pager``
function). Now you can forcefully enable or disable it, overriding
the auto detection of Click.
- Added an ``UNPROCESSED`` type which does not perform any type
changes which simplifies text handling on 2.x / 3.x in some special
advanced usecases.
- Added ``NoSuchOption`` and ``BadOptionUsage`` exceptions for more
generic handling of errors.
- Added support for handling of unprocessed options which can be
useful in situations where arguments are forwarded to underlying
tools.
- Added ``max_content_width`` parameter to the context which can be
used to change the maximum width of help output. By default Click
will not format content for more than 80 characters width.
- Added support for writing prompts to stderr.
- Fix a bug when showing the default for multiple arguments.
- Added support for custom subclasses to ``option`` and ``argument``.
- Fix bug in ``clear()`` on Windows when colorama is installed.
- Reject ``nargs=-1`` for options properly. Options cannot be
variadic.
- Fixed an issue with bash completion not working properly for
commands with non ASCII characters or dashes.
- Added a way to manually update the progressbar.
- Changed the formatting of missing arguments. Previously the internal
argument name was shown in error messages, now the metavar is shown
if passed. In case an automated metavar is selected, it's stripped
of extra formatting first.
Version 3.3
-----------
Released 2014-09-08
- Fixed an issue with error reporting on Python 3 for invalid
forwarding of commands.
Version 3.2
-----------
Released 2014-08-22
- Added missing ``err`` parameter forwarding to the ``secho``
function.
- Fixed default parameters not being handled properly by the context
invoke method. This is a backwards incompatible change if the
function was used improperly. See :ref:`upgrade-to-3.2` for more
information.
- Removed the ``invoked_subcommands`` attribute largely. It is not
possible to provide it to work error free due to how the parsing
works so this API has been deprecated. See :ref:`upgrade-to-3.2` for
more information.
- Restored the functionality of ``invoked_subcommand`` which was
broken as a regression in 3.1.
Version 3.1
-----------
Released 2014-08-13
- Fixed a regression that caused contexts of subcommands to be created
before the parent command was invoked which was a regression from
earlier Click versions.
Version 3.0
-----------
Released 2014-08-12, codename "clonk clonk"
- Formatter now no longer attempts to accommodate for terminals
smaller than 50 characters. If that happens it just assumes a
minimal width.
- Added a way to not swallow exceptions in the test system.
- Added better support for colors with pagers and ways to override the
autodetection.
- The CLI runner's result object now has a traceback attached.
- Improved automatic short help detection to work better with dots
that do not terminate sentences.
- When defining options without actual valid option strings now,
Click will give an error message instead of silently passing. This
should catch situations where users wanted to created arguments
instead of options.
- Restructured Click internally to support vendoring.
- Added support for multi command chaining.
- Added support for defaults on options with ``multiple`` and options
and arguments with ``nargs != 1``.
- Label passed to ``progressbar`` is no longer rendered with
whitespace stripped.
- Added a way to disable the standalone mode of the ``main`` method on
a Click command to be able to handle errors better.
- Added support for returning values from command callbacks.
- Added simplifications for printing to stderr from ``echo``.
- Added result callbacks for groups.
- Entering a context multiple times defers the cleanup until the last
exit occurs.
- Added ``open_file``.
Version 2.6
-----------
Released 2014-08-11
- Fixed an issue where the wrapped streams on Python 3 would be
reporting incorrect values for seekable.
Version 2.5
-----------
Released 2014-07-28
- Fixed a bug with text wrapping on Python 3.
Version 2.4
-----------
Released 2014-07-04
- Corrected a bug in the change of the help option in 2.3.
Version 2.3
-----------
Released 2014-07-03
- Fixed an incorrectly formatted help record for count options.
- Add support for ansi code stripping on Windows if colorama is not
available.
- Restored the Click 1.0 handling of the help parameter for certain
edge cases.
Version 2.2
-----------
Released 2014-06-26
- Fixed tty detection on PyPy.
- Fixed an issue that progress bars were not rendered when the context
manager was entered.
Version 2.1
-----------
Released 2014-06-14
- Fixed the :func:`launch` function on windows.
- Improved the colorama support on windows to try hard to not screw up
the console if the application is interrupted.
- Fixed windows terminals incorrectly being reported to be 80
characters wide instead of 79
- Use colorama win32 bindings if available to get the correct
dimensions of a windows terminal.
- Fixed an issue with custom function types on Python 3.
- Fixed an issue with unknown options being incorrectly reported in
error messages.
Version 2.0
-----------
Released 2014-06-06, codename "tap tap tap"
- Added support for opening stdin/stdout on Windows in binary mode
correctly.
- Added support for atomic writes to files by going through a
temporary file.
- Introduced :exc:`BadParameter` which can be used to easily perform
custom validation with the same error messages as in the type
system.
- Added :func:`progressbar`; a function to show progress bars.
- Added :func:`get_app_dir`; a function to calculate the home folder
for configs.
- Added transparent handling for ANSI codes into the :func:`echo`
function through ``colorama``.
- Added :func:`clear` function.
- Breaking change: parameter callbacks now get the parameter object
passed as second argument. There is legacy support for old callbacks
which will warn but still execute the script.
- Added :func:`style`, :func:`unstyle` and :func:`secho` for ANSI
styles.
- Added an :func:`edit` function that invokes the default editor.
- Added an :func:`launch` function that launches browsers and
applications.
- Nargs of -1 for arguments can now be forced to be a single item
through the required flag. It defaults to not required.
- Setting a default for arguments now implicitly makes it non
required.
- Changed "yN" / "Yn" to "y/N" and "Y/n" in confirmation prompts.
- Added basic support for bash completion.
- Added :func:`getchar` to fetch a single character from the terminal.
- Errors now go to stderr as intended.
- Fixed various issues with more exotic parameter formats like
DOS/Windows style arguments.
- Added :func:`pause` which works similar to the Windows ``pause`` cmd
built-in but becomes an automatic noop if the application is not run
through a terminal.
- Added a bit of extra information about missing choice parameters.
- Changed how the help function is implemented to allow global
overriding of the help option.
- Added support for token normalization to implement case insensitive
handling.
- Added support for providing defaults for context settings.
Version 1.1
-----------
Released 2014-05-23
- Fixed a bug that caused text files in Python 2 to not accept native
strings.
Version 1.0
-----------
Released 2014-05-21
- Initial release.

View file

@ -1,76 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at report@palletsprojects.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View file

@ -1,222 +0,0 @@
How to contribute to Click
==========================
Thank you for considering contributing to Click!
Support questions
-----------------
Please don't use the issue tracker for this. The issue tracker is a tool
to address bugs and feature requests in Click itself. Use one of the
following resources for questions about using Click or issues with your
own code:
- The ``#get-help`` channel on our Discord chat:
https://discord.gg/pallets
- The mailing list flask@python.org for long term discussion or larger
issues.
- Ask on `Stack Overflow`_. Search with Google first using:
``site:stackoverflow.com python click {search term, exception message, etc.}``
.. _Stack Overflow: https://stackoverflow.com/questions/tagged/python-click?tab=Frequent
Reporting issues
----------------
Include the following information in your post:
- Describe what you expected to happen.
- If possible, include a `minimal reproducible example`_ to help us
identify the issue. This also helps check that the issue is not with
your own code.
- Describe what actually happened. Include the full traceback if there
was an exception.
- List your Python and Click versions. If possible, check if this
issue is already fixed in the latest releases or the latest code in
the repository.
.. _minimal reproducible example: https://stackoverflow.com/help/minimal-reproducible-example
Submitting patches
------------------
If there is not an open issue for what you want to submit, prefer
opening one for discussion before working on a PR. You can work on any
issue that doesn't have an open PR linked to it or a maintainer assigned
to it. These show up in the sidebar. No need to ask if you can work on
an issue that interests you.
Include the following in your patch:
- Use `Black`_ to format your code. This and other tools will run
automatically if you install `pre-commit`_ using the instructions
below.
- Include tests if your patch adds or changes code. Make sure the test
fails without your patch.
- Update any relevant docs pages and docstrings. Docs pages and
docstrings should be wrapped at 72 characters.
- Add an entry in ``CHANGES.rst``. Use the same style as other
entries. Also include ``.. versionchanged::`` inline changelogs in
relevant docstrings.
.. _Black: https://black.readthedocs.io
.. _pre-commit: https://pre-commit.com
First time setup
~~~~~~~~~~~~~~~~
- Download and install the `latest version of git`_.
- Configure git with your `username`_ and `email`_.
.. code-block:: text
$ git config --global user.name 'your name'
$ git config --global user.email 'your email'
- Make sure you have a `GitHub account`_.
- Fork Click to your GitHub account by clicking the `Fork`_ button.
- `Clone`_ the main repository locally.
.. code-block:: text
$ git clone https://github.com/pallets/click
$ cd click
- Add your fork as a remote to push your work to. Replace
``{username}`` with your username. This names the remote "fork", the
default Pallets remote is "origin".
.. code-block:: text
$ git remote add fork https://github.com/{username}/click
- Create a virtualenv.
.. code-block:: text
$ python3 -m venv env
$ . env/bin/activate
On Windows, activating is different.
.. code-block:: text
> env\Scripts\activate
- Upgrade pip and setuptools.
.. code-block:: text
$ python -m pip install --upgrade pip setuptools
- Install the development dependencies, then install Click in
editable mode.
.. code-block:: text
$ pip install -r requirements/dev.txt && pip install -e .
- Install the pre-commit hooks.
.. code-block:: text
$ pre-commit install
.. _latest version of git: https://git-scm.com/downloads
.. _username: https://docs.github.com/en/github/using-git/setting-your-username-in-git
.. _email: https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address
.. _GitHub account: https://github.com/join
.. _Fork: https://github.com/pallets/click/fork
.. _Clone: https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#step-2-create-a-local-clone-of-your-fork
Start coding
~~~~~~~~~~~~
- Create a branch to identify the issue you would like to work on. If
you're submitting a bug or documentation fix, branch off of the
latest ".x" branch.
.. code-block:: text
$ git fetch origin
$ git checkout -b your-branch-name origin/8.0.x
If you're submitting a feature addition or change, branch off of the
"main" branch.
.. code-block:: text
$ git fetch origin
$ git checkout -b your-branch-name origin/main
- Using your favorite editor, make your changes,
`committing as you go`_.
- Include tests that cover any code changes you make. Make sure the
test fails without your patch. Run the tests as described below.
- Push your commits to your fork on GitHub and
`create a pull request`_. Link to the issue being addressed with
``fixes #123`` in the pull request.
.. code-block:: text
$ git push --set-upstream fork your-branch-name
.. _committing as you go: https://dont-be-afraid-to-commit.readthedocs.io/en/latest/git/commandlinegit.html#commit-your-changes
.. _create a pull request: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request
Running the tests
~~~~~~~~~~~~~~~~~
Run the basic test suite with pytest.
.. code-block:: text
$ pytest
This runs the tests for the current environment, which is usually
sufficient. CI will run the full suite when you submit your pull
request. You can run the full test suite with tox if you don't want to
wait.
.. code-block:: text
$ tox
Running test coverage
~~~~~~~~~~~~~~~~~~~~~
Generating a report of lines that do not have test coverage can indicate
where to start contributing. Run ``pytest`` using ``coverage`` and
generate a report.
.. code-block:: text
$ pip install coverage
$ coverage run -m pytest
$ coverage html
Open ``htmlcov/index.html`` in your browser to explore the report.
Read more about `coverage <https://coverage.readthedocs.io>`__.
Building the docs
~~~~~~~~~~~~~~~~~
Build the docs in the ``docs`` directory using Sphinx.
.. code-block:: text
$ cd docs
$ make html
Open ``_build/html/index.html`` in your browser to view the docs.
Read more about `Sphinx <https://www.sphinx-doc.org/en/stable/>`__.

View file

@ -1,28 +0,0 @@
Copyright 2014 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,10 +0,0 @@
include CHANGES.rst
include tox.ini
include requirements/*.txt
graft artwork
graft docs
prune docs/_build
graft examples
graft tests
include src/click/py.typed
global-exclude *.pyc

View file

@ -1,80 +0,0 @@
\$ click\_
==========
Click is a Python package for creating beautiful command line interfaces
in a composable way with as little code as necessary. It's the "Command
Line Interface Creation Kit". It's highly configurable but comes with
sensible defaults out of the box.
It aims to make the process of writing command line tools quick and fun
while also preventing any frustration caused by the inability to
implement an intended CLI API.
Click in three points:
- Arbitrary nesting of commands
- Automatic help page generation
- Supports lazy loading of subcommands at runtime
Installing
----------
Install and update using `pip`_:
.. code-block:: text
$ pip install -U click
.. _pip: https://pip.pypa.io/en/stable/getting-started/
A Simple Example
----------------
.. code-block:: python
import click
@click.command()
@click.option("--count", default=1, help="Number of greetings.")
@click.option("--name", prompt="Your name", help="The person to greet.")
def hello(count, name):
"""Simple program that greets NAME for a total of COUNT times."""
for _ in range(count):
click.echo(f"Hello, {name}!")
if __name__ == '__main__':
hello()
.. code-block:: text
$ python hello.py --count=3
Your name: Click
Hello, Click!
Hello, Click!
Hello, Click!
Donate
------
The Pallets organization develops and supports Click and other popular
packages. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, `please
donate today`_.
.. _please donate today: https://palletsprojects.com/donate
Links
-----
- Documentation: https://click.palletsprojects.com/
- Changes: https://click.palletsprojects.com/changes/
- PyPI Releases: https://pypi.org/project/click/
- Source Code: https://github.com/pallets/click
- Issue Tracker: https://github.com/pallets/click/issues
- Website: https://palletsprojects.com/p/click
- Twitter: https://twitter.com/PalletsTeam
- Chat: https://discord.gg/pallets

View file

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="237.36929"
height="110.7928"
id="svg4837"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="New document 8">
<defs
id="defs4839" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="259.76814"
inkscape:cy="40.769955"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="10"
fit-margin-left="10"
fit-margin-right="10"
fit-margin-bottom="10"
inkscape:window-width="1676"
inkscape:window-height="1006"
inkscape:window-x="4"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata4842">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-255.43458,-207.38101)">
<path
style="fill:#000000"
d="m 466.33424,306.48462 0,-1.6892 3.16724,0 3.16723,0 0,1.6892 0,1.68919 -3.16723,0 -3.16724,0 0,-1.68919 z m -3.37839,-5.06759 0,-3.37839 1.47804,0 1.47805,0 0,3.37839 0,3.37839 -1.47805,0 -1.47804,0 0,-3.37839 z m 10.13516,0 0,-3.37839 1.47804,0 1.47805,0 0,3.37839 0,3.37839 -1.47805,0 -1.47804,0 0,-3.37839 z m -30.82778,-28.92744 0,-28.92744 1.68919,0 c 1.68919,0 1.68919,0 1.68919,1.68919 0,1.6892 0,1.6892 1.6892,1.6892 1.68919,0 1.68919,0 1.68919,1.68919 0,1.6892 0,1.6892 1.6892,1.6892 1.68919,0 1.68919,0 1.68919,1.68919 0,1.6892 0,1.6892 -1.68919,1.6892 -1.6892,0 -1.6892,0 -1.6892,-1.6892 0,-1.68919 0,-1.68919 -1.68919,-1.68919 l -1.6892,0 0,23.85986 0,23.85985 1.6892,0 c 1.68919,0 1.68919,0 1.68919,1.6892 l 0,1.68919 -3.37839,0 -3.37838,0 0,-28.92744 z m 7.00029,25.22951 c -0.13394,-0.13393 -0.24352,-0.87696 -0.24352,-1.65118 0,-1.36423 0.0529,-1.40766 1.71469,-1.40766 l 1.71468,0 -0.13106,1.58362 c -0.12024,1.45279 -0.24178,1.5892 -1.47117,1.65118 -0.73706,0.0372 -1.44968,-0.042 -1.58362,-0.17596 z m 10.14204,-0.0392 c -0.13814,-0.22352 -0.20454,-1.7545 -0.14756,-3.40219 l 0.10361,-2.99581 1.60373,0 1.60374,0 -0.12334,3.27282 -0.12334,3.27281 -1.33284,0.12938 c -0.73305,0.0712 -1.44586,-0.0535 -1.584,-0.27702 z m 10.30707,-3.03247 0,-3.36553 1.47803,0 1.47805,0 0,3.30997 0,3.30996 -1.47805,0.0556 -1.47803,0.0556 0,-3.36553 z m -17.03271,-0.26872 c -0.15484,-0.15483 -0.28153,-0.91497 -0.28153,-1.68919 0,-1.36073 0.0563,-1.40766 1.68919,-1.40766 1.6892,0 1.6892,0 1.6892,1.6892 0,1.63289 -0.0469,1.68919 -1.40766,1.68919 -0.77422,0 -1.53436,-0.12669 -1.6892,-0.28154 z m 3.09686,-4.99719 c 0,-1.44286 0.0402,-1.47804 1.68919,-1.47804 1.64898,0 1.68919,0.0352 1.68919,1.47804 0,1.44285 -0.0402,1.47805 -1.68919,1.47805 -1.64898,0 -1.68919,-0.0352 -1.68919,-1.47805 z m 10.55746,-1.68919 0,-3.16724 6.75677,0 6.75678,0 0,-1.68919 c 0,-1.64898 0.0351,-1.6892 1.47804,-1.6892 l 1.47804,0 0,3.15652 0,3.15651 -6.6512,0.1163 -6.65119,0.1163 -0.13108,1.58361 c -0.12394,1.49763 -0.20994,1.58363 -1.58361,1.58363 l -1.45255,0 0,-3.16724 z m 10.13516,-8.44597 c 0,-1.40766 0.0704,-1.47804 1.47804,-1.47804 1.40766,0 1.47805,0.0704 1.47805,1.47804 0,1.40766 -0.0704,1.47804 -1.47805,1.47804 -1.40766,0 -1.47804,-0.0704 -1.47804,-1.47804 z m -3.37839,-3.37839 c 0,-1.40766 0.0704,-1.47804 1.47804,-1.47804 1.40767,0 1.47805,0.0704 1.47805,1.47804 0,1.40767 -0.0704,1.47805 -1.47805,1.47805 -1.40765,0 -1.47804,-0.0704 -1.47804,-1.47805 z m -3.37838,-3.37839 c 0,-1.40765 0.0704,-1.47804 1.47803,-1.47804 1.40767,0 1.47805,0.0704 1.47805,1.47804 0,1.40767 -0.0704,1.47805 -1.47805,1.47805 -1.40765,0 -1.47803,-0.0704 -1.47803,-1.47805 z m -3.37839,-3.48871 c 0,-1.52897 0.0553,-1.58931 1.47804,-1.61346 1.43567,-0.0244 1.47804,0.0211 1.47804,1.58838 0,1.56241 -0.0467,1.61345 -1.47804,1.61345 -1.42721,0 -1.47804,-0.0546 -1.47804,-1.58837 z m -3.37839,-3.47921 c 0,-1.64897 0.0351,-1.68919 1.47804,-1.68919 1.44285,0 1.47805,0.0402 1.47805,1.68919 0,1.64898 -0.0352,1.6892 -1.47805,1.6892 -1.44285,0 -1.47804,-0.0403 -1.47804,-1.6892 z m -3.45076,-3.37839 c 0.15328,-1.60738 0.23052,-1.68919 1.59478,-1.68919 1.3911,0 1.43368,0.0502 1.43368,1.68919 0,1.67253 -0.0157,1.6892 -1.59478,1.6892 l -1.59477,0 0.16109,-1.6892 z m -3.30601,-3.37838 c 0,-1.64898 0.0351,-1.6892 1.47804,-1.6892 1.44285,0 1.47804,0.0402 1.47804,1.6892 0,1.64897 -0.0352,1.68919 -1.47804,1.68919 -1.44286,0 -1.47804,-0.0402 -1.47804,-1.68919 z m -3.72061,-3.27282 c 0.12395,-1.49762 0.21706,-1.59073 1.71468,-1.71468 l 1.58363,-0.13107 0,1.71469 0,1.71468 -1.71469,0 -1.71468,0 0.13106,-1.58362 z"
id="path4856"
inkscape:connector-curvature="0" />
<path
style="fill:#000000"
d="m 271.34527,247.46047 c 0,-1.32826 -0.94153,-2.12734 -3.05297,-2.59109 -4.04056,-0.88746 -3.19986,-3.08429 1.01754,-2.65894 9.32239,0.94022 10.81407,-3.50307 2.60795,-7.76831 -2.71012,-1.40862 -5.36388,-3.27897 -5.89726,-4.15634 -1.47604,-2.42802 -0.0246,-6.42458 2.80076,-7.7119 1.48697,-0.67751 2.52398,-1.98054 2.52398,-3.17144 0,-1.13017 0.66136,-2.02144 1.5,-2.02144 0.825,0 1.5,0.85122 1.5,1.89159 0,1.19765 0.94321,2.12832 2.57104,2.53688 3.91591,0.98283 2.39946,3.10499 -1.95093,2.73019 -6.99788,-0.60291 -8.93527,3.8291 -2.87011,6.5657 9.0905,4.10163 11.015,9.73021 4.5,13.16112 -1.2375,0.65169 -2.25,2.06905 -2.25,3.1497 0,1.08065 -0.675,1.96482 -1.5,1.96482 -0.825,0 -1.5,-0.86425 -1.5,-1.92054 z m 38.357,-3.07104 c -4.57947,-1.84804 -6.77791,-8.48491 -4.32736,-13.06381 2.11183,-3.94599 10.30093,-6.28597 13.9414,-3.98367 2.2687,1.43477 0.36183,2.48777 -3.94232,2.177 -6.96682,-0.50302 -10.61631,6.27447 -5.91184,10.97894 1.71218,1.71218 2.95483,2.02243 6.5,1.62284 3.13626,-0.35351 4.38312,-0.13272 4.38312,0.77613 0,2.4062 -6.21813,3.27822 -10.643,1.49257 z m 21.1997,-1.23093 c -1.16379,-1.66155 -1.5567,-4.81653 -1.5567,-12.5 l 0,-10.27749 -2.5,0 c -1.55556,0 -2.5,-0.56667 -2.5,-1.5 0,-1.08333 1.11111,-1.5 4,-1.5 l 4,0 0.0153,11.25 c 0.008,6.1875 0.41056,11.87411 0.89363,12.63691 0.54214,0.85607 1.88505,1.19446 3.50856,0.88411 2.94677,-0.56331 4.58181,0.98192 2.46061,2.32547 -2.5829,1.63598 -6.70984,0.98184 -8.32141,-1.319 z m 20.4433,0.22251 c -1.55556,-1.55556 -2,-3.33333 -2,-8 0,-5.73333 -0.11111,-6 -2.5,-6 -1.55556,0 -2.5,-0.56667 -2.5,-1.5 0,-1.08333 1.11111,-1.5 4,-1.5 l 4,0 0.0153,6.75 c 0.0183,8.04891 0.82623,9.70461 4.40219,9.02102 2.94677,-0.56331 4.58181,0.98192 2.46061,2.32547 -2.3358,1.47948 -5.78176,0.99986 -7.87811,-1.09649 z m 18.357,1.00842 c -4.57947,-1.84804 -6.77791,-8.48491 -4.32736,-13.06381 2.11183,-3.94599 10.30093,-6.28597 13.9414,-3.98367 2.2687,1.43477 0.36183,2.48777 -3.94232,2.177 -6.96682,-0.50302 -10.61631,6.27447 -5.91184,10.97894 1.71218,1.71218 2.95483,2.02243 6.5,1.62284 3.13626,-0.35351 4.38312,-0.13272 4.38312,0.77613 0,2.4062 -6.21813,3.27822 -10.643,1.49257 z m 15.86478,-12.67646 c 0.20032,-9.84119 0.6282,-13.78431 1.52822,-14.08333 0.9358,-0.31091 1.25628,1.80502 1.275,8.41804 l 0.025,8.83333 4.01111,-4.25 c 2.32594,-2.46446 4.92367,-4.25 6.18321,-4.25 1.8968,0 1.6121,0.57059 -2.24643,4.50214 l -4.41851,4.50213 4.92271,4.99787 c 3.84161,3.90023 4.49929,4.99786 2.99467,4.99786 -1.06044,0 -4.08102,-2.12058 -6.71241,-4.71241 l -4.78435,-4.71241 0,4.71241 c 0,3.56082 -0.37346,4.71241 -1.52822,4.71241 -1.30999,0 -1.48849,-1.95179 -1.25,-13.66804 z m -37.85759,-9.82527 c -0.34636,-0.90262 -0.15025,-2.12063 0.43581,-2.70669 1.52361,-1.52361 4.41041,-0.13109 4.01242,1.93549 -0.4433,2.30188 -3.64766,2.85743 -4.44823,0.7712 z"
id="path4887"
inkscape:connector-curvature="0" />
<path
style="fill:#000000;fill-opacity:1;stroke:none"
d="m 411.32164,243.39982 c 7.38153,0.15924 14.76525,0.0821 22.14736,0.0136 -3.6814,3.83663 -9.42739,1.45689 -14.06576,2.07921 -3.69684,-0.007 -7.3939,0.0151 -11.09,0.0923 1.0029,-0.72825 2.00505,-1.45754 3.0084,-2.18514 z"
id="path4889"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.5 KiB

250
debian/changelog vendored
View file

@ -1,250 +0,0 @@
python-click (8.1.3-2~bpo11+1~evo) bullseye-backports; urgency=medium
* Rebuild for bullseye-backports.
-- David Prévot <taffit@debian.org> Fri, 03 Mar 2023 14:20:57 +0100
python-click (8.1.3-2) unstable; urgency=medium
* remove excessive changes not coordinated with the current maintainer.
* debian/copyright
- extend packaging copyright years
* debian/control
- bump Standards-Version to 4.6.2.0 (no changes needed)
-- Sandro Tosi <morph@debian.org> Tue, 10 Jan 2023 01:12:21 -0500
python-click (8.1.3-1) unstable; urgency=medium
* Team upload
[ Sandro Tosi ]
* Add autopkgtest
[ Carsten Schoenert ]
* d/gbp.conf: Add some more defaults
* New upstream version 8.1.3
* Add patch queue from patch-queue branch
Added patch:
docs-Use-local-Python-intersphinx-inventary.patch
* d/control: Switch and small update on build dependencies
* d/control: Bump Standards-Version to 4.6.1
No further modifications needed.
* d/control: Sorting binary packages alphabetical
No modifications to the control fields.
* d/copyright: Small updates on content
* d/u/metadata: Adding entries for FAQ and Documentation
* d/rules: Tune sphinxdoc build a bit
* d/rules: Remove unneded VCS file from package
* autopkgtest: Run test really on all python versions
* d/README.source: Addings some information about source
* d/control: Set Rules-Requires-Root: no
-- Carsten Schoenert <c.schoenert@t-online.de> Wed, 30 Nov 2022 11:16:40 +0100
python-click (8.0.3-1) unstable; urgency=medium
* New upstream release
* debian/copyright
- extend packaging copyright years
* debian/control
- add Breaks: python3-click-threading (<< 0.5.0); Closes: #994391
- bump Standards-Version to 4.6.0.1 (no changes needed)
-- Sandro Tosi <morph@debian.org> Sun, 02 Jan 2022 20:58:40 -0500
python-click (8.0.2-1) unstable; urgency=low
[ Debian Janitor ]
* Apply multi-arch hints.
+ python-click-doc: Add Multi-Arch: foreign.
[ Ondřej Nový ]
* d/control: Update Vcs-* fields with new Debian Python Team Salsa
layout.
[ Sandro Tosi ]
* New upstream release
* Use the new Debian Python Team contact name and address
* debian/watch
- track github releases
* debian/rules
- exclude test_expand_args, it fails and upstream is not interested in
helping out what may be wrong
* debian/control
- merge b-d-i into b-d
- add sphinx-tabs to b-d, needed by doc
- set versioned dep on pallets-sphinx-themes to >= 2.0.1, needed for
ethicalads.html template
-- Sandro Tosi <morph@debian.org> Sat, 09 Oct 2021 22:41:33 -0400
python-click (7.1.2-1) unstable; urgency=medium
[ Debian Janitor ]
* Bump debhelper from deprecated 9 to 12.
* Set upstream metadata fields: Bug-Database, Bug-Submit, Repository,
Repository-Browse.
* Update standards version to 4.5.0, no changes needed.
[ Sandro Tosi ]
* New upstream release
* debian/copyright
- extend packaging copyright years
- update upstream copyright information
* debian/control
- wrap-and-sort
- add sphinxcontrib-log-cabinet to b-d, needed by doc
- add sphinx.issues to b-d, needed by doc
- dh compat to 13
* debian/rules
- properly build doc and installd it in the right -doc location
- install examples
* debian/python-click-doc.doc-base
- adjust doc-base to new doc location
-- Sandro Tosi <morph@debian.org> Sun, 23 Aug 2020 23:18:54 -0400
python-click (7.0-3) unstable; urgency=medium
[ Ondřej Nový ]
* Use debhelper-compat instead of debian/compat.
* Bump Standards-Version to 4.4.1.
[ Sandro Tosi ]
* Drop python2 support; Closes: #937648
-- Sandro Tosi <morph@debian.org> Thu, 02 Jan 2020 22:56:09 -0500
python-click (7.0-2) unstable; urgency=medium
* debian/control
- adopt under DPMT umbrella; Thanks Alexandre for your previous work!
Closes: #940333
- bump Standards-Version to 4.4.0 (no changes needed)
- Update Vcs-* fields to DPMT location
* debian/copyright
- add packaging copyright
-- Sandro Tosi <morph@debian.org> Thu, 19 Sep 2019 19:24:24 -0400
python-click (7.0-1) unstable; urgency=medium
[ Ondřej Nový ]
* Use 'python3 -m sphinx' instead of sphinx-build for building docs
[ Alexandre Viau ]
* New upstream version. (Closes: #918561)
* d/watch: support Click and click.
-- Alexandre Viau <aviau@debian.org> Mon, 07 Jan 2019 11:53:07 -0500
python-click (6.7+git20180829-1) unstable; urgency=medium
* New upstream snapshot.
* Remove unneeded patches.
* Depend on python3-pallets-sphinx-themes.
* d/rules: no longer clean artwork/.
* d/rules: override_dh_sphinxdoc. (Closes: #906550)
-- Alexandre Viau <aviau@debian.org> Thu, 06 Sep 2018 15:21:26 -0400
python-click (6.7-5) unstable; urgency=medium
* Sphinx 1.7 support. (Closes: #896630)
-- Alexandre Viau <aviau@debian.org> Thu, 28 Jun 2018 20:37:56 -0400
python-click (6.7-4) unstable; urgency=medium
* Correct homepage field (Closes: #895277).
* Fix insecure-copyright-format-uri.
-- Alexandre Viau <aviau@debian.org> Fri, 13 Apr 2018 09:12:35 -0400
python-click (6.7-3.1) unstable; urgency=medium
* Non-maintainer upload.
* Ship documentation subpackage (Closes: #844432).
* Reduce short description length.
* Declare compliance with Debian policy 4.1.3.
-- Athos Ribeiro <athoscribeiro@gmail.com> Fri, 23 Mar 2018 23:25:00 +0000
python-click (6.7-3) unstable; urgency=medium
* Fix dead VCS-Git URL.
-- Alexandre Viau <aviau@debian.org> Sun, 07 Jan 2018 13:59:09 -0500
python-click (6.7-2) unstable; urgency=medium
* Move to salsa.debian.org.
-- Alexandre Viau <aviau@debian.org> Fri, 29 Dec 2017 01:02:22 -0500
python-click (6.7-1) unstable; urgency=medium
[ Ondřej Nový ]
* Enabled autopkgtest-pkg-python testsuite
* Standards-Version is 3.9.8 now (no changes needed)
* d/watch: Use https protocol
[ Alexandre Viau ]
* New upstream version (Closes: #856581)
* d/watch: exclude dev versions
* Create skip_test_legacy_callbacks.patch (Closes: #868816)
-- Alexandre Viau <aviau@debian.org> Wed, 19 Jul 2017 14:22:51 -0400
python-click (6.6-1) unstable; urgency=medium
[ Adrian Alves ]
* New upstream release
* upstream fixed debian patch fix-locale-check.patch
[ Alexandre Viau ]
* Changed version to 6.6
* Changed Vcs-Browser and Vcs-Git to secure (https) urls
* Bumped Standards-Version to 3.9.7
-- Alexandre Viau <aviau@debian.org> Fri, 25 Mar 2016 09:33:30 -0500
python-click (6.2-2) unstable; urgency=medium
* Fixed locale detection error (Closes: #812713)
-- Alexandre Viau <aviau@debian.org> Tue, 26 Jan 2016 09:33:30 -0500
python-click (6.2-1) unstable; urgency=medium
* New upstream release
* changed my email to @debian.org
-- Alexandre Viau <aviau@debian.org> Thu, 17 Dec 2015 08:54:36 -0500
python-click (5.1-1) unstable; urgency=low
* New upstream release
* Moved appropriate dependencies to Build-Depends-Indep
* Re-licensed debian packaging to BSD
-- Alexandre Viau <alexandre@alexandreviau.net> Sat, 22 Aug 2015 21:10:55 -0400
python-click (4.1-1) unstable; urgency=medium
* Upstream 4.1 release
-- Alexandre Viau <alexandre@alexandreviau.net> Thu, 16 Jul 2015 08:28:32 -0400
python-click (3.3-2) unstable; urgency=low
* Set UTF-8 before building (Closes: #772605)
-- Alexandre Viau <alexandre@alexandreviau.net> Tue, 09 Dec 2014 00:22:06 -0500
python-click (3.3-1) unstable; urgency=low
* Initial release (Closes: #764953)
-- Alexandre Viau <alexandre@alexandreviau.net> Fri, 10 Oct 2014 12:56:09 -0400

61
debian/control vendored
View file

@ -1,61 +0,0 @@
Source: python-click
Section: python
Priority: optional
Maintainer: Sandro Tosi <morph@debian.org>
Uploaders: Debian Python Team <team+python@tracker.debian.org>,
Build-Depends: debhelper-compat (= 13),
dh-sequence-python3,
python3-all,
python3-doc <!nodoc>,
python3-colorama,
python3-docutils,
python3-pallets-sphinx-themes (>= 2.0.1) <!nodoc>,
python3-pytest <!nocheck>,
python3-requests,
python3-setuptools,
python3-sphinx <!nodoc>,
python3-sphinx-issues <!nodoc>,
python3-sphinx-tabs <!nodoc>,
python3-sphinxcontrib-log-cabinet <!nodoc>,
Standards-Version: 4.6.2.0
Vcs-Browser: https://salsa.debian.org/python-team/packages/python-click
Vcs-Git: https://salsa.debian.org/python-team/packages/python-click.git
Homepage: https://github.com/pallets/click
Rules-Requires-Root: no
Testsuite: autopkgtest-pkg-python
Package: python3-click
Architecture: all
Depends: python3-colorama,
${misc:Depends},
${python3:Depends},
Breaks: python3-click-threading (<< 0.5.0),
Description: Wrapper around optparse for command line utilities - Python 3.x
Click is a Python package for creating beautiful command line interfaces
in a composable way with as little code as necessary. It's the "Command
Line Interface Creation Kit". It's highly configurable but comes with
sensible defaults out of the box.
.
It aims to make the process of writing command line tools quick and fun
while also preventing any frustration caused by the inability to implement
an intended CLI API.
.
This is the Python 3 compatible package.
Package: python-click-doc
Section: doc
Architecture: all
Depends: ${misc:Depends},
${sphinxdoc:Depends},
Multi-Arch: foreign
Description: Wrapper around optparse for command line utilities - documentation
Click is a Python package for creating beautiful command line interfaces
in a composable way with as little code as necessary. It's the "Command
Line Interface Creation Kit". It's highly configurable but comes with
sensible defaults out of the box.
.
It aims to make the process of writing command line tools quick and fun
while also preventing any frustration caused by the inability to implement
an intended CLI API.
.
This package contains the documentation for Click.

48
debian/copyright vendored
View file

@ -1,48 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Contact: contact@palletsprojects.com
Upstream-Name: click
Source: https://github.com/pallets/click
Files: *
Copyright: Copyright 2014 Pallets
2016-2022 David Lord <davidism@gmail.com>
License: BSD-3-clause
Files: src/click/parser.py
Copyright: 2001-2006 Gregory P. Ward
2002-2006 Python Software Foundation
License: BSD-3-clause
Files: debian/*
Copyright: 2014 Alexandre Viau <alexandre@alexandreviau.net>
Copyright (C) 2019-2023 Sandro Tosi <morph@debian.org>
License: BSD-3-clause
License: BSD-3-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
.
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
.
* The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,22 +0,0 @@
From: Carsten Schoenert <c.schoenert@t-online.de>
Date: Wed, 30 Nov 2022 10:04:35 +0100
Subject: docs: Use local Python intersphinx inventary
Forwarded: Not-Needed
---
docs/conf.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/conf.py b/docs/conf.py
index b0ed9ff..f4eab7a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -25,7 +25,7 @@ extensions = [
"sphinx_tabs.tabs",
]
autodoc_typehints = "description"
-intersphinx_mapping = {"python": ("https://docs.python.org/3/", None)}
+intersphinx_mapping = {"python": ("/usr/share/doc/python3-doc/html", None)}
issues_github_path = "pallets/click"
# HTML -----------------------------------------------------------------

View file

@ -1 +0,0 @@
docs-Use-local-Python-intersphinx-inventary.patch

View file

@ -1,15 +0,0 @@
Document: python-click
Title: Click Documentation
Author: Armin Ronacher
Abstract: Manual for Click
Section: Programming/Python
Format: text
Files: /usr/share/doc/python-click-doc/html/_sources/*.rst.txt
Format: HTML
Index: /usr/share/doc/python-click-doc/html/index.html
Files:
/usr/share/doc/python-click-doc/html/_static/*
/usr/share/doc/python-click-doc/html/*.html

34
debian/rules vendored
View file

@ -1,34 +0,0 @@
#!/usr/bin/make -f
# -*- makefile -*-
#export DH_VERBOSE=1
include /usr/share/dpkg/pkg-info.mk
BUILD_DATE = $(shell LC_ALL=C date -u "+%d %B %Y" -d "@$(SOURCE_DATE_EPOCH)")
SPHINXOPTS := -E -N -D html_last_updated_fmt="$(BUILD_DATE)"
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
export PYBUILD_NAME=click
export PYBUILD_TEST_PYTEST=1
export PYBUILD_TEST_ARGS=-k 'not test_expand_args' {dir}/tests/
export SOURCE = $(CURDIR)/debian/
%:
dh $@ --with sphinxdoc --buildsystem=pybuild
override_dh_sphinxdoc:
ifeq (,$(findstring nodoc, $(DEB_BUILD_OPTIONS)))
PYTHONPATH=src/ python3 -m sphinx -b html $(SPHINXOPTS) docs/ debian/python-click-doc/usr/share/doc/python-click-doc/html/
dh_sphinxdoc
endif
override_dh_installexamples:
dh_installexamples -ppython-click-doc examples/*
override_dh_fixperms:
dh_fixperms
rm -f debian/python-click-doc/usr/share/doc/python-click-doc/examples/imagepipe/.gitignore

View file

@ -1 +0,0 @@
3.0 (quilt)

View file

@ -1,4 +0,0 @@
Tests: unittests
Depends: @,
@builddeps@,
Restrictions: allow-stderr

View file

@ -1,18 +0,0 @@
#!/bin/sh
set -efu
pys="$(py3versions -s 2> /dev/null)"
cp -a setup.cfg tests "$AUTOPKGTEST_TMP"
# needed by `test_expand_args`
mkdir $AUTOPKGTEST_TMP/docs
cp -a docs/conf.py $AUTOPKGTEST_TMP/docs
cp -a setup.cfg "$AUTOPKGTEST_TMP"
cd "$AUTOPKGTEST_TMP"
for py in $pys; do
echo "=== $py ==="
$py -m pytest tests 2>&1
done

View file

@ -1,5 +0,0 @@
Bug-Database: https://github.com/pallets/click/issues
Bug-Submit: https://github.com/pallets/click/issues/new
Documentation: https://click.palletsprojects.com
Repository: https://github.com/pallets/click.git
Repository-Browse: https://github.com/pallets/click

3
debian/watch vendored
View file

@ -1,3 +0,0 @@
version=4
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%python-click-$1.tar.gz%" \
https://github.com/pallets/click/tags (?:.*?/)?v?(\d[\d.]*)\.tar\.gz

View file

@ -1,20 +0,0 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = Jinja
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,488 +0,0 @@
Advanced Patterns
=================
.. currentmodule:: click
In addition to common functionality that is implemented in the library
itself, there are countless patterns that can be implemented by extending
Click. This page should give some insight into what can be accomplished.
.. _aliases:
Command Aliases
---------------
Many tools support aliases for commands (see `Command alias example
<https://github.com/pallets/click/tree/main/examples/aliases>`_).
For instance, you can configure ``git`` to accept ``git ci`` as alias for
``git commit``. Other tools also support auto-discovery for aliases by
automatically shortening them.
Click does not support this out of the box, but it's very easy to customize
the :class:`Group` or any other :class:`MultiCommand` to provide this
functionality.
As explained in :ref:`custom-multi-commands`, a multi command can provide
two methods: :meth:`~MultiCommand.list_commands` and
:meth:`~MultiCommand.get_command`. In this particular case, you only need
to override the latter as you generally don't want to enumerate the
aliases on the help page in order to avoid confusion.
This following example implements a subclass of :class:`Group` that
accepts a prefix for a command. If there were a command called ``push``,
it would accept ``pus`` as an alias (so long as it was unique):
.. click:example::
class AliasedGroup(click.Group):
def get_command(self, ctx, cmd_name):
rv = click.Group.get_command(self, ctx, cmd_name)
if rv is not None:
return rv
matches = [x for x in self.list_commands(ctx)
if x.startswith(cmd_name)]
if not matches:
return None
elif len(matches) == 1:
return click.Group.get_command(self, ctx, matches[0])
ctx.fail(f"Too many matches: {', '.join(sorted(matches))}")
def resolve_command(self, ctx, args):
# always return the full command name
_, cmd, args = super().resolve_command(ctx, args)
return cmd.name, cmd, args
And it can then be used like this:
.. click:example::
@click.command(cls=AliasedGroup)
def cli():
pass
@cli.command()
def push():
pass
@cli.command()
def pop():
pass
Parameter Modifications
-----------------------
Parameters (options and arguments) are forwarded to the command callbacks
as you have seen. One common way to prevent a parameter from being passed
to the callback is the `expose_value` argument to a parameter which hides
the parameter entirely. The way this works is that the :class:`Context`
object has a :attr:`~Context.params` attribute which is a dictionary of
all parameters. Whatever is in that dictionary is being passed to the
callbacks.
This can be used to make up addition parameters. Generally this pattern
is not recommended but in some cases it can be useful. At the very least
it's good to know that the system works this way.
.. click:example::
import urllib
def open_url(ctx, param, value):
if value is not None:
ctx.params['fp'] = urllib.urlopen(value)
return value
@click.command()
@click.option('--url', callback=open_url)
def cli(url, fp=None):
if fp is not None:
click.echo(f"{url}: {fp.code}")
In this case the callback returns the URL unchanged but also passes a
second ``fp`` value to the callback. What's more recommended is to pass
the information in a wrapper however:
.. click:example::
import urllib
class URL(object):
def __init__(self, url, fp):
self.url = url
self.fp = fp
def open_url(ctx, param, value):
if value is not None:
return URL(value, urllib.urlopen(value))
@click.command()
@click.option('--url', callback=open_url)
def cli(url):
if url is not None:
click.echo(f"{url.url}: {url.fp.code}")
Token Normalization
-------------------
.. versionadded:: 2.0
Starting with Click 2.0, it's possible to provide a function that is used
for normalizing tokens. Tokens are option names, choice values, or command
values. This can be used to implement case insensitive options, for
instance.
In order to use this feature, the context needs to be passed a function that
performs the normalization of the token. For instance, you could have a
function that converts the token to lowercase:
.. click:example::
CONTEXT_SETTINGS = dict(token_normalize_func=lambda x: x.lower())
@click.command(context_settings=CONTEXT_SETTINGS)
@click.option('--name', default='Pete')
def cli(name):
click.echo(f"Name: {name}")
And how it works on the command line:
.. click:run::
invoke(cli, prog_name='cli', args=['--NAME=Pete'])
Invoking Other Commands
-----------------------
Sometimes, it might be interesting to invoke one command from another
command. This is a pattern that is generally discouraged with Click, but
possible nonetheless. For this, you can use the :func:`Context.invoke`
or :func:`Context.forward` methods.
They work similarly, but the difference is that :func:`Context.invoke` merely
invokes another command with the arguments you provide as a caller,
whereas :func:`Context.forward` fills in the arguments from the current
command. Both accept the command as the first argument and everything else
is passed onwards as you would expect.
Example:
.. click:example::
cli = click.Group()
@cli.command()
@click.option('--count', default=1)
def test(count):
click.echo(f'Count: {count}')
@cli.command()
@click.option('--count', default=1)
@click.pass_context
def dist(ctx, count):
ctx.forward(test)
ctx.invoke(test, count=42)
And what it looks like:
.. click:run::
invoke(cli, prog_name='cli', args=['dist'])
.. _callback-evaluation-order:
Callback Evaluation Order
-------------------------
Click works a bit differently than some other command line parsers in that
it attempts to reconcile the order of arguments as defined by the
programmer with the order of arguments as defined by the user before
invoking any callbacks.
This is an important concept to understand when porting complex
patterns to Click from optparse or other systems. A parameter
callback invocation in optparse happens as part of the parsing step,
whereas a callback invocation in Click happens after the parsing.
The main difference is that in optparse, callbacks are invoked with the raw
value as it happens, whereas a callback in Click is invoked after the
value has been fully converted.
Generally, the order of invocation is driven by the order in which the user
provides the arguments to the script; if there is an option called ``--foo``
and an option called ``--bar`` and the user calls it as ``--bar
--foo``, then the callback for ``bar`` will fire before the one for ``foo``.
There are three exceptions to this rule which are important to know:
Eagerness:
An option can be set to be "eager". All eager parameters are
evaluated before all non-eager parameters, but again in the order as
they were provided on the command line by the user.
This is important for parameters that execute and exit like ``--help``
and ``--version``. Both are eager parameters, but whatever parameter
comes first on the command line will win and exit the program.
Repeated parameters:
If an option or argument is split up on the command line into multiple
places because it is repeated -- for instance, ``--exclude foo --include
baz --exclude bar`` -- the callback will fire based on the position of
the first option. In this case, the callback will fire for
``exclude`` and it will be passed both options (``foo`` and
``bar``), then the callback for ``include`` will fire with ``baz``
only.
Note that even if a parameter does not allow multiple versions, Click
will still accept the position of the first, but it will ignore every
value except the last. The reason for this is to allow composability
through shell aliases that set defaults.
Missing parameters:
If a parameter is not defined on the command line, the callback will
still fire. This is different from how it works in optparse where
undefined values do not fire the callback. Missing parameters fire
their callbacks at the very end which makes it possible for them to
default to values from a parameter that came before.
Most of the time you do not need to be concerned about any of this,
but it is important to know how it works for some advanced cases.
.. _forwarding-unknown-options:
Forwarding Unknown Options
--------------------------
In some situations it is interesting to be able to accept all unknown
options for further manual processing. Click can generally do that as of
Click 4.0, but it has some limitations that lie in the nature of the
problem. The support for this is provided through a parser flag called
``ignore_unknown_options`` which will instruct the parser to collect all
unknown options and to put them to the leftover argument instead of
triggering a parsing error.
This can generally be activated in two different ways:
1. It can be enabled on custom :class:`Command` subclasses by changing
the :attr:`~BaseCommand.ignore_unknown_options` attribute.
2. It can be enabled by changing the attribute of the same name on the
context class (:attr:`Context.ignore_unknown_options`). This is best
changed through the ``context_settings`` dictionary on the command.
For most situations the easiest solution is the second. Once the behavior
is changed something needs to pick up those leftover options (which at
this point are considered arguments). For this again you have two
options:
1. You can use :func:`pass_context` to get the context passed. This will
only work if in addition to :attr:`~Context.ignore_unknown_options`
you also set :attr:`~Context.allow_extra_args` as otherwise the
command will abort with an error that there are leftover arguments.
If you go with this solution, the extra arguments will be collected in
:attr:`Context.args`.
2. You can attach a :func:`argument` with ``nargs`` set to `-1` which
will eat up all leftover arguments. In this case it's recommended to
set the `type` to :data:`UNPROCESSED` to avoid any string processing
on those arguments as otherwise they are forced into unicode strings
automatically which is often not what you want.
In the end you end up with something like this:
.. click:example::
import sys
from subprocess import call
@click.command(context_settings=dict(
ignore_unknown_options=True,
))
@click.option('-v', '--verbose', is_flag=True, help='Enables verbose mode')
@click.argument('timeit_args', nargs=-1, type=click.UNPROCESSED)
def cli(verbose, timeit_args):
"""A fake wrapper around Python's timeit."""
cmdline = ['echo', 'python', '-mtimeit'] + list(timeit_args)
if verbose:
click.echo(f"Invoking: {' '.join(cmdline)}")
call(cmdline)
And what it looks like:
.. click:run::
invoke(cli, prog_name='cli', args=['--help'])
println()
invoke(cli, prog_name='cli', args=['-n', '100', 'a = 1; b = 2; a * b'])
println()
invoke(cli, prog_name='cli', args=['-v', 'a = 1; b = 2; a * b'])
As you can see the verbosity flag is handled by Click, everything else
ends up in the `timeit_args` variable for further processing which then
for instance, allows invoking a subprocess. There are a few things that
are important to know about how this ignoring of unhandled flag happens:
* Unknown long options are generally ignored and not processed at all.
So for instance if ``--foo=bar`` or ``--foo bar`` are passed they
generally end up like that. Note that because the parser cannot know
if an option will accept an argument or not, the ``bar`` part might be
handled as an argument.
* Unknown short options might be partially handled and reassembled if
necessary. For instance in the above example there is an option
called ``-v`` which enables verbose mode. If the command would be
ignored with ``-va`` then the ``-v`` part would be handled by Click
(as it is known) and ``-a`` would end up in the leftover parameters
for further processing.
* Depending on what you plan on doing you might have some success by
disabling interspersed arguments
(:attr:`~Context.allow_interspersed_args`) which instructs the parser
to not allow arguments and options to be mixed. Depending on your
situation this might improve your results.
Generally though the combinated handling of options and arguments from
your own commands and commands from another application are discouraged
and if you can avoid it, you should. It's a much better idea to have
everything below a subcommand be forwarded to another application than to
handle some arguments yourself.
Global Context Access
---------------------
.. versionadded:: 5.0
Starting with Click 5.0 it is possible to access the current context from
anywhere within the same thread through the use of the
:func:`get_current_context` function which returns it. This is primarily
useful for accessing the context bound object as well as some flags that
are stored on it to customize the runtime behavior. For instance the
:func:`echo` function does this to infer the default value of the `color`
flag.
Example usage::
def get_current_command_name():
return click.get_current_context().info_name
It should be noted that this only works within the current thread. If you
spawn additional threads then those threads will not have the ability to
refer to the current context. If you want to give another thread the
ability to refer to this context you need to use the context within the
thread as a context manager::
def spawn_thread(ctx, func):
def wrapper():
with ctx:
func()
t = threading.Thread(target=wrapper)
t.start()
return t
Now the thread function can access the context like the main thread would
do. However if you do use this for threading you need to be very careful
as the vast majority of the context is not thread safe! You are only
allowed to read from the context, but not to perform any modifications on
it.
Detecting the Source of a Parameter
-----------------------------------
In some situations it's helpful to understand whether or not an option
or parameter came from the command line, the environment, the default
value, or :attr:`Context.default_map`. The
:meth:`Context.get_parameter_source` method can be used to find this
out. It will return a member of the :class:`~click.core.ParameterSource`
enum.
.. click:example::
@click.command()
@click.argument('port', nargs=1, default=8080, envvar="PORT")
@click.pass_context
def cli(ctx, port):
source = ctx.get_parameter_source("port")
click.echo(f"Port came from {source.name}")
.. click:run::
invoke(cli, prog_name='cli', args=['8080'])
println()
invoke(cli, prog_name='cli', args=[], env={"PORT": "8080"})
println()
invoke(cli, prog_name='cli', args=[])
println()
Managing Resources
------------------
It can be useful to open a resource in a group, to be made available to
subcommands. Many types of resources need to be closed or otherwise
cleaned up after use. The standard way to do this in Python is by using
a context manager with the ``with`` statement.
For example, the ``Repo`` class from :doc:`complex` might actually be
defined as a context manager:
.. code-block:: python
class Repo:
def __init__(self, home=None):
self.home = os.path.abspath(home or ".")
self.db = None
def __enter__(self):
path = os.path.join(self.home, "repo.db")
self.db = open_database(path)
def __exit__(self, exc_type, exc_value, tb):
self.db.close()
Ordinarily, it would be used with the ``with`` statement:
.. code-block:: python
with Repo() as repo:
repo.db.query(...)
However, a ``with`` block in a group would exit and close the database
before it could be used by a subcommand.
Instead, use the context's :meth:`~click.Context.with_resource` method
to enter the context manager and return the resource. When the group and
any subcommands finish, the context's resources are cleaned up.
.. code-block:: python
@click.group()
@click.option("--repo-home", default=".repo")
@click.pass_context
def cli(ctx, repo_home):
ctx.obj = ctx.with_resource(Repo(repo_home))
@cli.command()
@click.pass_obj
def log(obj):
# obj is the repo opened in the cli group
for entry in obj.db.query(...):
click.echo(entry)
If the resource isn't a context manager, usually it can be wrapped in
one using something from :mod:`contextlib`. If that's not possible, use
the context's :meth:`~click.Context.call_on_close` method to register a
cleanup function.
.. code-block:: python
@click.group()
@click.option("--name", default="repo.db")
@click.pass_context
def cli(ctx, repo_home):
ctx.obj = db = open_db(repo_home)
@ctx.call_on_close
def close_db():
db.record_use()
db.save()
db.close()

View file

@ -1,209 +0,0 @@
API
===
.. module:: click
This part of the documentation lists the full API reference of all public
classes and functions.
Decorators
----------
.. autofunction:: command
.. autofunction:: group
.. autofunction:: argument
.. autofunction:: option
.. autofunction:: password_option
.. autofunction:: confirmation_option
.. autofunction:: version_option
.. autofunction:: help_option
.. autofunction:: pass_context
.. autofunction:: pass_obj
.. autofunction:: make_pass_decorator
.. autofunction:: click.decorators.pass_meta_key
Utilities
---------
.. autofunction:: echo
.. autofunction:: echo_via_pager
.. autofunction:: prompt
.. autofunction:: confirm
.. autofunction:: progressbar
.. autofunction:: clear
.. autofunction:: style
.. autofunction:: unstyle
.. autofunction:: secho
.. autofunction:: edit
.. autofunction:: launch
.. autofunction:: getchar
.. autofunction:: pause
.. autofunction:: get_binary_stream
.. autofunction:: get_text_stream
.. autofunction:: open_file
.. autofunction:: get_app_dir
.. autofunction:: format_filename
Commands
--------
.. autoclass:: BaseCommand
:members:
.. autoclass:: Command
:members:
.. autoclass:: MultiCommand
:members:
.. autoclass:: Group
:members:
.. autoclass:: CommandCollection
:members:
Parameters
----------
.. autoclass:: Parameter
:members:
.. autoclass:: Option
.. autoclass:: Argument
Context
-------
.. autoclass:: Context
:members:
.. autofunction:: get_current_context
.. autoclass:: click.core.ParameterSource
:members:
:member-order: bysource
Types
-----
.. autodata:: STRING
.. autodata:: INT
.. autodata:: FLOAT
.. autodata:: BOOL
.. autodata:: UUID
.. autodata:: UNPROCESSED
.. autoclass:: File
.. autoclass:: Path
.. autoclass:: Choice
.. autoclass:: IntRange
.. autoclass:: FloatRange
.. autoclass:: DateTime
.. autoclass:: Tuple
.. autoclass:: ParamType
:members:
Exceptions
----------
.. autoexception:: ClickException
.. autoexception:: Abort
.. autoexception:: UsageError
.. autoexception:: BadParameter
.. autoexception:: FileError
.. autoexception:: NoSuchOption
.. autoexception:: BadOptionUsage
.. autoexception:: BadArgumentUsage
Formatting
----------
.. autoclass:: HelpFormatter
:members:
.. autofunction:: wrap_text
Parsing
-------
.. autoclass:: OptionParser
:members:
Shell Completion
----------------
See :doc:`/shell-completion` for information about enabling and
customizing Click's shell completion system.
.. currentmodule:: click.shell_completion
.. autoclass:: CompletionItem
.. autoclass:: ShellComplete
:members:
:member-order: bysource
.. autofunction:: add_completion_class
Testing
-------
.. currentmodule:: click.testing
.. autoclass:: CliRunner
:members:
.. autoclass:: Result
:members:

View file

@ -1,269 +0,0 @@
.. _arguments:
Arguments
=========
.. currentmodule:: click
Arguments work similarly to :ref:`options <options>` but are positional.
They also only support a subset of the features of options due to their
syntactical nature. Click will also not attempt to document arguments for
you and wants you to :ref:`document them manually <documenting-arguments>`
in order to avoid ugly help pages.
Basic Arguments
---------------
The most basic option is a simple string argument of one value. If no
type is provided, the type of the default value is used, and if no default
value is provided, the type is assumed to be :data:`STRING`.
Example:
.. click:example::
@click.command()
@click.argument('filename')
def touch(filename):
"""Print FILENAME."""
click.echo(filename)
And what it looks like:
.. click:run::
invoke(touch, args=['foo.txt'])
Variadic Arguments
------------------
The second most common version is variadic arguments where a specific (or
unlimited) number of arguments is accepted. This can be controlled with
the ``nargs`` parameter. If it is set to ``-1``, then an unlimited number
of arguments is accepted.
The value is then passed as a tuple. Note that only one argument can be
set to ``nargs=-1``, as it will eat up all arguments.
Example:
.. click:example::
@click.command()
@click.argument('src', nargs=-1)
@click.argument('dst', nargs=1)
def copy(src, dst):
"""Move file SRC to DST."""
for fn in src:
click.echo(f"move {fn} to folder {dst}")
And what it looks like:
.. click:run::
invoke(copy, args=['foo.txt', 'bar.txt', 'my_folder'])
Note that this is not how you would write this application. The reason
for this is that in this particular example the arguments are defined as
strings. Filenames, however, are not strings! They might be on certain
operating systems, but not necessarily on all. For better ways to write
this, see the next sections.
.. admonition:: Note on Non-Empty Variadic Arguments
If you come from ``argparse``, you might be missing support for setting
``nargs`` to ``+`` to indicate that at least one argument is required.
This is supported by setting ``required=True``. However, this should
not be used if you can avoid it as we believe scripts should gracefully
degrade into becoming noops if a variadic argument is empty. The
reason for this is that very often, scripts are invoked with wildcard
inputs from the command line and they should not error out if the
wildcard is empty.
.. _file-args:
File Arguments
--------------
Since all the examples have already worked with filenames, it makes sense
to explain how to deal with files properly. Command line tools are more
fun if they work with files the Unix way, which is to accept ``-`` as a
special file that refers to stdin/stdout.
Click supports this through the :class:`click.File` type which
intelligently handles files for you. It also deals with Unicode and bytes
correctly for all versions of Python so your script stays very portable.
Example:
.. click:example::
@click.command()
@click.argument('input', type=click.File('rb'))
@click.argument('output', type=click.File('wb'))
def inout(input, output):
"""Copy contents of INPUT to OUTPUT."""
while True:
chunk = input.read(1024)
if not chunk:
break
output.write(chunk)
And what it does:
.. click:run::
with isolated_filesystem():
invoke(inout, args=['-', 'hello.txt'], input=['hello'],
terminate_input=True)
invoke(inout, args=['hello.txt', '-'])
File Path Arguments
-------------------
In the previous example, the files were opened immediately. But what if
we just want the filename? The naïve way is to use the default string
argument type. However, remember that Click is Unicode-based, so the string
will always be a Unicode value. Unfortunately, filenames can be Unicode or
bytes depending on which operating system is being used. As such, the type
is insufficient.
Instead, you should be using the :class:`Path` type, which automatically
handles this ambiguity. Not only will it return either bytes or Unicode
depending on what makes more sense, but it will also be able to do some
basic checks for you such as existence checks.
Example:
.. click:example::
@click.command()
@click.argument('filename', type=click.Path(exists=True))
def touch(filename):
"""Print FILENAME if the file exists."""
click.echo(click.format_filename(filename))
And what it does:
.. click:run::
with isolated_filesystem():
with open('hello.txt', 'w') as f:
f.write('Hello World!\n')
invoke(touch, args=['hello.txt'])
println()
invoke(touch, args=['missing.txt'])
File Opening Safety
-------------------
The :class:`FileType` type has one problem it needs to deal with, and that
is to decide when to open a file. The default behavior is to be
"intelligent" about it. What this means is that it will open stdin/stdout
and files opened for reading immediately. This will give the user direct
feedback when a file cannot be opened, but it will only open files
for writing the first time an IO operation is performed by automatically
wrapping the file in a special wrapper.
This behavior can be forced by passing ``lazy=True`` or ``lazy=False`` to
the constructor. If the file is opened lazily, it will fail its first IO
operation by raising an :exc:`FileError`.
Since files opened for writing will typically immediately empty the file,
the lazy mode should only be disabled if the developer is absolutely sure
that this is intended behavior.
Forcing lazy mode is also very useful to avoid resource handling
confusion. If a file is opened in lazy mode, it will receive a
``close_intelligently`` method that can help figure out if the file
needs closing or not. This is not needed for parameters, but is
necessary for manually prompting with the :func:`prompt` function as you
do not know if a stream like stdout was opened (which was already open
before) or a real file that needs closing.
Starting with Click 2.0, it is also possible to open files in atomic mode by
passing ``atomic=True``. In atomic mode, all writes go into a separate
file in the same folder, and upon completion, the file will be moved over to
the original location. This is useful if a file regularly read by other
users is modified.
Environment Variables
---------------------
Like options, arguments can also grab values from an environment variable.
Unlike options, however, this is only supported for explicitly named
environment variables.
Example usage:
.. click:example::
@click.command()
@click.argument('src', envvar='SRC', type=click.File('r'))
def echo(src):
"""Print value of SRC environment variable."""
click.echo(src.read())
And from the command line:
.. click:run::
with isolated_filesystem():
with open('hello.txt', 'w') as f:
f.write('Hello World!')
invoke(echo, env={'SRC': 'hello.txt'})
In that case, it can also be a list of different environment variables
where the first one is picked.
Generally, this feature is not recommended because it can cause the user
a lot of confusion.
Option-Like Arguments
---------------------
Sometimes, you want to process arguments that look like options. For
instance, imagine you have a file named ``-foo.txt``. If you pass this as
an argument in this manner, Click will treat it as an option.
To solve this, Click does what any POSIX style command line script does,
and that is to accept the string ``--`` as a separator for options and
arguments. After the ``--`` marker, all further parameters are accepted as
arguments.
Example usage:
.. click:example::
@click.command()
@click.argument('files', nargs=-1, type=click.Path())
def touch(files):
"""Print all FILES file names."""
for filename in files:
click.echo(filename)
And from the command line:
.. click:run::
invoke(touch, ['--', '-foo.txt', 'bar.txt'])
If you don't like the ``--`` marker, you can set ignore_unknown_options to
True to avoid checking unknown options:
.. click:example::
@click.command(context_settings={"ignore_unknown_options": True})
@click.argument('files', nargs=-1, type=click.Path())
def touch(files):
"""Print all FILES file names."""
for filename in files:
click.echo(filename)
And from the command line:
.. click:run::
invoke(touch, ['-foo.txt', 'bar.txt'])

View file

@ -1,4 +0,0 @@
Changes
=======
.. include:: ../CHANGES.rst

View file

@ -1,571 +0,0 @@
Commands and Groups
===================
.. currentmodule:: click
The most important feature of Click is the concept of arbitrarily nesting
command line utilities. This is implemented through the :class:`Command`
and :class:`Group` (actually :class:`MultiCommand`).
Callback Invocation
-------------------
For a regular command, the callback is executed whenever the command runs.
If the script is the only command, it will always fire (unless a parameter
callback prevents it. This for instance happens if someone passes
``--help`` to the script).
For groups and multi commands, the situation looks different. In this case,
the callback fires whenever a subcommand fires (unless this behavior is
changed). What this means in practice is that an outer command runs
when an inner command runs:
.. click:example::
@click.group()
@click.option('--debug/--no-debug', default=False)
def cli(debug):
click.echo(f"Debug mode is {'on' if debug else 'off'}")
@cli.command() # @cli, not @click!
def sync():
click.echo('Syncing')
Here is what this looks like:
.. click:run::
invoke(cli, prog_name='tool.py')
println()
invoke(cli, prog_name='tool.py', args=['--debug', 'sync'])
Passing Parameters
------------------
Click strictly separates parameters between commands and subcommands. What this
means is that options and arguments for a specific command have to be specified
*after* the command name itself, but *before* any other command names.
This behavior is already observable with the predefined ``--help`` option.
Suppose we have a program called ``tool.py``, containing a subcommand called
``sub``.
- ``tool.py --help`` will return the help for the whole program (listing
subcommands).
- ``tool.py sub --help`` will return the help for the ``sub`` subcommand.
- But ``tool.py --help sub`` will treat ``--help`` as an argument for the main
program. Click then invokes the callback for ``--help``, which prints the
help and aborts the program before click can process the subcommand.
Nested Handling and Contexts
----------------------------
As you can see from the earlier example, the basic command group accepts a
debug argument which is passed to its callback, but not to the sync
command itself. The sync command only accepts its own arguments.
This allows tools to act completely independent of each other, but how
does one command talk to a nested one? The answer to this is the
:class:`Context`.
Each time a command is invoked, a new context is created and linked with the
parent context. Normally, you can't see these contexts, but they are
there. Contexts are passed to parameter callbacks together with the
value automatically. Commands can also ask for the context to be passed
by marking themselves with the :func:`pass_context` decorator. In that
case, the context is passed as first argument.
The context can also carry a program specified object that can be
used for the program's purposes. What this means is that you can build a
script like this:
.. click:example::
@click.group()
@click.option('--debug/--no-debug', default=False)
@click.pass_context
def cli(ctx, debug):
# ensure that ctx.obj exists and is a dict (in case `cli()` is called
# by means other than the `if` block below)
ctx.ensure_object(dict)
ctx.obj['DEBUG'] = debug
@cli.command()
@click.pass_context
def sync(ctx):
click.echo(f"Debug is {'on' if ctx.obj['DEBUG'] else 'off'}")
if __name__ == '__main__':
cli(obj={})
If the object is provided, each context will pass the object onwards to
its children, but at any level a context's object can be overridden. To
reach to a parent, ``context.parent`` can be used.
In addition to that, instead of passing an object down, nothing stops the
application from modifying global state. For instance, you could just flip
a global ``DEBUG`` variable and be done with it.
Decorating Commands
-------------------
As you have seen in the earlier example, a decorator can change how a
command is invoked. What actually happens behind the scenes is that
callbacks are always invoked through the :meth:`Context.invoke` method
which automatically invokes a command correctly (by either passing the
context or not).
This is very useful when you want to write custom decorators. For
instance, a common pattern would be to configure an object representing
state and then storing it on the context and then to use a custom
decorator to find the most recent object of this sort and pass it as first
argument.
For instance, the :func:`pass_obj` decorator can be implemented like this:
.. click:example::
from functools import update_wrapper
def pass_obj(f):
@click.pass_context
def new_func(ctx, *args, **kwargs):
return ctx.invoke(f, ctx.obj, *args, **kwargs)
return update_wrapper(new_func, f)
The :meth:`Context.invoke` command will automatically invoke the function
in the correct way, so the function will either be called with ``f(ctx,
obj)`` or ``f(obj)`` depending on whether or not it itself is decorated with
:func:`pass_context`.
This is a very powerful concept that can be used to build very complex
nested applications; see :ref:`complex-guide` for more information.
Group Invocation Without Command
--------------------------------
By default, a group or multi command is not invoked unless a subcommand is
passed. In fact, not providing a command automatically passes ``--help``
by default. This behavior can be changed by passing
``invoke_without_command=True`` to a group. In that case, the callback is
always invoked instead of showing the help page. The context object also
includes information about whether or not the invocation would go to a
subcommand.
Example:
.. click:example::
@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
if ctx.invoked_subcommand is None:
click.echo('I was invoked without subcommand')
else:
click.echo(f"I am about to invoke {ctx.invoked_subcommand}")
@cli.command()
def sync():
click.echo('The subcommand')
And how it works in practice:
.. click:run::
invoke(cli, prog_name='tool', args=[])
invoke(cli, prog_name='tool', args=['sync'])
.. _custom-multi-commands:
Custom Multi Commands
---------------------
In addition to using :func:`click.group`, you can also build your own
custom multi commands. This is useful when you want to support commands
being loaded lazily from plugins.
A custom multi command just needs to implement a list and load method:
.. click:example::
import click
import os
plugin_folder = os.path.join(os.path.dirname(__file__), 'commands')
class MyCLI(click.MultiCommand):
def list_commands(self, ctx):
rv = []
for filename in os.listdir(plugin_folder):
if filename.endswith('.py') and filename != '__init__.py':
rv.append(filename[:-3])
rv.sort()
return rv
def get_command(self, ctx, name):
ns = {}
fn = os.path.join(plugin_folder, name + '.py')
with open(fn) as f:
code = compile(f.read(), fn, 'exec')
eval(code, ns, ns)
return ns['cli']
cli = MyCLI(help='This tool\'s subcommands are loaded from a '
'plugin folder dynamically.')
if __name__ == '__main__':
cli()
These custom classes can also be used with decorators:
.. click:example::
@click.command(cls=MyCLI)
def cli():
pass
Merging Multi Commands
----------------------
In addition to implementing custom multi commands, it can also be
interesting to merge multiple together into one script. While this is
generally not as recommended as it nests one below the other, the merging
approach can be useful in some circumstances for a nicer shell experience.
The default implementation for such a merging system is the
:class:`CommandCollection` class. It accepts a list of other multi
commands and makes the commands available on the same level.
Example usage:
.. click:example::
import click
@click.group()
def cli1():
pass
@cli1.command()
def cmd1():
"""Command on cli1"""
@click.group()
def cli2():
pass
@cli2.command()
def cmd2():
"""Command on cli2"""
cli = click.CommandCollection(sources=[cli1, cli2])
if __name__ == '__main__':
cli()
And what it looks like:
.. click:run::
invoke(cli, prog_name='cli', args=['--help'])
In case a command exists in more than one source, the first source wins.
.. _multi-command-chaining:
Multi Command Chaining
----------------------
.. versionadded:: 3.0
Sometimes it is useful to be allowed to invoke more than one subcommand in
one go. For instance if you have installed a setuptools package before
you might be familiar with the ``setup.py sdist bdist_wheel upload``
command chain which invokes ``sdist`` before ``bdist_wheel`` before
``upload``. Starting with Click 3.0 this is very simple to implement.
All you have to do is to pass ``chain=True`` to your multicommand:
.. click:example::
@click.group(chain=True)
def cli():
pass
@cli.command('sdist')
def sdist():
click.echo('sdist called')
@cli.command('bdist_wheel')
def bdist_wheel():
click.echo('bdist_wheel called')
Now you can invoke it like this:
.. click:run::
invoke(cli, prog_name='setup.py', args=['sdist', 'bdist_wheel'])
When using multi command chaining you can only have one command (the last)
use ``nargs=-1`` on an argument. It is also not possible to nest multi
commands below chained multicommands. Other than that there are no
restrictions on how they work. They can accept options and arguments as
normal. The order between options and arguments is limited for chained
commands. Currently only ``--options argument`` order is allowed.
Another note: the :attr:`Context.invoked_subcommand` attribute is a bit
useless for multi commands as it will give ``'*'`` as value if more than
one command is invoked. This is necessary because the handling of
subcommands happens one after another so the exact subcommands that will
be handled are not yet available when the callback fires.
.. note::
It is currently not possible for chain commands to be nested. This
will be fixed in future versions of Click.
Multi Command Pipelines
-----------------------
.. versionadded:: 3.0
A very common usecase of multi command chaining is to have one command
process the result of the previous command. There are various ways in
which this can be facilitated. The most obvious way is to store a value
on the context object and process it from function to function. This
works by decorating a function with :func:`pass_context` after which the
context object is provided and a subcommand can store its data there.
Another way to accomplish this is to setup pipelines by returning
processing functions. Think of it like this: when a subcommand gets
invoked it processes all of its parameters and comes up with a plan of
how to do its processing. At that point it then returns a processing
function and returns.
Where do the returned functions go? The chained multicommand can register
a callback with :meth:`MultiCommand.result_callback` that goes over all
these functions and then invoke them.
To make this a bit more concrete consider this example:
.. click:example::
@click.group(chain=True, invoke_without_command=True)
@click.option('-i', '--input', type=click.File('r'))
def cli(input):
pass
@cli.result_callback()
def process_pipeline(processors, input):
iterator = (x.rstrip('\r\n') for x in input)
for processor in processors:
iterator = processor(iterator)
for item in iterator:
click.echo(item)
@cli.command('uppercase')
def make_uppercase():
def processor(iterator):
for line in iterator:
yield line.upper()
return processor
@cli.command('lowercase')
def make_lowercase():
def processor(iterator):
for line in iterator:
yield line.lower()
return processor
@cli.command('strip')
def make_strip():
def processor(iterator):
for line in iterator:
yield line.strip()
return processor
That's a lot in one go, so let's go through it step by step.
1. The first thing is to make a :func:`group` that is chainable. In
addition to that we also instruct Click to invoke even if no
subcommand is defined. If this would not be done, then invoking an
empty pipeline would produce the help page instead of running the
result callbacks.
2. The next thing we do is to register a result callback on our group.
This callback will be invoked with an argument which is the list of
all return values of all subcommands and then the same keyword
parameters as our group itself. This means we can access the input
file easily there without having to use the context object.
3. In this result callback we create an iterator of all the lines in the
input file and then pass this iterator through all the returned
callbacks from all subcommands and finally we print all lines to
stdout.
After that point we can register as many subcommands as we want and each
subcommand can return a processor function to modify the stream of lines.
One important thing of note is that Click shuts down the context after
each callback has been run. This means that for instance file types
cannot be accessed in the `processor` functions as the files will already
be closed there. This limitation is unlikely to change because it would
make resource handling much more complicated. For such it's recommended
to not use the file type and manually open the file through
:func:`open_file`.
For a more complex example that also improves upon handling of the
pipelines have a look at the `imagepipe multi command chaining demo
<https://github.com/pallets/click/tree/main/examples/imagepipe>`__ in
the Click repository. It implements a pipeline based image editing tool
that has a nice internal structure for the pipelines.
Overriding Defaults
-------------------
By default, the default value for a parameter is pulled from the
``default`` flag that is provided when it's defined, but that's not the
only place defaults can be loaded from. The other place is the
:attr:`Context.default_map` (a dictionary) on the context. This allows
defaults to be loaded from a configuration file to override the regular
defaults.
This is useful if you plug in some commands from another package but
you're not satisfied with the defaults.
The default map can be nested arbitrarily for each subcommand:
.. code-block:: python
default_map = {
"debug": True, # default for a top level option
"runserver": {"port": 5000} # default for a subcommand
}
The default map can be provided when the script is invoked, or
overridden at any point by commands. For instance, a top-level command
could load the defaults from a configuration file.
Example usage:
.. click:example::
import click
@click.group()
def cli():
pass
@cli.command()
@click.option('--port', default=8000)
def runserver(port):
click.echo(f"Serving on http://127.0.0.1:{port}/")
if __name__ == '__main__':
cli(default_map={
'runserver': {
'port': 5000
}
})
And in action:
.. click:run::
invoke(cli, prog_name='cli', args=['runserver'], default_map={
'runserver': {
'port': 5000
}
})
Context Defaults
----------------
.. versionadded:: 2.0
Starting with Click 2.0 you can override defaults for contexts not just
when calling your script, but also in the decorator that declares a
command. For instance given the previous example which defines a custom
``default_map`` this can also be accomplished in the decorator now.
This example does the same as the previous example:
.. click:example::
import click
CONTEXT_SETTINGS = dict(
default_map={'runserver': {'port': 5000}}
)
@click.group(context_settings=CONTEXT_SETTINGS)
def cli():
pass
@cli.command()
@click.option('--port', default=8000)
def runserver(port):
click.echo(f"Serving on http://127.0.0.1:{port}/")
if __name__ == '__main__':
cli()
And again the example in action:
.. click:run::
invoke(cli, prog_name='cli', args=['runserver'])
Command Return Values
---------------------
.. versionadded:: 3.0
One of the new introductions in Click 3.0 is the full support for return
values from command callbacks. This enables a whole range of features
that were previously hard to implement.
In essence any command callback can now return a value. This return value
is bubbled to certain receivers. One usecase for this has already been
show in the example of :ref:`multi-command-chaining` where it has been
demonstrated that chained multi commands can have callbacks that process
all return values.
When working with command return values in Click, this is what you need to
know:
- The return value of a command callback is generally returned from the
:meth:`BaseCommand.invoke` method. The exception to this rule has to
do with :class:`Group`\s:
* In a group the return value is generally the return value of the
subcommand invoked. The only exception to this rule is that the
return value is the return value of the group callback if it's
invoked without arguments and `invoke_without_command` is enabled.
* If a group is set up for chaining then the return value is a list
of all subcommands' results.
* Return values of groups can be processed through a
:attr:`MultiCommand.result_callback`. This is invoked with the
list of all return values in chain mode, or the single return
value in case of non chained commands.
- The return value is bubbled through from the :meth:`Context.invoke`
and :meth:`Context.forward` methods. This is useful in situations
where you internally want to call into another command.
- Click does not have any hard requirements for the return values and
does not use them itself. This allows return values to be used for
custom decorators or workflows (like in the multi command chaining
example).
- When a Click script is invoked as command line application (through
:meth:`BaseCommand.main`) the return value is ignored unless the
`standalone_mode` is disabled in which case it's bubbled through.

View file

@ -1,220 +0,0 @@
.. _complex-guide:
Complex Applications
====================
.. currentmodule:: click
Click is designed to assist with the creation of complex and simple CLI tools
alike. However, the power of its design is the ability to arbitrarily nest
systems together. For instance, if you have ever used Django, you will
have realized that it provides a command line utility, but so does Celery.
When using Celery with Django, there are two tools that need to interact with
each other and be cross-configured.
In a theoretical world of two separate Click command line utilities, they
could solve this problem by nesting one inside the other. For instance, the
web framework could also load the commands for the message queue framework.
Basic Concepts
--------------
To understand how this works, you need to understand two concepts: contexts
and the calling convention.
Contexts
````````
Whenever a Click command is executed, a :class:`Context` object is created
which holds state for this particular invocation. It remembers parsed
parameters, what command created it, which resources need to be cleaned up
at the end of the function, and so forth. It can also optionally hold an
application-defined object.
Context objects build a linked list until they hit the top one. Each context
is linked to a parent context. This allows a command to work below
another command and store its own information there without having to be
afraid of altering up the state of the parent command.
Because the parent data is available, however, it is possible to navigate to
it if needed.
Most of the time, you do not see the context object, but when writing more
complex applications it comes in handy. This brings us to the next point.
Calling Convention
``````````````````
When a Click command callback is executed, it's passed all the non-hidden
parameters as keyword arguments. Notably absent is the context. However,
a callback can opt into being passed to the context object by marking itself
with :func:`pass_context`.
So how do you invoke a command callback if you don't know if it should
receive the context or not? The answer is that the context itself
provides a helper function (:meth:`Context.invoke`) which can do this for
you. It accepts the callback as first argument and then invokes the
function correctly.
Building a Git Clone
--------------------
In this example, we want to build a command line tool that resembles a
version control system. Systems like Git usually provide one
over-arching command that already accepts some parameters and
configuration, and then have extra subcommands that do other things.
The Root Command
````````````````
At the top level, we need a group that can hold all our commands. In this
case, we use the basic :func:`click.group` which allows us to register
other Click commands below it.
For this command, we also want to accept some parameters that configure the
state of our tool:
.. click:example::
import os
import click
class Repo(object):
def __init__(self, home=None, debug=False):
self.home = os.path.abspath(home or '.')
self.debug = debug
@click.group()
@click.option('--repo-home', envvar='REPO_HOME', default='.repo')
@click.option('--debug/--no-debug', default=False,
envvar='REPO_DEBUG')
@click.pass_context
def cli(ctx, repo_home, debug):
ctx.obj = Repo(repo_home, debug)
Let's understand what this does. We create a group command which can
have subcommands. When it is invoked, it will create an instance of a
``Repo`` class. This holds the state for our command line tool. In this
case, it just remembers some parameters, but at this point it could also
start loading configuration files and so on.
This state object is then remembered by the context as :attr:`~Context.obj`.
This is a special attribute where commands are supposed to remember what
they need to pass on to their children.
In order for this to work, we need to mark our function with
:func:`pass_context`, because otherwise, the context object would be
entirely hidden from us.
The First Child Command
```````````````````````
Let's add our first child command to it, the clone command:
.. click:example::
@cli.command()
@click.argument('src')
@click.argument('dest', required=False)
def clone(src, dest):
pass
So now we have a clone command, but how do we get access to the repo? As
you can imagine, one way is to use the :func:`pass_context` function which
again will make our callback also get the context passed on which we
memorized the repo. However, there is a second version of this decorator
called :func:`pass_obj` which will just pass the stored object, (in our case
the repo):
.. click:example::
@cli.command()
@click.argument('src')
@click.argument('dest', required=False)
@click.pass_obj
def clone(repo, src, dest):
pass
Interleaved Commands
````````````````````
While not relevant for the particular program we want to build, there is
also quite good support for interleaving systems. Imagine for instance that
there was a super cool plugin for our version control system that needed a
lot of configuration and wanted to store its own configuration as
:attr:`~Context.obj`. If we would then attach another command below that,
we would all of a sudden get the plugin configuration instead of our repo
object.
One obvious way to remedy this is to store a reference to the repo in the
plugin, but then a command needs to be aware that it's attached below such a
plugin.
There is a much better system that can be built by taking advantage of the
linked nature of contexts. We know that the plugin context is linked to the
context that created our repo. Because of that, we can start a search for
the last level where the object stored by the context was a repo.
Built-in support for this is provided by the :func:`make_pass_decorator`
factory, which will create decorators for us that find objects (it
internally calls into :meth:`Context.find_object`). In our case, we
know that we want to find the closest ``Repo`` object, so let's make a
decorator for this:
.. click:example::
pass_repo = click.make_pass_decorator(Repo)
If we now use ``pass_repo`` instead of ``pass_obj``, we will always get a
repo instead of something else:
.. click:example::
@cli.command()
@click.argument('src')
@click.argument('dest', required=False)
@pass_repo
def clone(repo, src, dest):
pass
Ensuring Object Creation
````````````````````````
The above example only works if there was an outer command that created a
``Repo`` object and stored it in the context. For some more advanced use
cases, this might become a problem. The default behavior of
:func:`make_pass_decorator` is to call :meth:`Context.find_object`
which will find the object. If it can't find the object,
:meth:`make_pass_decorator` will raise an error.
The alternative behavior is to use :meth:`Context.ensure_object`
which will find the object, and if it cannot find it, will create one and
store it in the innermost context. This behavior can also be enabled for
:func:`make_pass_decorator` by passing ``ensure=True``:
.. click:example::
pass_repo = click.make_pass_decorator(Repo, ensure=True)
In this case, the innermost context gets an object created if it is
missing. This might replace objects being placed there earlier. In this
case, the command stays executable, even if the outer command does not run.
For this to work, the object type needs to have a constructor that accepts
no arguments.
As such it runs standalone:
.. click:example::
@click.command()
@pass_repo
def cp(repo):
click.echo(isinstance(repo, Repo))
As you can see:
.. click:run::
invoke(cp, [])

View file

@ -1,59 +0,0 @@
from pallets_sphinx_themes import get_version
from pallets_sphinx_themes import ProjectLink
import click._compat
# compat until pallets-sphinx-themes is updated
click._compat.text_type = str
# Project --------------------------------------------------------------
project = "Click"
copyright = "2014 Pallets"
author = "Pallets"
release, version = get_version("Click")
# General --------------------------------------------------------------
master_doc = "index"
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinxcontrib.log_cabinet",
"pallets_sphinx_themes",
"sphinx_issues",
"sphinx_tabs.tabs",
]
autodoc_typehints = "description"
intersphinx_mapping = {"python": ("https://docs.python.org/3/", None)}
issues_github_path = "pallets/click"
# HTML -----------------------------------------------------------------
html_theme = "click"
html_theme_options = {"index_sidebar_logo": False}
html_context = {
"project_links": [
ProjectLink("Donate", "https://palletsprojects.com/donate"),
ProjectLink("PyPI Releases", "https://pypi.org/project/click/"),
ProjectLink("Source Code", "https://github.com/pallets/click/"),
ProjectLink("Issue Tracker", "https://github.com/pallets/click/issues/"),
ProjectLink("Website", "https://palletsprojects.com/p/click"),
ProjectLink("Twitter", "https://twitter.com/PalletsTeam"),
ProjectLink("Chat", "https://discord.gg/pallets"),
]
}
html_sidebars = {
"index": ["project.html", "localtoc.html", "searchbox.html", "ethicalads.html"],
"**": ["localtoc.html", "relations.html", "searchbox.html", "ethicalads.html"],
}
singlehtml_sidebars = {"index": ["project.html", "localtoc.html", "ethicalads.html"]}
html_static_path = ["_static"]
html_favicon = "_static/click-icon.png"
html_logo = "_static/click-logo-sidebar.png"
html_title = f"Click Documentation ({version})"
html_show_sourcelink = False
# LaTeX ----------------------------------------------------------------
latex_documents = [(master_doc, f"Click-{version}.tex", html_title, author, "manual")]

View file

@ -1,25 +0,0 @@
.. _contrib:
=============
click-contrib
=============
As the userbase of Click grows, more and more major feature requests pop up in
Click's bugtracker. As reasonable as it may be for those features to be bundled
with Click instead of being a standalone project, many of those requested
features are either highly experimental or have unproven practical use, while
potentially being a burden to maintain.
This is why click-contrib_ exists. The GitHub organization is a collection of
possibly experimental third-party packages whose featureset does not belong
into Click, but also a playground for major features that may be added to Click
in the future. It is also meant to coordinate and concentrate effort on writing
third-party extensions for Click, and to ease the effort of searching for such
extensions. In that sense it could be described as a low-maintenance
alternative to extension repositories of other frameworks.
Please note that the quality and stability of those packages may be different
than what you expect from Click itself. While published under a common
organization, they are still projects separate from Click.
.. _click-contrib: https://github.com/click-contrib/

View file

@ -1,241 +0,0 @@
Documenting Scripts
===================
.. currentmodule:: click
Click makes it very easy to document your command line tools. First of
all, it automatically generates help pages for you. While these are
currently not customizable in terms of their layout, all of the text
can be changed.
Help Texts
----------
Commands and options accept help arguments. In the case of commands, the
docstring of the function is automatically used if provided.
Simple example:
.. click:example::
@click.command()
@click.option('--count', default=1, help='number of greetings')
@click.argument('name')
def hello(count, name):
"""This script prints hello NAME COUNT times."""
for x in range(count):
click.echo(f"Hello {name}!")
And what it looks like:
.. click:run::
invoke(hello, args=['--help'])
.. _documenting-arguments:
Documenting Arguments
~~~~~~~~~~~~~~~~~~~~~
:func:`click.argument` does not take a ``help`` parameter. This is to
follow the general convention of Unix tools of using arguments for only
the most necessary things, and to document them in the command help text
by referring to them by name.
You might prefer to reference the argument in the description:
.. click:example::
@click.command()
@click.argument('filename')
def touch(filename):
"""Print FILENAME."""
click.echo(filename)
And what it looks like:
.. click:run::
invoke(touch, args=['--help'])
Or you might prefer to explicitly provide a description of the argument:
.. click:example::
@click.command()
@click.argument('filename')
def touch(filename):
"""Print FILENAME.
FILENAME is the name of the file to check.
"""
click.echo(filename)
And what it looks like:
.. click:run::
invoke(touch, args=['--help'])
For more examples, see the examples in :doc:`/arguments`.
Preventing Rewrapping
---------------------
The default behavior of Click is to rewrap text based on the width of the
terminal. In some circumstances, this can become a problem. The main issue
is when showing code examples, where newlines are significant.
Rewrapping can be disabled on a per-paragraph basis by adding a line with
solely the ``\b`` escape marker in it. This line will be removed from the
help text and rewrapping will be disabled.
Example:
.. click:example::
@click.command()
def cli():
"""First paragraph.
This is a very long second paragraph and as you
can see wrapped very early in the source text
but will be rewrapped to the terminal width in
the final output.
\b
This is
a paragraph
without rewrapping.
And this is a paragraph
that will be rewrapped again.
"""
And what it looks like:
.. click:run::
invoke(cli, args=['--help'])
.. _doc-meta-variables:
Truncating Help Texts
---------------------
Click gets command help text from function docstrings. However if you
already use docstrings to document function arguments you may not want
to see :param: and :return: lines in your help text.
You can use the ``\f`` escape marker to have Click truncate the help text
after the marker.
Example:
.. click:example::
@click.command()
@click.pass_context
def cli(ctx):
"""First paragraph.
This is a very long second
paragraph and not correctly
wrapped but it will be rewrapped.
\f
:param click.core.Context ctx: Click context.
"""
And what it looks like:
.. click:run::
invoke(cli, args=['--help'])
Meta Variables
--------------
Options and parameters accept a ``metavar`` argument that can change the
meta variable in the help page. The default version is the parameter name
in uppercase with underscores, but can be annotated differently if
desired. This can be customized at all levels:
.. click:example::
@click.command(options_metavar='<options>')
@click.option('--count', default=1, help='number of greetings',
metavar='<int>')
@click.argument('name', metavar='<name>')
def hello(count, name):
"""This script prints hello <name> <int> times."""
for x in range(count):
click.echo(f"Hello {name}!")
Example:
.. click:run::
invoke(hello, args=['--help'])
Command Short Help
------------------
For commands, a short help snippet is generated. By default, it's the first
sentence of the help message of the command, unless it's too long. This can
also be overridden:
.. click:example::
@click.group()
def cli():
"""A simple command line tool."""
@cli.command('init', short_help='init the repo')
def init():
"""Initializes the repository."""
@cli.command('delete', short_help='delete the repo')
def delete():
"""Deletes the repository."""
And what it looks like:
.. click:run::
invoke(cli, prog_name='repo.py')
Help Parameter Customization
----------------------------
.. versionadded:: 2.0
The help parameter is implemented in Click in a very special manner.
Unlike regular parameters it's automatically added by Click for any
command and it performs automatic conflict resolution. By default it's
called ``--help``, but this can be changed. If a command itself implements
a parameter with the same name, the default help parameter stops accepting
it. There is a context setting that can be used to override the names of
the help parameters called :attr:`~Context.help_option_names`.
This example changes the default parameters to ``-h`` and ``--help``
instead of just ``--help``:
.. click:example::
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
@click.command(context_settings=CONTEXT_SETTINGS)
def cli():
pass
And what it looks like:
.. click:run::
invoke(cli, ['-h'])

View file

@ -1,73 +0,0 @@
Exception Handling
==================
.. currentmodule:: click
Click internally uses exceptions to signal various error conditions that
the user of the application might have caused. Primarily this is things
like incorrect usage.
Where are Errors Handled?
-------------------------
Click's main error handling is happening in :meth:`BaseCommand.main`. In
there it handles all subclasses of :exc:`ClickException` as well as the
standard :exc:`EOFError` and :exc:`KeyboardInterrupt` exceptions. The
latter are internally translated into a :exc:`Abort`.
The logic applied is the following:
1. If an :exc:`EOFError` or :exc:`KeyboardInterrupt` happens, reraise it
as :exc:`Abort`.
2. If an :exc:`ClickException` is raised, invoke the
:meth:`ClickException.show` method on it to display it and then exit
the program with :attr:`ClickException.exit_code`.
3. If an :exc:`Abort` exception is raised print the string ``Aborted!``
to standard error and exit the program with exit code ``1``.
4. if it goes through well, exit the program with exit code ``0``.
What if I don't want that?
--------------------------
Generally you always have the option to invoke the :meth:`invoke` method
yourself. For instance if you have a :class:`Command` you can invoke it
manually like this::
ctx = command.make_context('command-name', ['args', 'go', 'here'])
with ctx:
result = command.invoke(ctx)
In this case exceptions will not be handled at all and bubbled up as you
would expect.
Starting with Click 3.0 you can also use the :meth:`Command.main` method
but disable the standalone mode which will do two things: disable
exception handling and disable the implicit :meth:`sys.exit` at the end.
So you can do something like this::
command.main(['command-name', 'args', 'go', 'here'],
standalone_mode=False)
Which Exceptions Exist?
-----------------------
Click has two exception bases: :exc:`ClickException` which is raised for
all exceptions that Click wants to signal to the user and :exc:`Abort`
which is used to instruct Click to abort the execution.
A :exc:`ClickException` has a :meth:`~ClickException.show` method which
can render an error message to stderr or the given file object. If you
want to use the exception yourself for doing something check the API docs
about what else they provide.
The following common subclasses exist:
* :exc:`UsageError` to inform the user that something went wrong.
* :exc:`BadParameter` to inform the user that something went wrong with
a specific parameter. These are often handled internally in Click and
augmented with extra information if possible. For instance if those
are raised from a callback Click will automatically augment it with
the parameter name if possible.
* :exc:`FileError` this is an error that is raised by the
:exc:`FileType` if Click encounters issues opening the file.

View file

@ -1,107 +0,0 @@
.. rst-class:: hide-header
Welcome to Click
================
.. image:: _static/click-logo.png
:align: center
:scale: 50%
:target: https://palletsprojects.com/p/click/
Click is a Python package for creating beautiful command line interfaces
in a composable way with as little code as necessary. It's the "Command
Line Interface Creation Kit". It's highly configurable but comes with
sensible defaults out of the box.
It aims to make the process of writing command line tools quick and fun
while also preventing any frustration caused by the inability to implement
an intended CLI API.
Click in three points:
- arbitrary nesting of commands
- automatic help page generation
- supports lazy loading of subcommands at runtime
What does it look like? Here is an example of a simple Click program:
.. click:example::
import click
@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
help='The person to greet.')
def hello(count, name):
"""Simple program that greets NAME for a total of COUNT times."""
for x in range(count):
click.echo(f"Hello {name}!")
if __name__ == '__main__':
hello()
And what it looks like when run:
.. click:run::
invoke(hello, ['--count=3'], prog_name='python hello.py', input='John\n')
It automatically generates nicely formatted help pages:
.. click:run::
invoke(hello, ['--help'], prog_name='python hello.py')
You can get the library directly from PyPI::
pip install click
Documentation
-------------
This part of the documentation guides you through all of the library's
usage patterns.
.. toctree::
:maxdepth: 2
why
quickstart
setuptools
parameters
options
arguments
commands
prompts
documentation
complex
advanced
testing
utils
shell-completion
exceptions
unicode-support
wincmd
API Reference
-------------
If you are looking for information on a specific function, class, or
method, this part of the documentation is for you.
.. toctree::
:maxdepth: 2
api
Miscellaneous Pages
-------------------
.. toctree::
:maxdepth: 2
contrib
upgrading
license
changes

View file

@ -1,4 +0,0 @@
BSD-3-Clause License
====================
.. include:: ../LICENSE.rst

View file

@ -1,36 +0,0 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=Jinja
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

View file

@ -1,935 +0,0 @@
.. _options:
Options
=======
.. currentmodule:: click
Adding options to commands can be accomplished by the :func:`option`
decorator. Since options can come in various different versions, there
are a ton of parameters to configure their behavior. Options in click are
distinct from :ref:`positional arguments <arguments>`.
Name Your Options
-----------------
Options have a name that will be used as the Python argument name when
calling the decorated function. This can be inferred from the option
names or given explicitly. Names are given as position arguments to the
decorator.
A name is chosen in the following order
1. If a name is not prefixed, it is used as the Python argument name
and not treated as an option name on the command line.
2. If there is at least one name prefixed with two dashes, the first
one given is used as the name.
3. The first name prefixed with one dash is used otherwise.
To get the Python argument name, the chosen name is converted to lower
case, up to two dashes are removed as the prefix, and other dashes are
converted to underscores.
.. code-block:: python
@click.command()
@click.option('-s', '--string-to-echo')
def echo(string_to_echo):
click.echo(string_to_echo)
.. code-block:: python
@click.command()
@click.option('-s', '--string-to-echo', 'string')
def echo(string):
click.echo(string)
- ``"-f", "--foo-bar"``, the name is ``foo_bar``
- ``"-x"``, the name is ``x``
- ``"-f", "--filename", "dest"``, the name is ``dest``
- ``"--CamelCase"``, the name is ``camelcase``
- ``"-f", "-fb"``, the name is ``f``
- ``"--f", "--foo-bar"``, the name is ``f``
- ``"---f"``, the name is ``_f``
Basic Value Options
-------------------
The most basic option is a value option. These options accept one
argument which is a value. If no type is provided, the type of the default
value is used. If no default value is provided, the type is assumed to be
:data:`STRING`. Unless a name is explicitly specified, the name of the
parameter is the first long option defined; otherwise the first short one is
used. By default, options are not required, however to make an option required,
simply pass in `required=True` as an argument to the decorator.
.. click:example::
@click.command()
@click.option('--n', default=1)
def dots(n):
click.echo('.' * n)
.. click:example::
# How to make an option required
@click.command()
@click.option('--n', required=True, type=int)
def dots(n):
click.echo('.' * n)
.. click:example::
# How to use a Python reserved word such as `from` as a parameter
@click.command()
@click.option('--from', '-f', 'from_')
@click.option('--to', '-t')
def reserved_param_name(from_, to):
click.echo(f"from {from_} to {to}")
And on the command line:
.. click:run::
invoke(dots, args=['--n=2'])
In this case the option is of type :data:`INT` because the default value
is an integer.
To show the default values when showing command help, use ``show_default=True``
.. click:example::
@click.command()
@click.option('--n', default=1, show_default=True)
def dots(n):
click.echo('.' * n)
.. click:run::
invoke(dots, args=['--help'])
For single option boolean flags, the default remains hidden if the default
value is False.
.. click:example::
@click.command()
@click.option('--n', default=1, show_default=True)
@click.option("--gr", is_flag=True, show_default=True, default=False, help="Greet the world.")
@click.option("--br", is_flag=True, show_default=True, default=True, help="Add a thematic break")
def dots(n, gr, br):
if gr:
click.echo('Hello world!')
click.echo('.' * n)
if br:
click.echo('-' * n)
.. click:run::
invoke(dots, args=['--help'])
Multi Value Options
-------------------
Sometimes, you have options that take more than one argument. For options,
only a fixed number of arguments is supported. This can be configured by
the ``nargs`` parameter. The values are then stored as a tuple.
.. click:example::
@click.command()
@click.option('--pos', nargs=2, type=float)
def findme(pos):
a, b = pos
click.echo(f"{a} / {b}")
And on the command line:
.. click:run::
invoke(findme, args=['--pos', '2.0', '3.0'])
.. _tuple-type:
Tuples as Multi Value Options
-----------------------------
.. versionadded:: 4.0
As you can see that by using `nargs` set to a specific number each item in
the resulting tuple is of the same type. This might not be what you want.
Commonly you might want to use different types for different indexes in
the tuple. For this you can directly specify a tuple as type:
.. click:example::
@click.command()
@click.option('--item', type=(str, int))
def putitem(item):
name, id = item
click.echo(f"name={name} id={id}")
And on the command line:
.. click:run::
invoke(putitem, args=['--item', 'peter', '1338'])
By using a tuple literal as type, `nargs` gets automatically set to the
length of the tuple and the :class:`click.Tuple` type is automatically
used. The above example is thus equivalent to this:
.. click:example::
@click.command()
@click.option('--item', nargs=2, type=click.Tuple([str, int]))
def putitem(item):
name, id = item
click.echo(f"name={name} id={id}")
.. _multiple-options:
Multiple Options
----------------
Similarly to ``nargs``, there is also the case of wanting to support a
parameter being provided multiple times and have all the values recorded --
not just the last one. For instance, ``git commit -m foo -m bar`` would
record two lines for the commit message: ``foo`` and ``bar``. This can be
accomplished with the ``multiple`` flag:
Example:
.. click:example::
@click.command()
@click.option('--message', '-m', multiple=True)
def commit(message):
click.echo('\n'.join(message))
And on the command line:
.. click:run::
invoke(commit, args=['-m', 'foo', '-m', 'bar'])
When passing a ``default`` with ``multiple=True``, the default value
must be a list or tuple, otherwise it will be interpreted as a list of
single characters.
.. code-block:: python
@click.option("--format", multiple=True, default=["json"])
Counting
--------
In some very rare circumstances, it is interesting to use the repetition
of options to count an integer up. This can be used for verbosity flags,
for instance:
.. click:example::
@click.command()
@click.option('-v', '--verbose', count=True)
def log(verbose):
click.echo(f"Verbosity: {verbose}")
And on the command line:
.. click:run::
invoke(log, args=['-vvv'])
Boolean Flags
-------------
Boolean flags are options that can be enabled or disabled. This can be
accomplished by defining two flags in one go separated by a slash (``/``)
for enabling or disabling the option. (If a slash is in an option string,
Click automatically knows that it's a boolean flag and will pass
``is_flag=True`` implicitly.) Click always wants you to provide an enable
and disable flag so that you can change the default later.
Example:
.. click:example::
import sys
@click.command()
@click.option('--shout/--no-shout', default=False)
def info(shout):
rv = sys.platform
if shout:
rv = rv.upper() + '!!!!111'
click.echo(rv)
And on the command line:
.. click:run::
invoke(info, args=['--shout'])
invoke(info, args=['--no-shout'])
invoke(info)
If you really don't want an off-switch, you can just define one and
manually inform Click that something is a flag:
.. click:example::
import sys
@click.command()
@click.option('--shout', is_flag=True)
def info(shout):
rv = sys.platform
if shout:
rv = rv.upper() + '!!!!111'
click.echo(rv)
And on the command line:
.. click:run::
invoke(info, args=['--shout'])
invoke(info)
Note that if a slash is contained in your option already (for instance, if
you use Windows-style parameters where ``/`` is the prefix character), you
can alternatively split the parameters through ``;`` instead:
.. click:example::
@click.command()
@click.option('/debug;/no-debug')
def log(debug):
click.echo(f"debug={debug}")
if __name__ == '__main__':
log()
.. versionchanged:: 6.0
If you want to define an alias for the second option only, then you will
need to use leading whitespace to disambiguate the format string:
Example:
.. click:example::
import sys
@click.command()
@click.option('--shout/--no-shout', ' /-S', default=False)
def info(shout):
rv = sys.platform
if shout:
rv = rv.upper() + '!!!!111'
click.echo(rv)
.. click:run::
invoke(info, args=['--help'])
Feature Switches
----------------
In addition to boolean flags, there are also feature switches. These are
implemented by setting multiple options to the same parameter name and
defining a flag value. Note that by providing the ``flag_value`` parameter,
Click will implicitly set ``is_flag=True``.
To set a default flag, assign a value of `True` to the flag that should be
the default.
.. click:example::
import sys
@click.command()
@click.option('--upper', 'transformation', flag_value='upper',
default=True)
@click.option('--lower', 'transformation', flag_value='lower')
def info(transformation):
click.echo(getattr(sys.platform, transformation)())
And on the command line:
.. click:run::
invoke(info, args=['--upper'])
invoke(info, args=['--lower'])
invoke(info)
.. _choice-opts:
Choice Options
--------------
Sometimes, you want to have a parameter be a choice of a list of values.
In that case you can use :class:`Choice` type. It can be instantiated
with a list of valid values. The originally passed choice will be returned,
not the str passed on the command line. Token normalization functions and
``case_sensitive=False`` can cause the two to be different but still match.
Example:
.. click:example::
@click.command()
@click.option('--hash-type',
type=click.Choice(['MD5', 'SHA1'], case_sensitive=False))
def digest(hash_type):
click.echo(hash_type)
What it looks like:
.. click:run::
invoke(digest, args=['--hash-type=MD5'])
println()
invoke(digest, args=['--hash-type=md5'])
println()
invoke(digest, args=['--hash-type=foo'])
println()
invoke(digest, args=['--help'])
Only pass the choices as list or tuple. Other iterables (like
generators) may lead to unexpected results.
Choices work with options that have ``multiple=True``. If a ``default``
value is given with ``multiple=True``, it should be a list or tuple of
valid choices.
Choices should be unique after considering the effects of
``case_sensitive`` and any specified token normalization function.
.. versionchanged:: 7.1
The resulting value from an option will always be one of the
originally passed choices regardless of ``case_sensitive``.
.. _option-prompting:
Prompting
---------
In some cases, you want parameters that can be provided from the command line,
but if not provided, ask for user input instead. This can be implemented with
Click by defining a prompt string.
Example:
.. click:example::
@click.command()
@click.option('--name', prompt=True)
def hello(name):
click.echo(f"Hello {name}!")
And what it looks like:
.. click:run::
invoke(hello, args=['--name=John'])
invoke(hello, input=['John'])
If you are not happy with the default prompt string, you can ask for
a different one:
.. click:example::
@click.command()
@click.option('--name', prompt='Your name please')
def hello(name):
click.echo(f"Hello {name}!")
What it looks like:
.. click:run::
invoke(hello, input=['John'])
It is advised that prompt not be used in conjunction with the multiple
flag set to True. Instead, prompt in the function interactively.
By default, the user will be prompted for an input if one was not passed
through the command line. To turn this behavior off, see
:ref:`optional-value`.
Password Prompts
----------------
Click also supports hidden prompts and asking for confirmation. This is
useful for password input:
.. click:example::
import codecs
@click.command()
@click.option(
"--password", prompt=True, hide_input=True,
confirmation_prompt=True
)
def encode(password):
click.echo(f"encoded: {codecs.encode(password, 'rot13')}")
.. click:run::
invoke(encode, input=['secret', 'secret'])
Because this combination of parameters is quite common, this can also be
replaced with the :func:`password_option` decorator:
.. code-block:: python
@click.command()
@click.password_option()
def encrypt(password):
click.echo(f"encoded: to {codecs.encode(password, 'rot13')}")
Dynamic Defaults for Prompts
----------------------------
The ``auto_envvar_prefix`` and ``default_map`` options for the context
allow the program to read option values from the environment or a
configuration file. However, this overrides the prompting mechanism, so
that the user does not get the option to change the value interactively.
If you want to let the user configure the default value, but still be
prompted if the option isn't specified on the command line, you can do so
by supplying a callable as the default value. For example, to get a default
from the environment:
.. code-block:: python
import os
@click.command()
@click.option(
"--username", prompt=True,
default=lambda: os.environ.get("USER", "")
)
def hello(username):
click.echo(f"Hello, {username}!")
To describe what the default value will be, set it in ``show_default``.
.. click:example::
import os
@click.command()
@click.option(
"--username", prompt=True,
default=lambda: os.environ.get("USER", ""),
show_default="current user"
)
def hello(username):
click.echo(f"Hello, {username}!")
.. click:run::
invoke(hello, args=["--help"])
Callbacks and Eager Options
---------------------------
Sometimes, you want a parameter to completely change the execution flow.
For instance, this is the case when you want to have a ``--version``
parameter that prints out the version and then exits the application.
Note: an actual implementation of a ``--version`` parameter that is
reusable is available in Click as :func:`click.version_option`. The code
here is merely an example of how to implement such a flag.
In such cases, you need two concepts: eager parameters and a callback. An
eager parameter is a parameter that is handled before others, and a
callback is what executes after the parameter is handled. The eagerness
is necessary so that an earlier required parameter does not produce an
error message. For instance, if ``--version`` was not eager and a
parameter ``--foo`` was required and defined before, you would need to
specify it for ``--version`` to work. For more information, see
:ref:`callback-evaluation-order`.
A callback is a function that is invoked with three parameters: the
current :class:`Context`, the current :class:`Parameter`, and the value.
The context provides some useful features such as quitting the
application and gives access to other already processed parameters.
Here an example for a ``--version`` flag:
.. click:example::
def print_version(ctx, param, value):
if not value or ctx.resilient_parsing:
return
click.echo('Version 1.0')
ctx.exit()
@click.command()
@click.option('--version', is_flag=True, callback=print_version,
expose_value=False, is_eager=True)
def hello():
click.echo('Hello World!')
The `expose_value` parameter prevents the pretty pointless ``version``
parameter from being passed to the callback. If that was not specified, a
boolean would be passed to the `hello` script. The `resilient_parsing`
flag is applied to the context if Click wants to parse the command line
without any destructive behavior that would change the execution flow. In
this case, because we would exit the program, we instead do nothing.
What it looks like:
.. click:run::
invoke(hello)
invoke(hello, args=['--version'])
.. admonition:: Callback Signature Changes
In Click 2.0 the signature for callbacks changed. For more
information about these changes see :ref:`upgrade-to-2.0`.
Yes Parameters
--------------
For dangerous operations, it's very useful to be able to ask a user for
confirmation. This can be done by adding a boolean ``--yes`` flag and
asking for confirmation if the user did not provide it and to fail in a
callback:
.. click:example::
def abort_if_false(ctx, param, value):
if not value:
ctx.abort()
@click.command()
@click.option('--yes', is_flag=True, callback=abort_if_false,
expose_value=False,
prompt='Are you sure you want to drop the db?')
def dropdb():
click.echo('Dropped all tables!')
And what it looks like on the command line:
.. click:run::
invoke(dropdb, input=['n'])
invoke(dropdb, args=['--yes'])
Because this combination of parameters is quite common, this can also be
replaced with the :func:`confirmation_option` decorator:
.. click:example::
@click.command()
@click.confirmation_option(prompt='Are you sure you want to drop the db?')
def dropdb():
click.echo('Dropped all tables!')
.. admonition:: Callback Signature Changes
In Click 2.0 the signature for callbacks changed. For more
information about these changes see :ref:`upgrade-to-2.0`.
Values from Environment Variables
---------------------------------
A very useful feature of Click is the ability to accept parameters from
environment variables in addition to regular parameters. This allows
tools to be automated much easier. For instance, you might want to pass
a configuration file with a ``--config`` parameter but also support exporting
a ``TOOL_CONFIG=hello.cfg`` key-value pair for a nicer development
experience.
This is supported by Click in two ways. One is to automatically build
environment variables which is supported for options only. To enable this
feature, the ``auto_envvar_prefix`` parameter needs to be passed to the
script that is invoked. Each command and parameter is then added as an
uppercase underscore-separated variable. If you have a subcommand
called ``run`` taking an option called ``reload`` and the prefix is
``WEB``, then the variable is ``WEB_RUN_RELOAD``.
Example usage:
.. click:example::
@click.command()
@click.option('--username')
def greet(username):
click.echo(f'Hello {username}!')
if __name__ == '__main__':
greet(auto_envvar_prefix='GREETER')
And from the command line:
.. click:run::
invoke(greet, env={'GREETER_USERNAME': 'john'},
auto_envvar_prefix='GREETER')
When using ``auto_envvar_prefix`` with command groups, the command name
needs to be included in the environment variable, between the prefix and
the parameter name, *i.e.* ``PREFIX_COMMAND_VARIABLE``. If you have a
subcommand called ``run-server`` taking an option called ``host`` and
the prefix is ``WEB``, then the variable is ``WEB_RUN_SERVER_HOST``.
Example:
.. click:example::
@click.group()
@click.option('--debug/--no-debug')
def cli(debug):
click.echo(f"Debug mode is {'on' if debug else 'off'}")
@cli.command()
@click.option('--username')
def greet(username):
click.echo(f"Hello {username}!")
if __name__ == '__main__':
cli(auto_envvar_prefix='GREETER')
.. click:run::
invoke(cli, args=['greet',],
env={'GREETER_GREET_USERNAME': 'John', 'GREETER_DEBUG': 'false'},
auto_envvar_prefix='GREETER')
The second option is to manually pull values in from specific environment
variables by defining the name of the environment variable on the option.
Example usage:
.. click:example::
@click.command()
@click.option('--username', envvar='USERNAME')
def greet(username):
click.echo(f"Hello {username}!")
if __name__ == '__main__':
greet()
And from the command line:
.. click:run::
invoke(greet, env={'USERNAME': 'john'})
In that case it can also be a list of different environment variables
where the first one is picked.
Multiple Values from Environment Values
---------------------------------------
As options can accept multiple values, pulling in such values from
environment variables (which are strings) is a bit more complex. The way
Click solves this is by leaving it up to the type to customize this
behavior. For both ``multiple`` and ``nargs`` with values other than
``1``, Click will invoke the :meth:`ParamType.split_envvar_value` method to
perform the splitting.
The default implementation for all types is to split on whitespace. The
exceptions to this rule are the :class:`File` and :class:`Path` types
which both split according to the operating system's path splitting rules.
On Unix systems like Linux and OS X, the splitting happens for those on
every colon (``:``), and for Windows, on every semicolon (``;``).
Example usage:
.. click:example::
@click.command()
@click.option('paths', '--path', envvar='PATHS', multiple=True,
type=click.Path())
def perform(paths):
for path in paths:
click.echo(path)
if __name__ == '__main__':
perform()
And from the command line:
.. click:run::
import os
invoke(perform, env={"PATHS": f"./foo/bar{os.path.pathsep}./test"})
Other Prefix Characters
-----------------------
Click can deal with alternative prefix characters other than ``-`` for
options. This is for instance useful if you want to handle slashes as
parameters ``/`` or something similar. Note that this is strongly
discouraged in general because Click wants developers to stay close to
POSIX semantics. However in certain situations this can be useful:
.. click:example::
@click.command()
@click.option('+w/-w')
def chmod(w):
click.echo(f"writable={w}")
if __name__ == '__main__':
chmod()
And from the command line:
.. click:run::
invoke(chmod, args=['+w'])
invoke(chmod, args=['-w'])
Note that if you are using ``/`` as prefix character and you want to use a
boolean flag you need to separate it with ``;`` instead of ``/``:
.. click:example::
@click.command()
@click.option('/debug;/no-debug')
def log(debug):
click.echo(f"debug={debug}")
if __name__ == '__main__':
log()
.. _ranges:
Range Options
-------------
The :class:`IntRange` type extends the :data:`INT` type to ensure the
value is contained in the given range. The :class:`FloatRange` type does
the same for :data:`FLOAT`.
If ``min`` or ``max`` is omitted, that side is *unbounded*. Any value in
that direction is accepted. By default, both bounds are *closed*, which
means the boundary value is included in the accepted range. ``min_open``
and ``max_open`` can be used to exclude that boundary from the range.
If ``clamp`` mode is enabled, a value that is outside the range is set
to the boundary instead of failing. For example, the range ``0, 5``
would return ``5`` for the value ``10``, or ``0`` for the value ``-1``.
When using :class:`FloatRange`, ``clamp`` can only be enabled if both
bounds are *closed* (the default).
.. click:example::
@click.command()
@click.option("--count", type=click.IntRange(0, 20, clamp=True))
@click.option("--digit", type=click.IntRange(0, 9))
def repeat(count, digit):
click.echo(str(digit) * count)
.. click:run::
invoke(repeat, args=['--count=100', '--digit=5'])
invoke(repeat, args=['--count=6', '--digit=12'])
Callbacks for Validation
------------------------
.. versionchanged:: 2.0
If you want to apply custom validation logic, you can do this in the
parameter callbacks. These callbacks can both modify values as well as
raise errors if the validation does not work. The callback runs after
type conversion. It is called for all sources, including prompts.
In Click 1.0, you can only raise the :exc:`UsageError` but starting with
Click 2.0, you can also raise the :exc:`BadParameter` error, which has the
added advantage that it will automatically format the error message to
also contain the parameter name.
.. click:example::
def validate_rolls(ctx, param, value):
if isinstance(value, tuple):
return value
try:
rolls, _, dice = value.partition("d")
return int(dice), int(rolls)
except ValueError:
raise click.BadParameter("format must be 'NdM'")
@click.command()
@click.option(
"--rolls", type=click.UNPROCESSED, callback=validate_rolls,
default="1d6", prompt=True,
)
def roll(rolls):
sides, times = rolls
click.echo(f"Rolling a {sides}-sided dice {times} time(s)")
.. click:run::
invoke(roll, args=["--rolls=42"])
println()
invoke(roll, args=["--rolls=2d12"])
println()
invoke(roll, input=["42", "2d12"])
.. _optional-value:
Optional Value
--------------
Providing the value to an option can be made optional, in which case
providing only the option's flag without a value will either show a
prompt or use its ``flag_value``.
Setting ``is_flag=False, flag_value=value`` tells Click that the option
can still be passed a value, but if only the flag is given the
``flag_value`` is used.
.. click:example::
@click.command()
@click.option("--name", is_flag=False, flag_value="Flag", default="Default")
def hello(name):
click.echo(f"Hello, {name}!")
.. click:run::
invoke(hello, args=[])
invoke(hello, args=["--name", "Value"])
invoke(hello, args=["--name"])
If the option has ``prompt`` enabled, then setting
``prompt_required=False`` tells Click to only show the prompt if the
option's flag is given, instead of if the option is not provided at all.
.. click:example::
@click.command()
@click.option('--name', prompt=True, prompt_required=False, default="Default")
def hello(name):
click.echo(f"Hello {name}!")
.. click:run::
invoke(hello)
invoke(hello, args=["--name", "Value"])
invoke(hello, args=["--name"], input="Prompt")
If ``required=True``, then the option will still prompt if it is not
given, but it will also prompt if only the flag is given.

View file

@ -1,143 +0,0 @@
Parameters
==========
.. currentmodule:: click
Click supports two types of parameters for scripts: options and arguments.
There is generally some confusion among authors of command line scripts of
when to use which, so here is a quick overview of the differences. As its
name indicates, an option is optional. While arguments can be optional
within reason, they are much more restricted in how optional they can be.
To help you decide between options and arguments, the recommendation is
to use arguments exclusively for things like going to subcommands or input
filenames / URLs, and have everything else be an option instead.
Differences
-----------
Arguments can do less than options. The following features are only
available for options:
* automatic prompting for missing input
* act as flags (boolean or otherwise)
* option values can be pulled from environment variables, arguments can not
* options are fully documented in the help page, arguments are not
(:ref:`this is intentional <documenting-arguments>` as arguments
might be too specific to be automatically documented)
On the other hand arguments, unlike options, can accept an arbitrary number
of arguments. Options can strictly ever only accept a fixed number of
arguments (defaults to 1), or they may be specified multiple times using
:ref:`multiple-options`.
Parameter Types
---------------
Parameters can be of different types. Types can be implemented with
different behavior and some are supported out of the box:
``str`` / :data:`click.STRING`:
The default parameter type which indicates unicode strings.
``int`` / :data:`click.INT`:
A parameter that only accepts integers.
``float`` / :data:`click.FLOAT`:
A parameter that only accepts floating point values.
``bool`` / :data:`click.BOOL`:
A parameter that accepts boolean values. This is automatically used
for boolean flags. The string values "1", "true", "t", "yes", "y",
and "on" convert to ``True``. "0", "false", "f", "no", "n", and
"off" convert to ``False``.
:data:`click.UUID`:
A parameter that accepts UUID values. This is not automatically
guessed but represented as :class:`uuid.UUID`.
.. autoclass:: File
:noindex:
.. autoclass:: Path
:noindex:
.. autoclass:: Choice
:noindex:
.. autoclass:: IntRange
:noindex:
.. autoclass:: FloatRange
:noindex:
.. autoclass:: DateTime
:noindex:
Custom parameter types can be implemented by subclassing
:class:`click.ParamType`. For simple cases, passing a Python function that
fails with a `ValueError` is also supported, though discouraged.
.. _parameter_names:
Parameter Names
---------------
Parameters (both options and arguments) have a name that will be used as
the Python argument name when calling the decorated function with
values.
Arguments take only one positional name. To provide a different name for
use in help text, see :ref:`doc-meta-variables`.
Options can have many names that may be prefixed with one or two dashes.
Names with one dash are parsed as short options, names with two are
parsed as long options. If a name is not prefixed, it is used as the
Python argument name and not parsed as an option name. Otherwise, the
first name with a two dash prefix is used, or the first with a one dash
prefix if there are none with two. The prefix is removed and dashes are
converted to underscores to get the Python argument name.
Implementing Custom Types
-------------------------
To implement a custom type, you need to subclass the :class:`ParamType`
class. Override the :meth:`~ParamType.convert` method to convert the
value from a string to the correct type.
The following code implements an integer type that accepts hex and octal
numbers in addition to normal integers, and converts them into regular
integers.
.. code-block:: python
import click
class BasedIntParamType(click.ParamType):
name = "integer"
def convert(self, value, param, ctx):
if isinstance(value, int):
return value
try:
if value[:2].lower() == "0x":
return int(value[2:], 16)
elif value[:1] == "0":
return int(value, 8)
return int(value, 10)
except ValueError:
self.fail(f"{value!r} is not a valid integer", param, ctx)
BASED_INT = BasedIntParamType()
The :attr:`~ParamType.name` attribute is optional and is used for
documentation. Call :meth:`~ParamType.fail` if conversion fails. The
``param`` and ``ctx`` arguments may be ``None`` in some cases such as
prompts.
Values from user input or the command line will be strings, but default
values and Python arguments may already be the correct type. The custom
type should check at the top if the value is already valid and pass it
through to support those cases.

View file

@ -1,48 +0,0 @@
User Input Prompts
==================
.. currentmodule:: click
Click supports prompts in two different places. The first is automated
prompts when the parameter handling happens, and the second is to ask for
prompts at a later point independently.
This can be accomplished with the :func:`prompt` function, which asks for
valid input according to a type, or the :func:`confirm` function, which asks
for confirmation (yes/no).
Option Prompts
--------------
Option prompts are integrated into the option interface. See
:ref:`option-prompting` for more information. Internally, it
automatically calls either :func:`prompt` or :func:`confirm` as necessary.
Input Prompts
-------------
To manually ask for user input, you can use the :func:`prompt` function.
By default, it accepts any Unicode string, but you can ask for any other
type. For instance, you can ask for a valid integer::
value = click.prompt('Please enter a valid integer', type=int)
Additionally, the type will be determined automatically if a default value is
provided. For instance, the following will only accept floats::
value = click.prompt('Please enter a number', default=42.0)
Confirmation Prompts
--------------------
To ask if a user wants to continue with an action, the :func:`confirm`
function comes in handy. By default, it returns the result of the prompt
as a boolean value::
if click.confirm('Do you want to continue?'):
click.echo('Well done!')
There is also the option to make the function automatically abort the
execution of the program if it does not return ``True``::
click.confirm('Do you want to continue?', abort=True)

View file

@ -1,299 +0,0 @@
Quickstart
==========
.. currentmodule:: click
You can get the library directly from PyPI::
pip install click
The installation into a :ref:`virtualenv` is heavily recommended.
.. _virtualenv:
virtualenv
----------
Virtualenv is probably what you want to use for developing Click
applications.
What problem does virtualenv solve? Chances are that you want to use it
for other projects besides your Click script. But the more projects you
have, the more likely it is that you will be working with different
versions of Python itself, or at least different versions of Python
libraries. Let's face it: quite often libraries break backwards
compatibility, and it's unlikely that any serious application will have
zero dependencies. So what do you do if two or more of your projects have
conflicting dependencies?
Virtualenv to the rescue! Virtualenv enables multiple side-by-side
installations of Python, one for each project. It doesn't actually
install separate copies of Python, but it does provide a clever way to
keep different project environments isolated. Let's see how virtualenv
works.
If you are on Mac OS X or Linux::
$ pip install virtualenv --user
One of these will probably install virtualenv on your system. Maybe it's even
in your package manager. If you use Ubuntu, try::
$ sudo apt-get install python-virtualenv
If you are on Windows (or none of the above methods worked) you must install
``pip`` first. For more information about this, see `installing pip`_.
Once you have it installed, run the ``pip`` command from above, but without
the `sudo` prefix.
.. _installing pip: https://pip.readthedocs.io/en/latest/installing/
Once you have virtualenv installed, just fire up a shell and create
your own environment. I usually create a project folder and a `venv`
folder within::
$ mkdir myproject
$ cd myproject
$ virtualenv venv
New python executable in venv/bin/python
Installing setuptools, pip............done.
Now, whenever you want to work on a project, you only have to activate the
corresponding environment. On OS X and Linux, do the following::
$ . venv/bin/activate
If you are a Windows user, the following command is for you::
$ venv\scripts\activate
Either way, you should now be using your virtualenv (notice how the prompt of
your shell has changed to show the active environment).
And if you want to go back to the real world, use the following command::
$ deactivate
After doing this, the prompt of your shell should be as familiar as before.
Now, let's move on. Enter the following command to get Click activated in your
virtualenv::
$ pip install click
A few seconds later and you are good to go.
Screencast and Examples
-----------------------
There is a screencast available which shows the basic API of Click and
how to build simple applications with it. It also explores how to build
commands with subcommands.
* `Building Command Line Applications with Click
<https://www.youtube.com/watch?v=kNke39OZ2k0>`_
Examples of Click applications can be found in the documentation as well
as in the GitHub repository together with readme files:
* ``inout``: `File input and output
<https://github.com/pallets/click/tree/main/examples/inout>`_
* ``naval``: `Port of docopt naval example
<https://github.com/pallets/click/tree/main/examples/naval>`_
* ``aliases``: `Command alias example
<https://github.com/pallets/click/tree/main/examples/aliases>`_
* ``repo``: `Git-/Mercurial-like command line interface
<https://github.com/pallets/click/tree/main/examples/repo>`_
* ``complex``: `Complex example with plugin loading
<https://github.com/pallets/click/tree/main/examples/complex>`_
* ``validation``: `Custom parameter validation example
<https://github.com/pallets/click/tree/main/examples/validation>`_
* ``colors``: `Color support demo
<https://github.com/pallets/click/tree/main/examples/colors>`_
* ``termui``: `Terminal UI functions demo
<https://github.com/pallets/click/tree/main/examples/termui>`_
* ``imagepipe``: `Multi command chaining demo
<https://github.com/pallets/click/tree/main/examples/imagepipe>`_
Basic Concepts - Creating a Command
-----------------------------------
Click is based on declaring commands through decorators. Internally, there
is a non-decorator interface for advanced use cases, but it's discouraged
for high-level usage.
A function becomes a Click command line tool by decorating it through
:func:`click.command`. At its simplest, just decorating a function
with this decorator will make it into a callable script:
.. click:example::
import click
@click.command()
def hello():
click.echo('Hello World!')
What's happening is that the decorator converts the function into a
:class:`Command` which then can be invoked::
if __name__ == '__main__':
hello()
And what it looks like:
.. click:run::
invoke(hello, args=[], prog_name='python hello.py')
And the corresponding help page:
.. click:run::
invoke(hello, args=['--help'], prog_name='python hello.py')
Echoing
-------
Why does this example use :func:`echo` instead of the regular
:func:`print` function? The answer to this question is that Click
attempts to support different environments consistently and to be very
robust even when the environment is misconfigured. Click wants to be
functional at least on a basic level even if everything is completely
broken.
What this means is that the :func:`echo` function applies some error
correction in case the terminal is misconfigured instead of dying with a
:exc:`UnicodeError`.
The echo function also supports color and other styles in output. It
will automatically remove styles if the output stream is a file. On
Windows, colorama is automatically installed and used. See
:ref:`ansi-colors`.
If you don't need this, you can also use the `print()` construct /
function.
Nesting Commands
----------------
Commands can be attached to other commands of type :class:`Group`. This
allows arbitrary nesting of scripts. As an example here is a script that
implements two commands for managing databases:
.. click:example::
@click.group()
def cli():
pass
@click.command()
def initdb():
click.echo('Initialized the database')
@click.command()
def dropdb():
click.echo('Dropped the database')
cli.add_command(initdb)
cli.add_command(dropdb)
As you can see, the :func:`group` decorator works like the :func:`command`
decorator, but creates a :class:`Group` object instead which can be given
multiple subcommands that can be attached with :meth:`Group.add_command`.
For simple scripts, it's also possible to automatically attach and create a
command by using the :meth:`Group.command` decorator instead. The above
script can instead be written like this:
.. click:example::
@click.group()
def cli():
pass
@cli.command()
def initdb():
click.echo('Initialized the database')
@cli.command()
def dropdb():
click.echo('Dropped the database')
You would then invoke the :class:`Group` in your setuptools entry points or
other invocations::
if __name__ == '__main__':
cli()
Registering Commands Later
--------------------------
Instead of using the ``@group.command()`` decorator, commands can be
decorated with the plain ``@click.command()`` decorator and registered
with a group later with ``group.add_command()``. This could be used to
split commands into multiple Python modules.
.. code-block:: python
@click.command()
def greet():
click.echo("Hello, World!")
.. code-block:: python
@click.group()
def group():
pass
group.add_command(greet)
Adding Parameters
-----------------
To add parameters, use the :func:`option` and :func:`argument` decorators:
.. click:example::
@click.command()
@click.option('--count', default=1, help='number of greetings')
@click.argument('name')
def hello(count, name):
for x in range(count):
click.echo(f"Hello {name}!")
What it looks like:
.. click:run::
invoke(hello, args=['--help'], prog_name='python hello.py')
.. _switching-to-setuptools:
Switching to Setuptools
-----------------------
In the code you wrote so far there is a block at the end of the file which
looks like this: ``if __name__ == '__main__':``. This is traditionally
how a standalone Python file looks like. With Click you can continue
doing that, but there are better ways through setuptools.
There are two main (and many more) reasons for this:
The first one is that setuptools automatically generates executable
wrappers for Windows so your command line utilities work on Windows too.
The second reason is that setuptools scripts work with virtualenv on Unix
without the virtualenv having to be activated. This is a very useful
concept which allows you to bundle your scripts with all requirements into
a virtualenv.
Click is perfectly equipped to work with that and in fact the rest of the
documentation will assume that you are writing applications through
setuptools.
I strongly recommend to have a look at the :ref:`setuptools-integration`
chapter before reading the rest as the examples assume that you will
be using setuptools.

View file

@ -1,153 +0,0 @@
.. _setuptools-integration:
Setuptools Integration
======================
When writing command line utilities, it's recommended to write them as
modules that are distributed with setuptools instead of using Unix
shebangs.
Why would you want to do that? There are a bunch of reasons:
1. One of the problems with the traditional approach is that the first
module the Python interpreter loads has an incorrect name. This might
sound like a small issue but it has quite significant implications.
The first module is not called by its actual name, but the
interpreter renames it to ``__main__``. While that is a perfectly
valid name it means that if another piece of code wants to import from
that module it will trigger the import a second time under its real
name and all of a sudden your code is imported twice.
2. Not on all platforms are things that easy to execute. On Linux and OS
X you can add a comment to the beginning of the file (``#!/usr/bin/env
python``) and your script works like an executable (assuming it has
the executable bit set). This however does not work on Windows.
While on Windows you can associate interpreters with file extensions
(like having everything ending in ``.py`` execute through the Python
interpreter) you will then run into issues if you want to use the
script in a virtualenv.
In fact running a script in a virtualenv is an issue with OS X and
Linux as well. With the traditional approach you need to have the
whole virtualenv activated so that the correct Python interpreter is
used. Not very user friendly.
3. The main trick only works if the script is a Python module. If your
application grows too large and you want to start using a package you
will run into issues.
Introduction
------------
To bundle your script with setuptools, all you need is the script in a
Python package and a ``setup.py`` file.
Imagine this directory structure:
.. code-block:: text
yourscript.py
setup.py
Contents of ``yourscript.py``:
.. click:example::
import click
@click.command()
def cli():
"""Example script."""
click.echo('Hello World!')
Contents of ``setup.py``:
.. code-block:: python
from setuptools import setup
setup(
name='yourscript',
version='0.1.0',
py_modules=['yourscript'],
install_requires=[
'Click',
],
entry_points={
'console_scripts': [
'yourscript = yourscript:cli',
],
},
)
The magic is in the ``entry_points`` parameter. Below
``console_scripts``, each line identifies one console script. The first
part before the equals sign (``=``) is the name of the script that should
be generated, the second part is the import path followed by a colon
(``:``) with the Click command.
That's it.
Testing The Script
------------------
To test the script, you can make a new virtualenv and then install your
package:
.. code-block:: console
$ virtualenv venv
$ . venv/bin/activate
$ pip install --editable .
Afterwards, your command should be available:
.. click:run::
invoke(cli, prog_name='yourscript')
Scripts in Packages
-------------------
If your script is growing and you want to switch over to your script being
contained in a Python package the changes necessary are minimal. Let's
assume your directory structure changed to this:
.. code-block:: text
project/
yourpackage/
__init__.py
main.py
utils.py
scripts/
__init__.py
yourscript.py
setup.py
In this case instead of using ``py_modules`` in your ``setup.py`` file you
can use ``packages`` and the automatic package finding support of
setuptools. In addition to that it's also recommended to include other
package data.
These would be the modified contents of ``setup.py``:
.. code-block:: python
from setuptools import setup, find_packages
setup(
name='yourpackage',
version='0.1.0',
packages=find_packages(),
include_package_data=True,
install_requires=[
'Click',
],
entry_points={
'console_scripts': [
'yourscript = yourpackage.scripts.yourscript:cli',
],
},
)

View file

@ -1,287 +0,0 @@
.. currentmodule:: click.shell_completion
Shell Completion
================
Click provides tab completion support for Bash (version 4.4 and up),
Zsh, and Fish. It is possible to add support for other shells too, and
suggestions can be customized at multiple levels.
Shell completion suggests command names, option names, and values for
choice, file, and path parameter types. Options are only listed if at
least a dash has been entered. Hidden commands and options are not
shown.
.. code-block:: text
$ repo <TAB><TAB>
clone commit copy delete setuser
$ repo clone -<TAB><TAB>
--deep --help --rev --shallow -r
Enabling Completion
-------------------
Completion is only available if a script is installed and invoked
through an entry point, not through the ``python`` command. See
:doc:`/setuptools`. Once the executable is installed, calling it with
a special environment variable will put Click in completion mode.
In order for completion to be used, the user needs to register a special
function with their shell. The script is different for every shell, and
Click will output it when called with ``_{PROG_NAME}_COMPLETE`` set to
``{shell}_source``. ``{PROG_NAME}`` is the executable name in uppercase
with dashes replaced by underscores. The built-in shells are ``bash``,
``zsh``, and ``fish``.
Provide your users with the following instructions customized to your
program name. This uses ``foo-bar`` as an example.
.. tabs::
.. group-tab:: Bash
Add this to ``~/.bashrc``:
.. code-block:: bash
eval "$(_FOO_BAR_COMPLETE=bash_source foo-bar)"
.. group-tab:: Zsh
Add this to ``~/.zshrc``:
.. code-block:: zsh
eval "$(_FOO_BAR_COMPLETE=zsh_source foo-bar)"
.. group-tab:: Fish
Add this to ``~/.config/fish/completions/foo-bar.fish``:
.. code-block:: fish
eval (env _FOO_BAR_COMPLETE=fish_source foo-bar)
This is the same file used for the activation script method
below. For Fish it's probably always easier to use that method.
Using ``eval`` means that the command is invoked and evaluated every
time a shell is started, which can delay shell responsiveness. To speed
it up, write the generated script to a file, then source that. You can
generate the files ahead of time and distribute them with your program
to save your users a step.
.. tabs::
.. group-tab:: Bash
Save the script somewhere.
.. code-block:: bash
_FOO_BAR_COMPLETE=bash_source foo-bar > ~/.foo-bar-complete.bash
Source the file in ``~/.bashrc``.
.. code-block:: bash
. ~/.foo-bar-complete.bash
.. group-tab:: Zsh
Save the script somewhere.
.. code-block:: bash
_FOO_BAR_COMPLETE=zsh_source foo-bar > ~/.foo-bar-complete.zsh
Source the file in ``~/.zshrc``.
.. code-block:: bash
. ~/.foo-bar-complete.zsh
.. group-tab:: Fish
Save the script to ``~/.config/fish/completions/foo-bar.fish``:
.. code-block:: fish
_FOO_BAR_COMPLETE=fish_source foo-bar > ~/.config/fish/completions/foo-bar.fish
After modifying the shell config, you need to start a new shell in order
for the changes to be loaded.
Custom Type Completion
----------------------
When creating a custom :class:`~click.ParamType`, override its
:meth:`~click.ParamType.shell_complete` method to provide shell
completion for parameters with the type. The method must return a list
of :class:`~CompletionItem` objects. Besides the value, these objects
hold metadata that shell support might use. The built-in implementations
use ``type`` to indicate special handling for paths, and ``help`` for
shells that support showing a help string next to a suggestion.
In this example, the type will suggest environment variables that start
with the incomplete value.
.. code-block:: python
class EnvVarType(ParamType):
name = "envvar"
def shell_complete(self, ctx, param, incomplete):
return [
CompletionItem(name)
for name in os.environ if name.startswith(incomplete)
]
@click.command()
@click.option("--ev", type=EnvVarType())
def cli(ev):
click.echo(os.environ[ev])
Overriding Value Completion
---------------------------
Value completions for a parameter can be customized without a custom
type by providing a ``shell_complete`` function. The function is used
instead of any completion provided by the type. It is passed 3 keyword
arguments:
- ``ctx`` - The current command context.
- ``param`` - The current parameter requesting completion.
- ``incomplete`` - The partial word that is being completed. May
be an empty string if no characters have been entered yet.
It must return a list of :class:`CompletionItem` objects, or as a
shortcut it can return a list of strings.
In this example, the command will suggest environment variables that
start with the incomplete value.
.. code-block:: python
def complete_env_vars(ctx, param, incomplete):
return [k for k in os.environ if k.startswith(incomplete)]
@click.command()
@click.argument("name", shell_complete=complete_env_vars)
def cli(name):
click.echo(f"Name: {name}")
click.echo(f"Value: {os.environ[name]}")
Adding Support for a Shell
--------------------------
Support can be added for shells that do not come built in. Be sure to
check PyPI to see if there's already a package that adds support for
your shell. This topic is very technical, you'll want to look at Click's
source to study the built-in implementations.
Shell support is provided by subclasses of :class:`ShellComplete`
registered with :func:`add_completion_class`. When Click is invoked in
completion mode, it calls :meth:`~ShellComplete.source` to output the
completion script, or :meth:`~ShellComplete.complete` to output
completions. The base class provides default implementations that
require implementing some smaller parts.
First, you'll need to figure out how your shell's completion system
works and write a script to integrate it with Click. It must invoke your
program with the environment variable ``_{PROG_NAME}_COMPLETE`` set to
``{shell}_complete`` and pass the complete args and incomplete value.
How it passes those values, and the format of the completion response
from Click is up to you.
In your subclass, set :attr:`~ShellComplete.source_template` to the
completion script. The default implementation will perform ``%``
formatting with the following variables:
- ``complete_func`` - A safe name for the completion function defined
in the script.
- ``complete_var`` - The environment variable name for passing the
``{shell}_complete`` instruction.
- ``prog_name`` - The name of the executable being completed.
The example code is for a made up shell "My Shell" or "mysh" for short.
.. code-block:: python
from click.shell_completion import add_completion_class
from click.shell_completion import ShellComplete
_mysh_source = """\
%(complete_func)s {
response=$(%(complete_var)s=mysh_complete %(prog_name)s)
# parse response and set completions somehow
}
call-on-complete %(prog_name)s %(complete_func)s
"""
@add_completion_class
class MyshComplete(ShellComplete):
name = "mysh"
source_template = _mysh_source
Next, implement :meth:`~ShellComplete.get_completion_args`. This must
get, parse, and return the complete args and incomplete value from the
completion script. For example, for the Bash implementation the
``COMP_WORDS`` env var contains the command line args as a string, and
the ``COMP_CWORD`` env var contains the index of the incomplete arg. The
method must return a ``(args, incomplete)`` tuple.
.. code-block:: python
import os
from click.parser import split_arg_string
class MyshComplete(ShellComplete):
...
def get_completion_args(self):
args = split_arg_string(os.environ["COMP_WORDS"])
if os.environ["COMP_PARTIAL"] == "1":
incomplete = args.pop()
return args, incomplete
return args, ""
Finally, implement :meth:`~ShellComplete.format_completion`. This is
called to format each :class:`CompletionItem` into a string. For
example, the Bash implementation returns ``f"{item.type},{item.value}``
(it doesn't support help strings), and the Zsh implementation returns
each part separated by a newline, replacing empty help with a ``_``
placeholder. This format is entirely up to what you parse with your
completion script.
The ``type`` value is usually ``plain``, but it can be another value
that the completion script can switch on. For example, ``file`` or
``dir`` can tell the shell to handle path completion, since the shell is
better at that than Click.
.. code-block:: python
class MyshComplete(ShellComplete):
...
def format_completion(self, item):
return f"{item.type}\t{item.value}"
With those three things implemented, the new shell support is ready. In
case those weren't sufficient, there are more parts that can be
overridden, but that probably isn't necessary.
The activation instructions will again depend on how your shell works.
Use the following to generate the completion script, then load it into
the shell somehow.
.. code-block:: text
_FOO_BAR_COMPLETE=mysh_source foo-bar

View file

@ -1,158 +0,0 @@
Testing Click Applications
==========================
.. currentmodule:: click.testing
For basic testing, Click provides the :mod:`click.testing` module which
provides test functionality that helps you invoke command line
applications and check their behavior.
These tools should really only be used for testing as they change
the entire interpreter state for simplicity and are not in any way
thread-safe!
Basic Testing
-------------
The basic functionality for testing Click applications is the
:class:`CliRunner` which can invoke commands as command line scripts. The
:meth:`CliRunner.invoke` method runs the command line script in isolation
and captures the output as both bytes and binary data.
The return value is a :class:`Result` object, which has the captured output
data, exit code, and optional exception attached:
.. code-block:: python
:caption: hello.py
import click
@click.command()
@click.argument('name')
def hello(name):
click.echo(f'Hello {name}!')
.. code-block:: python
:caption: test_hello.py
from click.testing import CliRunner
from hello import hello
def test_hello_world():
runner = CliRunner()
result = runner.invoke(hello, ['Peter'])
assert result.exit_code == 0
assert result.output == 'Hello Peter!\n'
For subcommand testing, a subcommand name must be specified in the `args` parameter of :meth:`CliRunner.invoke` method:
.. code-block:: python
:caption: sync.py
import click
@click.group()
@click.option('--debug/--no-debug', default=False)
def cli(debug):
click.echo(f"Debug mode is {'on' if debug else 'off'}")
@cli.command()
def sync():
click.echo('Syncing')
.. code-block:: python
:caption: test_sync.py
from click.testing import CliRunner
from sync import cli
def test_sync():
runner = CliRunner()
result = runner.invoke(cli, ['--debug', 'sync'])
assert result.exit_code == 0
assert 'Debug mode is on' in result.output
assert 'Syncing' in result.output
Additional keyword arguments passed to ``.invoke()`` will be used to construct the initial Context object.
For example, if you want to run your tests against a fixed terminal width you can use the following::
runner = CliRunner()
result = runner.invoke(cli, ['--debug', 'sync'], terminal_width=60)
File System Isolation
---------------------
For basic command line tools with file system operations, the
:meth:`CliRunner.isolated_filesystem` method is useful for setting the
current working directory to a new, empty folder.
.. code-block:: python
:caption: cat.py
import click
@click.command()
@click.argument('f', type=click.File())
def cat(f):
click.echo(f.read())
.. code-block:: python
:caption: test_cat.py
from click.testing import CliRunner
from cat import cat
def test_cat():
runner = CliRunner()
with runner.isolated_filesystem():
with open('hello.txt', 'w') as f:
f.write('Hello World!')
result = runner.invoke(cat, ['hello.txt'])
assert result.exit_code == 0
assert result.output == 'Hello World!\n'
Pass ``temp_dir`` to control where the temporary directory is created.
The directory will not be removed by Click in this case. This is useful
to integrate with a framework like Pytest that manages temporary files.
.. code-block:: python
def test_keep_dir(tmp_path):
runner = CliRunner()
with runner.isolated_filesystem(temp_dir=tmp_path) as td:
...
Input Streams
-------------
The test wrapper can also be used to provide input data for the input
stream (stdin). This is very useful for testing prompts, for instance:
.. code-block:: python
:caption: prompt.py
import click
@click.command()
@click.option('--foo', prompt=True)
def prompt(foo):
click.echo(f"foo={foo}")
.. code-block:: python
:caption: test_prompt.py
from click.testing import CliRunner
from prompt import prompt
def test_prompts():
runner = CliRunner()
result = runner.invoke(prompt, input='wau wau\n')
assert not result.exception
assert result.output == 'Foo: wau wau\nfoo=wau wau\n'
Note that prompts will be emulated so that they write the input data to
the output stream as well. If hidden input is expected then this
obviously does not happen.

View file

@ -1,112 +0,0 @@
Unicode Support
===============
.. currentmodule:: click
Click has to take extra care to support Unicode text in different
environments.
* The command line in Unix is traditionally bytes, not Unicode. While
there are encoding hints, there are some situations where this can
break. The most common one is SSH connections to machines with
different locales.
Misconfigured environments can cause a wide range of Unicode
problems due to the lack of support for roundtripping surrogate
escapes. This will not be fixed in Click itself!
* Standard input and output is opened in text mode by default. Click
has to reopen the stream in binary mode in certain situations.
Because there is no standard way to do this, it might not always
work. Primarily this can become a problem when testing command-line
applications.
This is not supported::
sys.stdin = io.StringIO('Input here')
sys.stdout = io.StringIO()
Instead you need to do this::
input = 'Input here'
in_stream = io.BytesIO(input.encode('utf-8'))
sys.stdin = io.TextIOWrapper(in_stream, encoding='utf-8')
out_stream = io.BytesIO()
sys.stdout = io.TextIOWrapper(out_stream, encoding='utf-8')
Remember in that case, you need to use ``out_stream.getvalue()``
and not ``sys.stdout.getvalue()`` if you want to access the buffer
contents as the wrapper will not forward that method.
* ``sys.stdin``, ``sys.stdout`` and ``sys.stderr`` are by default
text-based. When Click needs a binary stream, it attempts to
discover the underlying binary stream.
* ``sys.argv`` is always text. This means that the native type for
input values to the types in Click is Unicode, not bytes.
This causes problems if the terminal is incorrectly set and Python
does not figure out the encoding. In that case, the Unicode string
will contain error bytes encoded as surrogate escapes.
* When dealing with files, Click will always use the Unicode file
system API by using the operating system's reported or guessed
filesystem encoding. Surrogates are supported for filenames, so it
should be possible to open files through the :class:`File` type even
if the environment is misconfigured.
Surrogate Handling
------------------
Click does all the Unicode handling in the standard library and is
subject to its behavior. Unicode requires extra care. The reason for
this is that the encoding detection is done in the interpreter, and on
Linux and certain other operating systems, its encoding handling is
problematic.
The biggest source of frustration is that Click scripts invoked by init
systems, deployment tools, or cron jobs will refuse to work unless a
Unicode locale is exported.
If Click encounters such an environment it will prevent further
execution to force you to set a locale. This is done because Click
cannot know about the state of the system once it's invoked and restore
the values before Python's Unicode handling kicked in.
If you see something like this error::
Traceback (most recent call last):
...
RuntimeError: Click will abort further execution because Python was
configured to use ASCII as encoding for the environment. Consult
https://click.palletsprojects.com/unicode-support/ for mitigation
steps.
You are dealing with an environment where Python thinks you are
restricted to ASCII data. The solution to these problems is different
depending on which locale your computer is running in.
For instance, if you have a German Linux machine, you can fix the
problem by exporting the locale to ``de_DE.utf-8``::
export LC_ALL=de_DE.utf-8
export LANG=de_DE.utf-8
If you are on a US machine, ``en_US.utf-8`` is the encoding of choice.
On some newer Linux systems, you could also try ``C.UTF-8`` as the
locale::
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
On some systems it was reported that ``UTF-8`` has to be written as
``UTF8`` and vice versa. To see which locales are supported you can
invoke ``locale -a``.
You need to export the values before you invoke your Python script.
In Python 3.7 and later you will no longer get a ``RuntimeError`` in
many cases thanks to :pep:`538` and :pep:`540`, which changed the
default assumption in unconfigured environments. This doesn't change the
general issue that your locale may be misconfigured.

View file

@ -1,131 +0,0 @@
Upgrading To Newer Releases
===========================
Click attempts the highest level of backwards compatibility but sometimes
this is not entirely possible. In case we need to break backwards
compatibility this document gives you information about how to upgrade or
handle backwards compatibility properly.
.. _upgrade-to-7.0:
Upgrading to 7.0
----------------
Commands that take their name from the decorated function now replace
underscores with dashes. For example, the Python function ``run_server``
will get the command name ``run-server`` now. There are a few options
to address this:
- To continue with the new behavior, pin your dependency to
``Click>=7`` and update any documentation to use dashes.
- To keep existing behavior, add an explicit command name with
underscores, like ``@click.command("run_server")``.
- To try a name with dashes if the name with underscores was not
found, pass a ``token_normalize_func`` to the context:
.. code-block:: python
def normalize(name):
return name.replace("_", "-")
@click.group(context_settings={"token_normalize_func": normalize})
def group():
...
@group.command()
def run_server():
...
.. _upgrade-to-3.2:
Upgrading to 3.2
----------------
Click 3.2 had to perform two changes to multi commands which were
triggered by a change between Click 2 and Click 3 that had bigger
consequences than anticipated.
Context Invokes
```````````````
Click 3.2 contains a fix for the :meth:`Context.invoke` function when used
with other commands. The original intention of this function was to
invoke the other command as as if it came from the command line when it
was passed a context object instead of a function. This use was only
documented in a single place in the documentation before and there was no
proper explanation for the method in the API documentation.
The core issue is that before 3.2 this call worked against intentions::
ctx.invoke(other_command, 'arg1', 'arg2')
This was never intended to work as it does not allow Click to operate on
the parameters. Given that this pattern was never documented and ill
intended the decision was made to change this behavior in a bugfix release
before it spreads by accident and developers depend on it.
The correct invocation for the above command is the following::
ctx.invoke(other_command, name_of_arg1='arg1', name_of_arg2='arg2')
This also allowed us to fix the issue that defaults were not handled
properly by this function.
Multicommand Chaining API
`````````````````````````
Click 3 introduced multicommand chaining. This required a change in how
Click internally dispatches. Unfortunately this change was not correctly
implemented and it appeared that it was possible to provide an API that
can inform the super command about all the subcommands that will be
invoked.
This assumption however does not work with one of the API guarantees that
have been given in the past. As such this functionality has been removed
in 3.2 as it was already broken. Instead the accidentally broken
functionality of the :attr:`Context.invoked_subcommand` attribute was
restored.
If you do require the know which exact commands will be invoked there are
different ways to cope with this. The first one is to let the subcommands
all return functions and then to invoke the functions in a
:meth:`Context.result_callback`.
.. _upgrade-to-2.0:
Upgrading to 2.0
----------------
Click 2.0 has one breaking change which is the signature for parameter
callbacks. Before 2.0, the callback was invoked with ``(ctx, value)``
whereas now it's ``(ctx, param, value)``. This change was necessary as it
otherwise made reusing callbacks too complicated.
To ease the transition Click will still accept old callbacks. Starting
with Click 3.0 it will start to issue a warning to stderr to encourage you
to upgrade.
In case you want to support both Click 1.0 and Click 2.0, you can make a
simple decorator that adjusts the signatures::
import click
from functools import update_wrapper
def compatcallback(f):
# Click 1.0 does not have a version string stored, so we need to
# use getattr here to be safe.
if getattr(click, '__version__', '0.0') >= '2.0':
return f
return update_wrapper(lambda ctx, value: f(ctx, None, value), f)
With that helper you can then write something like this::
@compatcallback
def callback(ctx, param, value):
return value.upper()
Note that because Click 1.0 did not pass a parameter, the `param` argument
here would be `None`, so a compatibility callback could not use that
argument.

View file

@ -1,408 +0,0 @@
Utilities
=========
.. currentmodule:: click
Besides the functionality that Click provides to interface with argument
parsing and handling, it also provides a bunch of addon functionality that
is useful for writing command line utilities.
Printing to Stdout
------------------
The most obvious helper is the :func:`echo` function, which in many ways
works like the Python ``print`` statement or function. The main difference is
that it works the same in many different terminal environments.
Example::
import click
click.echo('Hello World!')
It can output both text and binary data. It will emit a trailing newline
by default, which needs to be suppressed by passing ``nl=False``::
click.echo(b'\xe2\x98\x83', nl=False)
Last but not least :func:`echo` uses click's intelligent internal output
streams to stdout and stderr which support unicode output on the Windows
console. This means for as long as you are using `click.echo` you can
output unicode characters (there are some limitations on the default font
with regards to which characters can be displayed).
.. versionadded:: 6.0
Click emulates output streams on Windows to support unicode to the
Windows console through separate APIs. For more information see
:doc:`wincmd`.
.. versionadded:: 3.0
You can also easily print to standard error by passing ``err=True``::
click.echo('Hello World!', err=True)
.. _ansi-colors:
ANSI Colors
-----------
.. versionadded:: 2.0
The :func:`echo` function supports ANSI colors and styles. On Windows
this uses `colorama`_.
Primarily this means that:
- Click's :func:`echo` function will automatically strip ANSI color codes
if the stream is not connected to a terminal.
- the :func:`echo` function will transparently connect to the terminal on
Windows and translate ANSI codes to terminal API calls. This means
that colors will work on Windows the same way they do on other
operating systems.
On Windows, Click uses colorama without calling ``colorama.init()``. You
can still call that in your code, but it's not required for Click.
For styling a string, the :func:`style` function can be used::
import click
click.echo(click.style('Hello World!', fg='green'))
click.echo(click.style('Some more text', bg='blue', fg='white'))
click.echo(click.style('ATTENTION', blink=True, bold=True))
The combination of :func:`echo` and :func:`style` is also available in
a single function called :func:`secho`::
click.secho('Hello World!', fg='green')
click.secho('Some more text', bg='blue', fg='white')
click.secho('ATTENTION', blink=True, bold=True)
.. _colorama: https://pypi.org/project/colorama/
Pager Support
-------------
In some situations, you might want to show long texts on the terminal and
let a user scroll through it. This can be achieved by using the
:func:`echo_via_pager` function which works similarly to the :func:`echo`
function, but always writes to stdout and, if possible, through a pager.
Example:
.. click:example::
@click.command()
def less():
click.echo_via_pager("\n".join(f"Line {idx}" for idx in range(200)))
If you want to use the pager for a lot of text, especially if generating everything in advance would take a lot of time, you can pass a generator (or generator function) instead of a string:
.. click:example::
def _generate_output():
for idx in range(50000):
yield f"Line {idx}\n"
@click.command()
def less():
click.echo_via_pager(_generate_output())
Screen Clearing
---------------
.. versionadded:: 2.0
To clear the terminal screen, you can use the :func:`clear` function that
is provided starting with Click 2.0. It does what the name suggests: it
clears the entire visible screen in a platform-agnostic way:
::
import click
click.clear()
Getting Characters from Terminal
--------------------------------
.. versionadded:: 2.0
Normally, when reading input from the terminal, you would read from
standard input. However, this is buffered input and will not show up until
the line has been terminated. In certain circumstances, you might not want
to do that and instead read individual characters as they are being written.
For this, Click provides the :func:`getchar` function which reads a single
character from the terminal buffer and returns it as a Unicode character.
Note that this function will always read from the terminal, even if stdin
is instead a pipe.
Example::
import click
click.echo('Continue? [yn] ', nl=False)
c = click.getchar()
click.echo()
if c == 'y':
click.echo('We will go on')
elif c == 'n':
click.echo('Abort!')
else:
click.echo('Invalid input :(')
Note that this reads raw input, which means that things like arrow keys
will show up in the platform's native escape format. The only characters
translated are ``^C`` and ``^D`` which are converted into keyboard
interrupts and end of file exceptions respectively. This is done because
otherwise, it's too easy to forget about that and to create scripts that
cannot be properly exited.
Waiting for Key Press
---------------------
.. versionadded:: 2.0
Sometimes, it's useful to pause until the user presses any key on the
keyboard. This is especially useful on Windows where ``cmd.exe`` will
close the window at the end of the command execution by default, instead
of waiting.
In click, this can be accomplished with the :func:`pause` function. This
function will print a quick message to the terminal (which can be
customized) and wait for the user to press a key. In addition to that,
it will also become a NOP (no operation instruction) if the script is not
run interactively.
Example::
import click
click.pause()
Launching Editors
-----------------
.. versionadded:: 2.0
Click supports launching editors automatically through :func:`edit`. This
is very useful for asking users for multi-line input. It will
automatically open the user's defined editor or fall back to a sensible
default. If the user closes the editor without saving, the return value
will be ``None``, otherwise the entered text.
Example usage::
import click
def get_commit_message():
MARKER = '# Everything below is ignored\n'
message = click.edit('\n\n' + MARKER)
if message is not None:
return message.split(MARKER, 1)[0].rstrip('\n')
Alternatively, the function can also be used to launch editors for files by
a specific filename. In this case, the return value is always `None`.
Example usage::
import click
click.edit(filename='/etc/passwd')
Launching Applications
----------------------
.. versionadded:: 2.0
Click supports launching applications through :func:`launch`. This can be
used to open the default application associated with a URL or filetype.
This can be used to launch web browsers or picture viewers, for instance.
In addition to this, it can also launch the file manager and automatically
select the provided file.
Example usage::
click.launch("https://click.palletsprojects.com/")
click.launch("/my/downloaded/file.txt", locate=True)
Printing Filenames
------------------
Because filenames might not be Unicode, formatting them can be a bit
tricky.
The way this works with click is through the :func:`format_filename`
function. It does a best-effort conversion of the filename to Unicode and
will never fail. This makes it possible to use these filenames in the
context of a full Unicode string.
Example::
click.echo(f"Path: {click.format_filename(b'foo.txt')}")
Standard Streams
----------------
For command line utilities, it's very important to get access to input and
output streams reliably. Python generally provides access to these
streams through ``sys.stdout`` and friends, but unfortunately, there are
API differences between 2.x and 3.x, especially with regards to how these
streams respond to Unicode and binary data.
Because of this, click provides the :func:`get_binary_stream` and
:func:`get_text_stream` functions, which produce consistent results with
different Python versions and for a wide variety of terminal configurations.
The end result is that these functions will always return a functional
stream object (except in very odd cases; see :doc:`/unicode-support`).
Example::
import click
stdin_text = click.get_text_stream('stdin')
stdout_binary = click.get_binary_stream('stdout')
.. versionadded:: 6.0
Click now emulates output streams on Windows to support unicode to the
Windows console through separate APIs. For more information see
:doc:`wincmd`.
Intelligent File Opening
------------------------
.. versionadded:: 3.0
Starting with Click 3.0 the logic for opening files from the :class:`File`
type is exposed through the :func:`open_file` function. It can
intelligently open stdin/stdout as well as any other file.
Example::
import click
stdout = click.open_file('-', 'w')
test_file = click.open_file('test.txt', 'w')
If stdin or stdout are returned, the return value is wrapped in a special
file where the context manager will prevent the closing of the file. This
makes the handling of standard streams transparent and you can always use
it like this::
with click.open_file(filename, 'w') as f:
f.write('Hello World!\n')
Finding Application Folders
---------------------------
.. versionadded:: 2.0
Very often, you want to open a configuration file that belongs to your
application. However, different operating systems store these configuration
files in different locations depending on their standards. Click provides
a :func:`get_app_dir` function which returns the most appropriate location
for per-user config files for your application depending on the OS.
Example usage::
import os
import click
import ConfigParser
APP_NAME = 'My Application'
def read_config():
cfg = os.path.join(click.get_app_dir(APP_NAME), 'config.ini')
parser = ConfigParser.RawConfigParser()
parser.read([cfg])
rv = {}
for section in parser.sections():
for key, value in parser.items(section):
rv[f"{section}.{key}"] = value
return rv
Showing Progress Bars
---------------------
Sometimes, you have command line scripts that need to process a lot of data,
but you want to quickly show the user some progress about how long that
will take. Click supports simple progress bar rendering for that through
the :func:`progressbar` function.
.. note::
If you find that you have requirements beyond what Click's progress
bar supports, try using `tqdm`_.
.. _tqdm: https://tqdm.github.io/
The basic usage is very simple: the idea is that you have an iterable that
you want to operate on. For each item in the iterable it might take some
time to do processing. So say you have a loop like this::
for user in all_the_users_to_process:
modify_the_user(user)
To hook this up with an automatically updating progress bar, all you need
to do is to change the code to this::
import click
with click.progressbar(all_the_users_to_process) as bar:
for user in bar:
modify_the_user(user)
Click will then automatically print a progress bar to the terminal and
calculate the remaining time for you. The calculation of remaining time
requires that the iterable has a length. If it does not have a length
but you know the length, you can explicitly provide it::
with click.progressbar(all_the_users_to_process,
length=number_of_users) as bar:
for user in bar:
modify_the_user(user)
Note that :func:`progressbar` updates the bar *after* each iteration of the
loop. So code like this will render correctly::
import time
with click.progressbar([1, 2, 3]) as bar:
for x in bar:
print(f"sleep({x})...")
time.sleep(x)
Another useful feature is to associate a label with the progress bar which
will be shown preceding the progress bar::
with click.progressbar(all_the_users_to_process,
label='Modifying user accounts',
length=number_of_users) as bar:
for user in bar:
modify_the_user(user)
Sometimes, one may need to iterate over an external iterator, and advance the
progress bar irregularly. To do so, you need to specify the length (and no
iterable), and use the update method on the context return value instead of
iterating directly over it::
with click.progressbar(length=total_size,
label='Unzipping archive') as bar:
for archive in zip_file:
archive.extract()
bar.update(archive.size)

View file

@ -1,146 +0,0 @@
Why Click?
==========
There are so many libraries out there for writing command line utilities;
why does Click exist?
This question is easy to answer: because there is not a single command
line utility for Python out there which ticks the following boxes:
* Is lazily composable without restrictions.
* Supports implementation of Unix/POSIX command line conventions.
* Supports loading values from environment variables out of the box.
* Support for prompting of custom values.
* Is fully nestable and composable.
* Supports file handling out of the box.
* Comes with useful common helpers (getting terminal dimensions,
ANSI colors, fetching direct keyboard input, screen clearing,
finding config paths, launching apps and editors, etc.).
There are many alternatives to Click; the obvious ones are ``optparse``
and ``argparse`` from the standard library. Have a look to see if something
else resonates with you.
Click actually implements its own parsing of arguments and does not use
``optparse`` or ``argparse`` following the ``optparse`` parsing behavior.
The reason it's not based on ``argparse`` is that ``argparse`` does not
allow proper nesting of commands by design and has some deficiencies when
it comes to POSIX compliant argument handling.
Click is designed to be fun and customizable but not overly flexible.
For instance, the customizability of help pages is constrained. This
constraint is intentional because Click promises multiple Click instances
will continue to function as intended when strung together.
Too much customizability would break this promise.
Click was written to support the `Flask <https://palletsprojects.com/p/flask/>`_
microframework ecosystem because no tool could provide it with the
functionality it needed.
To get an understanding of what Click is all about, I strongly recommend
looking at the :ref:`complex-guide` chapter.
Why not Argparse?
-----------------
Click is internally based on ``optparse`` instead of ``argparse``. This
is an implementation detail that a user does not have to be concerned
with. Click is not based on ``argparse`` because it has some behaviors that
make handling arbitrary command line interfaces hard:
* ``argparse`` has built-in behavior to guess if something is an
argument or an option. This becomes a problem when dealing with
incomplete command lines; the behaviour becomes unpredictable
without full knowledge of a command line. This goes against Click's
ambitions of dispatching to subparsers.
* ``argparse`` does not support disabling interspersed arguments. Without
this feature, it's not possible to safely implement Click's nested
parsing.
Why not Docopt etc.?
--------------------
Docopt, and many tools like it, are cool in how they work, but very few of
these tools deal with nesting of commands and composability in a way like
Click. To the best of the developer's knowledge, Click is the first
Python library that aims to create a level of composability of applications
that goes beyond what the system itself supports.
Docopt, for instance, acts by parsing your help pages and then parsing
according to those rules. The side effect of this is that docopt is quite
rigid in how it handles the command line interface. The upside of docopt
is that it gives you strong control over your help page; the downside is
that due to this it cannot rewrap your output for the current terminal
width, and it makes translations hard. On top of that, docopt is restricted
to basic parsing. It does not handle argument dispatching and callback
invocation or types. This means there is a lot of code that needs to be
written in addition to the basic help page to handle the parsing results.
Most of all, however, it makes composability hard. While docopt does
support dispatching to subcommands, it, for instance, does not directly
support any kind of automatic subcommand enumeration based on what's
available or it does not enforce subcommands to work in a consistent way.
This is fine, but it's different from how Click wants to work. Click aims
to support fully composable command line user interfaces by doing the
following:
- Click does not just parse, it also dispatches to the appropriate code.
- Click has a strong concept of an invocation context that allows
subcommands to respond to data from the parent command.
- Click has strong information available for all parameters and commands,
so it can generate unified help pages for the full CLI and
assist the user in converting the input data as necessary.
- Click has a strong understanding of what types are, and it can give the user
consistent error messages if something goes wrong. A subcommand
written by a different developer will not suddenly die with a
different error message because it's manually handled.
- Click has enough meta information available for its whole program
to evolve over time and improve the user experience without
forcing developers to adjust their programs. For instance, if Click
decides to change how help pages are formatted, all Click programs
will automatically benefit from this.
The aim of Click is to make composable systems. Whereas, the aim of docopt
is to build the most beautiful and hand-crafted command line interfaces.
These two goals conflict with one another in subtle ways. Click
actively prevents people from implementing certain patterns in order to
achieve unified command line interfaces. For instance, as a developer, you
are given very little choice in formatting your help pages.
Why Hardcoded Behaviors?
------------------------
The other question is why Click goes away from optparse and hardcodes
certain behaviors instead of staying configurable. There are multiple
reasons for this. The biggest one is that too much configurability makes
it hard to achieve a consistent command line experience.
The best example for this is optparse's ``callback`` functionality for
accepting an arbitrary number of arguments. Due to syntactical ambiguities
on the command line, there is no way to implement fully variadic arguments.
There are always tradeoffs that need to be made and in case of
``argparse`` these tradeoffs have been critical enough, that a system like
Click cannot even be implemented on top of it.
In this particular case, Click attempts to stay with a handful of accepted
paradigms for building command line interfaces that can be well documented
and tested.
Why No Auto Correction?
-----------------------
The question came up why Click does not auto correct parameters given that
even optparse and ``argparse`` support automatic expansion of long arguments.
The reason for this is that it's a liability for backwards compatibility.
If people start relying on automatically modified parameters and someone
adds a new parameter in the future, the script might stop working. These
kinds of problems are hard to find, so Click does not attempt to be magical
about this.
This sort of behavior however can be implemented on a higher level to
support things such as explicit aliases. For more information see
:ref:`aliases`.

View file

@ -1,64 +0,0 @@
Windows Console Notes
=====================
.. versionadded:: 6.0
Click emulates output streams on Windows to support unicode to the
Windows console through separate APIs and we perform different decoding of
parameters.
Here is a brief overview of how this works and what it means to you.
Unicode Arguments
-----------------
Click internally is generally based on the concept that any argument can
come in as either byte string or unicode string and conversion is
performed to the type expected value as late as possible. This has some
advantages as it allows us to accept the data in the most appropriate form
for the operating system and Python version.
This caused some problems on Windows where initially the wrong encoding
was used and garbage ended up in your input data. We not only fixed the
encoding part, but we also now extract unicode parameters from `sys.argv`.
There is also another limitation with this: if `sys.argv` was modified
prior to invoking a click handler, we have to fall back to the regular
byte input in which case not all unicode values are available but only a
subset of the codepage used for parameters.
Unicode Output and Input
------------------------
Unicode output and input on Windows is implemented through the concept of
a dispatching text stream. What this means is that when click first needs
a text output (or input) stream on windows it goes through a few checks to
figure out of a windows console is connected or not. If no Windows
console is present then the text output stream is returned as such and the
encoding for that stream is set to ``utf-8`` like on all platforms.
However if a console is connected the stream will instead be emulated and
use the cmd.exe unicode APIs to output text information. In this case the
stream will also use ``utf-16-le`` as internal encoding. However there is
some hackery going on that the underlying raw IO buffer is still bypassing
the unicode APIs and byte output through an indirection is still possible.
* This unicode support is limited to ``click.echo``, ``click.prompt`` as
well as ``click.get_text_stream``.
* Depending on if unicode values or byte strings are passed the control
flow goes completely different places internally which can have some
odd artifacts if data partially ends up being buffered. Click
attempts to protect against that by manually always flushing but if
you are mixing and matching different string types to ``stdout`` or
``stderr`` you will need to manually flush.
* The raw output stream is set to binary mode, which is a global
operation on Windows, so ``print`` calls will be affected. Prefer
``click.echo`` over ``print``.
* On Windows 7 and below, there is a limitation where at most 64k
characters can be written in one call in binary mode. In this
situation, ``sys.stdout`` and ``sys.stderr`` are replaced with
wrappers that work around the limitation.
Another important thing to note is that the Windows console's default
fonts do not support a lot of characters which means that you are mostly
limited to international letters but no emojis or special characters.

View file

@ -1,12 +0,0 @@
Click Examples
This folder contains various Click examples. Note that
all of these are not runnable by themselves but should be
installed into a virtualenv.
This is done this way so that scripts also properly work
on Windows and in virtualenvs without accidentally executing
through the wrong interpreter.
For more information about this see the documentation:
https://click.palletsprojects.com/setuptools/

View file

@ -1,17 +0,0 @@
$ aliases_
aliases is a fairly advanced example that shows how
to implement command aliases with Click. It uses a
subclass of the default group to customize how commands
are located.
It supports both aliases read from a config file as well
as automatic abbreviations.
The aliases from the config are read from the aliases.ini
file. Try `aliases st` and `aliases ci`!
Usage:
$ pip install --editable .
$ aliases --help

View file

@ -1,2 +0,0 @@
[aliases]
ci=commit

View file

@ -1,143 +0,0 @@
import configparser
import os
import click
class Config:
"""The config in this example only holds aliases."""
def __init__(self):
self.path = os.getcwd()
self.aliases = {}
def add_alias(self, alias, cmd):
self.aliases.update({alias: cmd})
def read_config(self, filename):
parser = configparser.RawConfigParser()
parser.read([filename])
try:
self.aliases.update(parser.items("aliases"))
except configparser.NoSectionError:
pass
def write_config(self, filename):
parser = configparser.RawConfigParser()
parser.add_section("aliases")
for key, value in self.aliases.items():
parser.set("aliases", key, value)
with open(filename, "wb") as file:
parser.write(file)
pass_config = click.make_pass_decorator(Config, ensure=True)
class AliasedGroup(click.Group):
"""This subclass of a group supports looking up aliases in a config
file and with a bit of magic.
"""
def get_command(self, ctx, cmd_name):
# Step one: bulitin commands as normal
rv = click.Group.get_command(self, ctx, cmd_name)
if rv is not None:
return rv
# Step two: find the config object and ensure it's there. This
# will create the config object is missing.
cfg = ctx.ensure_object(Config)
# Step three: look up an explicit command alias in the config
if cmd_name in cfg.aliases:
actual_cmd = cfg.aliases[cmd_name]
return click.Group.get_command(self, ctx, actual_cmd)
# Alternative option: if we did not find an explicit alias we
# allow automatic abbreviation of the command. "status" for
# instance will match "st". We only allow that however if
# there is only one command.
matches = [
x for x in self.list_commands(ctx) if x.lower().startswith(cmd_name.lower())
]
if not matches:
return None
elif len(matches) == 1:
return click.Group.get_command(self, ctx, matches[0])
ctx.fail(f"Too many matches: {', '.join(sorted(matches))}")
def resolve_command(self, ctx, args):
# always return the command's name, not the alias
_, cmd, args = super().resolve_command(ctx, args)
return cmd.name, cmd, args
def read_config(ctx, param, value):
"""Callback that is used whenever --config is passed. We use this to
always load the correct config. This means that the config is loaded
even if the group itself never executes so our aliases stay always
available.
"""
cfg = ctx.ensure_object(Config)
if value is None:
value = os.path.join(os.path.dirname(__file__), "aliases.ini")
cfg.read_config(value)
return value
@click.command(cls=AliasedGroup)
@click.option(
"--config",
type=click.Path(exists=True, dir_okay=False),
callback=read_config,
expose_value=False,
help="The config file to use instead of the default.",
)
def cli():
"""An example application that supports aliases."""
@cli.command()
def push():
"""Pushes changes."""
click.echo("Push")
@cli.command()
def pull():
"""Pulls changes."""
click.echo("Pull")
@cli.command()
def clone():
"""Clones a repository."""
click.echo("Clone")
@cli.command()
def commit():
"""Commits pending changes."""
click.echo("Commit")
@cli.command()
@pass_config
def status(config):
"""Shows the status."""
click.echo(f"Status for {config.path}")
@cli.command()
@pass_config
@click.argument("alias_", metavar="ALIAS", type=click.STRING)
@click.argument("cmd", type=click.STRING)
@click.option(
"--config_file", type=click.Path(exists=True, dir_okay=False), default="aliases.ini"
)
def alias(config, alias_, cmd, config_file):
"""Adds an alias to the specified configuration file."""
config.add_alias(alias_, cmd)
config.write_config(config_file)
click.echo(f"Added '{alias_}' as alias for '{cmd}'")

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-aliases",
version="1.0",
py_modules=["aliases"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
aliases=aliases:cli
""",
)

View file

@ -1,11 +0,0 @@
$ colors_
colors is a simple example that shows how you can
colorize text.
Uses colorama on Windows.
Usage:
$ pip install --editable .
$ colors

View file

@ -1,39 +0,0 @@
import click
all_colors = (
"black",
"red",
"green",
"yellow",
"blue",
"magenta",
"cyan",
"white",
"bright_black",
"bright_red",
"bright_green",
"bright_yellow",
"bright_blue",
"bright_magenta",
"bright_cyan",
"bright_white",
)
@click.command()
def cli():
"""This script prints some colors. It will also automatically remove
all ANSI styles if data is piped into a file.
Give it a try!
"""
for color in all_colors:
click.echo(click.style(f"I am colored {color}", fg=color))
for color in all_colors:
click.echo(click.style(f"I am colored {color} and bold", fg=color, bold=True))
for color in all_colors:
click.echo(click.style(f"I am reverse colored {color}", fg=color, reverse=True))
click.echo(click.style("I am blinking", blink=True))
click.echo(click.style("I am underlined", underline=True))

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-colors",
version="1.0",
py_modules=["colors"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
colors=colors:cli
""",
)

View file

@ -1,28 +0,0 @@
$ completion
============
Demonstrates Click's shell completion support.
.. code-block:: bash
pip install --editable .
For Bash:
.. code-block:: bash
eval "$(_COMPLETION_COMPLETE=bash_source completion)"
For Zsh:
.. code-block:: zsh
eval "$(_COMPLETION_COMPLETE=zsh_source completion)"
For Fish:
.. code-block:: fish
eval (env _COMPLETION_COMPLETE=fish_source completion)
Now press tab (maybe twice) after typing something to see completions.

View file

@ -1,56 +0,0 @@
import os
import click
from click.shell_completion import CompletionItem
@click.group()
def cli():
pass
@cli.command()
@click.option("--dir", type=click.Path(file_okay=False))
def ls(dir):
click.echo("\n".join(os.listdir(dir)))
def get_env_vars(ctx, param, incomplete):
# Returning a list of values is a shortcut to returning a list of
# CompletionItem(value).
return [k for k in os.environ if incomplete in k]
@cli.command(help="A command to print environment variables")
@click.argument("envvar", shell_complete=get_env_vars)
def show_env(envvar):
click.echo(f"Environment variable: {envvar}")
click.echo(f"Value: {os.environ[envvar]}")
@cli.group(help="A group that holds a subcommand")
def group():
pass
def list_users(ctx, param, incomplete):
# You can generate completions with help strings by returning a list
# of CompletionItem. You can match on whatever you want, including
# the help.
items = [("bob", "butcher"), ("alice", "baker"), ("jerry", "candlestick maker")]
out = []
for value, help in items:
if incomplete in value or incomplete in help:
out.append(CompletionItem(value, help=help))
return out
@group.command(help="Choose a user")
@click.argument("user", shell_complete=list_users)
def select_user(user):
click.echo(f"Chosen user is {user}")
cli.add_command(group)

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-completion",
version="1.0",
py_modules=["completion"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
completion=completion:cli
""",
)

View file

@ -1,16 +0,0 @@
$ complex_
complex is an example of building very complex cli
applications that load subcommands dynamically from
a plugin folder and other things.
All the commands are implemented as plugins in the
`complex.commands` package. If a python module is
placed named "cmd_foo" it will show up as "foo"
command and the `cli` object within it will be
loaded as nested Click command.
Usage:
$ pip install --editable .
$ complex --help

View file

@ -1,60 +0,0 @@
import os
import sys
import click
CONTEXT_SETTINGS = dict(auto_envvar_prefix="COMPLEX")
class Environment:
def __init__(self):
self.verbose = False
self.home = os.getcwd()
def log(self, msg, *args):
"""Logs a message to stderr."""
if args:
msg %= args
click.echo(msg, file=sys.stderr)
def vlog(self, msg, *args):
"""Logs a message to stderr only if verbose is enabled."""
if self.verbose:
self.log(msg, *args)
pass_environment = click.make_pass_decorator(Environment, ensure=True)
cmd_folder = os.path.abspath(os.path.join(os.path.dirname(__file__), "commands"))
class ComplexCLI(click.MultiCommand):
def list_commands(self, ctx):
rv = []
for filename in os.listdir(cmd_folder):
if filename.endswith(".py") and filename.startswith("cmd_"):
rv.append(filename[4:-3])
rv.sort()
return rv
def get_command(self, ctx, name):
try:
mod = __import__(f"complex.commands.cmd_{name}", None, None, ["cli"])
except ImportError:
return
return mod.cli
@click.command(cls=ComplexCLI, context_settings=CONTEXT_SETTINGS)
@click.option(
"--home",
type=click.Path(exists=True, file_okay=False, resolve_path=True),
help="Changes the folder to operate on.",
)
@click.option("-v", "--verbose", is_flag=True, help="Enables verbose mode.")
@pass_environment
def cli(ctx, verbose, home):
"""A complex command line interface."""
ctx.verbose = verbose
if home is not None:
ctx.home = home

View file

@ -1,13 +0,0 @@
from complex.cli import pass_environment
import click
@click.command("init", short_help="Initializes a repo.")
@click.argument("path", required=False, type=click.Path(resolve_path=True))
@pass_environment
def cli(ctx, path):
"""Initializes a repository."""
if path is None:
path = ctx.home
ctx.log(f"Initialized the repository in {click.format_filename(path)}")

View file

@ -1,11 +0,0 @@
from complex.cli import pass_environment
import click
@click.command("status", short_help="Shows file changes.")
@pass_environment
def cli(ctx):
"""Shows file changes in the current working directory."""
ctx.log("Changed files: none")
ctx.vlog("bla bla bla, debug info")

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-complex",
version="1.0",
packages=["complex", "complex.commands"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
complex=complex.cli:cli
""",
)

View file

@ -1 +0,0 @@
processed-*

View file

@ -1,13 +0,0 @@
$ imagepipe_
imagepipe is an example application that implements some
multi commands that chain image processing instructions
together.
This requires pillow.
Usage:
$ pip install --editable .
$ imagepipe open -i example01.jpg resize -w 128 display
$ imagepipe open -i example02.jpg blur save

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

View file

@ -1,288 +0,0 @@
from functools import update_wrapper
from PIL import Image
from PIL import ImageEnhance
from PIL import ImageFilter
import click
@click.group(chain=True)
def cli():
"""This script processes a bunch of images through pillow in a unix
pipe. One commands feeds into the next.
Example:
\b
imagepipe open -i example01.jpg resize -w 128 display
imagepipe open -i example02.jpg blur save
"""
@cli.result_callback()
def process_commands(processors):
"""This result callback is invoked with an iterable of all the chained
subcommands. As in this example each subcommand returns a function
we can chain them together to feed one into the other, similar to how
a pipe on unix works.
"""
# Start with an empty iterable.
stream = ()
# Pipe it through all stream processors.
for processor in processors:
stream = processor(stream)
# Evaluate the stream and throw away the items.
for _ in stream:
pass
def processor(f):
"""Helper decorator to rewrite a function so that it returns another
function from it.
"""
def new_func(*args, **kwargs):
def processor(stream):
return f(stream, *args, **kwargs)
return processor
return update_wrapper(new_func, f)
def generator(f):
"""Similar to the :func:`processor` but passes through old values
unchanged and does not pass through the values as parameter.
"""
@processor
def new_func(stream, *args, **kwargs):
yield from stream
yield from f(*args, **kwargs)
return update_wrapper(new_func, f)
def copy_filename(new, old):
new.filename = old.filename
return new
@cli.command("open")
@click.option(
"-i",
"--image",
"images",
type=click.Path(),
multiple=True,
help="The image file to open.",
)
@generator
def open_cmd(images):
"""Loads one or multiple images for processing. The input parameter
can be specified multiple times to load more than one image.
"""
for image in images:
try:
click.echo(f"Opening '{image}'")
if image == "-":
img = Image.open(click.get_binary_stdin())
img.filename = "-"
else:
img = Image.open(image)
yield img
except Exception as e:
click.echo(f"Could not open image '{image}': {e}", err=True)
@cli.command("save")
@click.option(
"--filename",
default="processed-{:04}.png",
type=click.Path(),
help="The format for the filename.",
show_default=True,
)
@processor
def save_cmd(images, filename):
"""Saves all processed images to a series of files."""
for idx, image in enumerate(images):
try:
fn = filename.format(idx + 1)
click.echo(f"Saving '{image.filename}' as '{fn}'")
yield image.save(fn)
except Exception as e:
click.echo(f"Could not save image '{image.filename}': {e}", err=True)
@cli.command("display")
@processor
def display_cmd(images):
"""Opens all images in an image viewer."""
for image in images:
click.echo(f"Displaying '{image.filename}'")
image.show()
yield image
@cli.command("resize")
@click.option("-w", "--width", type=int, help="The new width of the image.")
@click.option("-h", "--height", type=int, help="The new height of the image.")
@processor
def resize_cmd(images, width, height):
"""Resizes an image by fitting it into the box without changing
the aspect ratio.
"""
for image in images:
w, h = (width or image.size[0], height or image.size[1])
click.echo(f"Resizing '{image.filename}' to {w}x{h}")
image.thumbnail((w, h))
yield image
@cli.command("crop")
@click.option(
"-b", "--border", type=int, help="Crop the image from all sides by this amount."
)
@processor
def crop_cmd(images, border):
"""Crops an image from all edges."""
for image in images:
box = [0, 0, image.size[0], image.size[1]]
if border is not None:
for idx, val in enumerate(box):
box[idx] = max(0, val - border)
click.echo(f"Cropping '{image.filename}' by {border}px")
yield copy_filename(image.crop(box), image)
else:
yield image
def convert_rotation(ctx, param, value):
if value is None:
return
value = value.lower()
if value in ("90", "r", "right"):
return (Image.ROTATE_90, 90)
if value in ("180", "-180"):
return (Image.ROTATE_180, 180)
if value in ("-90", "270", "l", "left"):
return (Image.ROTATE_270, 270)
raise click.BadParameter(f"invalid rotation '{value}'")
def convert_flip(ctx, param, value):
if value is None:
return
value = value.lower()
if value in ("lr", "leftright"):
return (Image.FLIP_LEFT_RIGHT, "left to right")
if value in ("tb", "topbottom", "upsidedown", "ud"):
return (Image.FLIP_LEFT_RIGHT, "top to bottom")
raise click.BadParameter(f"invalid flip '{value}'")
@cli.command("transpose")
@click.option(
"-r", "--rotate", callback=convert_rotation, help="Rotates the image (in degrees)"
)
@click.option("-f", "--flip", callback=convert_flip, help="Flips the image [LR / TB]")
@processor
def transpose_cmd(images, rotate, flip):
"""Transposes an image by either rotating or flipping it."""
for image in images:
if rotate is not None:
mode, degrees = rotate
click.echo(f"Rotate '{image.filename}' by {degrees}deg")
image = copy_filename(image.transpose(mode), image)
if flip is not None:
mode, direction = flip
click.echo(f"Flip '{image.filename}' {direction}")
image = copy_filename(image.transpose(mode), image)
yield image
@cli.command("blur")
@click.option("-r", "--radius", default=2, show_default=True, help="The blur radius.")
@processor
def blur_cmd(images, radius):
"""Applies gaussian blur."""
blur = ImageFilter.GaussianBlur(radius)
for image in images:
click.echo(f"Blurring '{image.filename}' by {radius}px")
yield copy_filename(image.filter(blur), image)
@cli.command("smoothen")
@click.option(
"-i",
"--iterations",
default=1,
show_default=True,
help="How many iterations of the smoothen filter to run.",
)
@processor
def smoothen_cmd(images, iterations):
"""Applies a smoothening filter."""
for image in images:
click.echo(
f"Smoothening {image.filename!r} {iterations}"
f" time{'s' if iterations != 1 else ''}"
)
for _ in range(iterations):
image = copy_filename(image.filter(ImageFilter.BLUR), image)
yield image
@cli.command("emboss")
@processor
def emboss_cmd(images):
"""Embosses an image."""
for image in images:
click.echo(f"Embossing '{image.filename}'")
yield copy_filename(image.filter(ImageFilter.EMBOSS), image)
@cli.command("sharpen")
@click.option(
"-f", "--factor", default=2.0, help="Sharpens the image.", show_default=True
)
@processor
def sharpen_cmd(images, factor):
"""Sharpens an image."""
for image in images:
click.echo(f"Sharpen '{image.filename}' by {factor}")
enhancer = ImageEnhance.Sharpness(image)
yield copy_filename(enhancer.enhance(max(1.0, factor)), image)
@cli.command("paste")
@click.option("-l", "--left", default=0, help="Offset from left.")
@click.option("-r", "--right", default=0, help="Offset from right.")
@processor
def paste_cmd(images, left, right):
"""Pastes the second image on the first image and leaves the rest
unchanged.
"""
imageiter = iter(images)
image = next(imageiter, None)
to_paste = next(imageiter, None)
if to_paste is None:
if image is not None:
yield image
return
click.echo(f"Paste '{to_paste.filename}' on '{image.filename}'")
mask = None
if to_paste.mode == "RGBA" or "transparency" in to_paste.info:
mask = to_paste
image.paste(to_paste, (left, right), mask)
image.filename += f"+{to_paste.filename}"
yield image
yield from imageiter

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-imagepipe",
version="1.0",
py_modules=["imagepipe"],
include_package_data=True,
install_requires=["click", "pillow"],
entry_points="""
[console_scripts]
imagepipe=imagepipe:cli
""",
)

View file

@ -1,10 +0,0 @@
$ inout_
inout is a simple example of an application that
can read from files and write to files but also
accept input from stdin or write to stdout.
Usage:
$ pip install --editable .
$ inout input_file.txt output_file.txt

View file

@ -1,30 +0,0 @@
import click
@click.command()
@click.argument("input", type=click.File("rb"), nargs=-1)
@click.argument("output", type=click.File("wb"))
def cli(input, output):
"""This script works similar to the Unix `cat` command but it writes
into a specific file (which could be the standard output as denoted by
the ``-`` sign).
\b
Copy stdin to stdout:
inout - -
\b
Copy foo.txt and bar.txt to stdout:
inout foo.txt bar.txt -
\b
Write stdin into the file foo.txt
inout - foo.txt
"""
for f in input:
while True:
chunk = f.read(1024)
if not chunk:
break
output.write(chunk)
output.flush()

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-inout",
version="0.1",
py_modules=["inout"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
inout=inout:cli
""",
)

View file

@ -1,14 +0,0 @@
$ naval_
naval is a simple example of an application that
is ported from the docopt example of the same name.
Unlike the original this one also runs some code and
prints messages and it's command line interface was
changed slightly to make more sense with established
POSIX semantics.
Usage:
$ pip install --editable .
$ naval --help

View file

@ -1,72 +0,0 @@
import click
@click.group()
@click.version_option()
def cli():
"""Naval Fate.
This is the docopt example adopted to Click but with some actual
commands implemented and not just the empty parsing which really
is not all that interesting.
"""
@cli.group()
def ship():
"""Manages ships."""
@ship.command("new")
@click.argument("name")
def ship_new(name):
"""Creates a new ship."""
click.echo(f"Created ship {name}")
@ship.command("move")
@click.argument("ship")
@click.argument("x", type=float)
@click.argument("y", type=float)
@click.option("--speed", metavar="KN", default=10, help="Speed in knots.")
def ship_move(ship, x, y, speed):
"""Moves SHIP to the new location X,Y."""
click.echo(f"Moving ship {ship} to {x},{y} with speed {speed}")
@ship.command("shoot")
@click.argument("ship")
@click.argument("x", type=float)
@click.argument("y", type=float)
def ship_shoot(ship, x, y):
"""Makes SHIP fire to X,Y."""
click.echo(f"Ship {ship} fires to {x},{y}")
@cli.group("mine")
def mine():
"""Manages mines."""
@mine.command("set")
@click.argument("x", type=float)
@click.argument("y", type=float)
@click.option(
"ty",
"--moored",
flag_value="moored",
default=True,
help="Moored (anchored) mine. Default.",
)
@click.option("ty", "--drifting", flag_value="drifting", help="Drifting mine.")
def mine_set(x, y, ty):
"""Sets a mine at a specific coordinate."""
click.echo(f"Set {ty} mine at {x},{y}")
@mine.command("remove")
@click.argument("x", type=float)
@click.argument("y", type=float)
def mine_remove(x, y):
"""Removes a mine at a specific coordinate."""
click.echo(f"Removed mine at {x},{y}")

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-naval",
version="2.0",
py_modules=["naval"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
naval=naval:cli
""",
)

View file

@ -1,9 +0,0 @@
$ repo_
repo is a simple example of an application that looks
and works similar to hg or git.
Usage:
$ pip install --editable .
$ repo --help

View file

@ -1,166 +0,0 @@
import os
import posixpath
import sys
import click
class Repo:
def __init__(self, home):
self.home = home
self.config = {}
self.verbose = False
def set_config(self, key, value):
self.config[key] = value
if self.verbose:
click.echo(f" config[{key}] = {value}", file=sys.stderr)
def __repr__(self):
return f"<Repo {self.home}>"
pass_repo = click.make_pass_decorator(Repo)
@click.group()
@click.option(
"--repo-home",
envvar="REPO_HOME",
default=".repo",
metavar="PATH",
help="Changes the repository folder location.",
)
@click.option(
"--config",
nargs=2,
multiple=True,
metavar="KEY VALUE",
help="Overrides a config key/value pair.",
)
@click.option("--verbose", "-v", is_flag=True, help="Enables verbose mode.")
@click.version_option("1.0")
@click.pass_context
def cli(ctx, repo_home, config, verbose):
"""Repo is a command line tool that showcases how to build complex
command line interfaces with Click.
This tool is supposed to look like a distributed version control
system to show how something like this can be structured.
"""
# Create a repo object and remember it as as the context object. From
# this point onwards other commands can refer to it by using the
# @pass_repo decorator.
ctx.obj = Repo(os.path.abspath(repo_home))
ctx.obj.verbose = verbose
for key, value in config:
ctx.obj.set_config(key, value)
@cli.command()
@click.argument("src")
@click.argument("dest", required=False)
@click.option(
"--shallow/--deep",
default=False,
help="Makes a checkout shallow or deep. Deep by default.",
)
@click.option(
"--rev", "-r", default="HEAD", help="Clone a specific revision instead of HEAD."
)
@pass_repo
def clone(repo, src, dest, shallow, rev):
"""Clones a repository.
This will clone the repository at SRC into the folder DEST. If DEST
is not provided this will automatically use the last path component
of SRC and create that folder.
"""
if dest is None:
dest = posixpath.split(src)[-1] or "."
click.echo(f"Cloning repo {src} to {os.path.basename(dest)}")
repo.home = dest
if shallow:
click.echo("Making shallow checkout")
click.echo(f"Checking out revision {rev}")
@cli.command()
@click.confirmation_option()
@pass_repo
def delete(repo):
"""Deletes a repository.
This will throw away the current repository.
"""
click.echo(f"Destroying repo {repo.home}")
click.echo("Deleted!")
@cli.command()
@click.option("--username", prompt=True, help="The developer's shown username.")
@click.option("--email", prompt="E-Mail", help="The developer's email address")
@click.password_option(help="The login password.")
@pass_repo
def setuser(repo, username, email, password):
"""Sets the user credentials.
This will override the current user config.
"""
repo.set_config("username", username)
repo.set_config("email", email)
repo.set_config("password", "*" * len(password))
click.echo("Changed credentials.")
@cli.command()
@click.option(
"--message",
"-m",
multiple=True,
help="The commit message. If provided multiple times each"
" argument gets converted into a new line.",
)
@click.argument("files", nargs=-1, type=click.Path())
@pass_repo
def commit(repo, files, message):
"""Commits outstanding changes.
Commit changes to the given files into the repository. You will need to
"repo push" to push up your changes to other repositories.
If a list of files is omitted, all changes reported by "repo status"
will be committed.
"""
if not message:
marker = "# Files to be committed:"
hint = ["", "", marker, "#"]
for file in files:
hint.append(f"# U {file}")
message = click.edit("\n".join(hint))
if message is None:
click.echo("Aborted!")
return
msg = message.split(marker)[0].rstrip()
if not msg:
click.echo("Aborted! Empty commit message")
return
else:
msg = "\n".join(message)
click.echo(f"Files to be committed: {files}")
click.echo(f"Commit message:\n{msg}")
@cli.command(short_help="Copies files.")
@click.option(
"--force", is_flag=True, help="forcibly copy over an existing managed file"
)
@click.argument("src", nargs=-1, type=click.Path())
@click.argument("dst", type=click.Path())
@pass_repo
def copy(repo, src, dst, force):
"""Copies one or multiple files to a new location. This copies all
files from SRC to DST.
"""
for fn in src:
click.echo(f"Copy from {fn} -> {dst}")

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-repo",
version="0.1",
py_modules=["repo"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
repo=repo:cli
""",
)

View file

@ -1,9 +0,0 @@
$ termui_
termui showcases the different terminal UI helpers that
Click provides.
Usage:
$ pip install --editable .
$ termui --help

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-termui",
version="1.0",
py_modules=["termui"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
termui=termui:cli
""",
)

View file

@ -1,169 +0,0 @@
import math
import random
import time
import click
@click.group()
def cli():
"""This script showcases different terminal UI helpers in Click."""
pass
@cli.command()
def colordemo():
"""Demonstrates ANSI color support."""
for color in "red", "green", "blue":
click.echo(click.style(f"I am colored {color}", fg=color))
click.echo(click.style(f"I am background colored {color}", bg=color))
@cli.command()
def pager():
"""Demonstrates using the pager."""
lines = []
for x in range(200):
lines.append(f"{click.style(str(x), fg='green')}. Hello World!")
click.echo_via_pager("\n".join(lines))
@cli.command()
@click.option(
"--count",
default=8000,
type=click.IntRange(1, 100000),
help="The number of items to process.",
)
def progress(count):
"""Demonstrates the progress bar."""
items = range(count)
def process_slowly(item):
time.sleep(0.002 * random.random())
def filter(items):
for item in items:
if random.random() > 0.3:
yield item
with click.progressbar(
items, label="Processing accounts", fill_char=click.style("#", fg="green")
) as bar:
for item in bar:
process_slowly(item)
def show_item(item):
if item is not None:
return f"Item #{item}"
with click.progressbar(
filter(items),
label="Committing transaction",
fill_char=click.style("#", fg="yellow"),
item_show_func=show_item,
) as bar:
for item in bar:
process_slowly(item)
with click.progressbar(
length=count,
label="Counting",
bar_template="%(label)s %(bar)s | %(info)s",
fill_char=click.style("", fg="cyan"),
empty_char=" ",
) as bar:
for item in bar:
process_slowly(item)
with click.progressbar(
length=count,
width=0,
show_percent=False,
show_eta=False,
fill_char=click.style("#", fg="magenta"),
) as bar:
for item in bar:
process_slowly(item)
# 'Non-linear progress bar'
steps = [math.exp(x * 1.0 / 20) - 1 for x in range(20)]
count = int(sum(steps))
with click.progressbar(
length=count,
show_percent=False,
label="Slowing progress bar",
fill_char=click.style("", fg="green"),
) as bar:
for item in steps:
time.sleep(item)
bar.update(item)
@cli.command()
@click.argument("url")
def open(url):
"""Opens a file or URL In the default application."""
click.launch(url)
@cli.command()
@click.argument("url")
def locate(url):
"""Opens a file or URL In the default application."""
click.launch(url, locate=True)
@cli.command()
def edit():
"""Opens an editor with some text in it."""
MARKER = "# Everything below is ignored\n"
message = click.edit(f"\n\n{MARKER}")
if message is not None:
msg = message.split(MARKER, 1)[0].rstrip("\n")
if not msg:
click.echo("Empty message!")
else:
click.echo(f"Message:\n{msg}")
else:
click.echo("You did not enter anything!")
@cli.command()
def clear():
"""Clears the entire screen."""
click.clear()
@cli.command()
def pause():
"""Waits for the user to press a button."""
click.pause()
@cli.command()
def menu():
"""Shows a simple menu."""
menu = "main"
while True:
if menu == "main":
click.echo("Main menu:")
click.echo(" d: debug menu")
click.echo(" q: quit")
char = click.getchar()
if char == "d":
menu = "debug"
elif char == "q":
menu = "quit"
else:
click.echo("Invalid input")
elif menu == "debug":
click.echo("Debug menu")
click.echo(" b: back")
char = click.getchar()
if char == "b":
menu = "main"
else:
click.echo("Invalid input")
elif menu == "quit":
return

View file

@ -1,12 +0,0 @@
$ validation_
validation is a simple example of an application that
performs custom validation of parameters in different
ways.
This example requires Click 2.0 or higher.
Usage:
$ pip install --editable .
$ validation --help

View file

@ -1,13 +0,0 @@
from setuptools import setup
setup(
name="click-example-validation",
version="1.0",
py_modules=["validation"],
include_package_data=True,
install_requires=["click"],
entry_points="""
[console_scripts]
validation=validation:cli
""",
)

View file

@ -1,48 +0,0 @@
from urllib import parse as urlparse
import click
def validate_count(ctx, param, value):
if value < 0 or value % 2 != 0:
raise click.BadParameter("Should be a positive, even integer.")
return value
class URL(click.ParamType):
name = "url"
def convert(self, value, param, ctx):
if not isinstance(value, tuple):
value = urlparse.urlparse(value)
if value.scheme not in ("http", "https"):
self.fail(
f"invalid URL scheme ({value.scheme}). Only HTTP URLs are allowed",
param,
ctx,
)
return value
@click.command()
@click.option(
"--count", default=2, callback=validate_count, help="A positive even number."
)
@click.option("--foo", help="A mysterious parameter.")
@click.option("--url", help="A URL", type=URL())
@click.version_option()
def cli(count, foo, url):
"""Validation.
This example validates parameters in different ways. It does it
through callbacks, through a custom type as well as by validating
manually in the function.
"""
if foo is not None and foo != "wat":
raise click.BadParameter(
'If a value is provided it needs to be the value "wat".',
param_hint=["--foo"],
)
click.echo(f"count: {count}")
click.echo(f"foo: {foo}")
click.echo(f"url: {url!r}")

Binary file not shown.

View file

@ -0,0 +1 @@
e716ec6d0f61577fc6f8827ee2f0d7d0200b7f60

Some files were not shown because too many files have changed in this diff Show more