Metadata-Version: 2.4
Name: click-compose
Version: 2025.10.27
Summary: Composable Click callback utilities for building flexible CLI applications.
Author-email: Adam Dangoor <adamdangoor@gmail.com>
License-Expression: MIT
Project-URL: Source, https://github.com/adamtheturtle/click-compose
Keywords: callbacks,cli,click,validation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/x-rst
License-File: LICENSE
Requires-Dist: click>=8.0.0
Provides-Extra: dev
Requires-Dist: actionlint-py==1.7.8.24; extra == "dev"
Requires-Dist: check-manifest==0.51; extra == "dev"
Requires-Dist: deptry==0.23.1; extra == "dev"
Requires-Dist: doc8==2.0.0; extra == "dev"
Requires-Dist: docformatter==1.7.7; extra == "dev"
Requires-Dist: furo==2025.9.25; extra == "dev"
Requires-Dist: interrogate==1.7.0; extra == "dev"
Requires-Dist: mypy[faster-cache]==1.18.2; extra == "dev"
Requires-Dist: mypy-strict-kwargs==2025.4.3; extra == "dev"
Requires-Dist: packaging>=24.0; extra == "dev"
Requires-Dist: pre-commit==4.3.0; extra == "dev"
Requires-Dist: pydocstyle==6.3; extra == "dev"
Requires-Dist: pygments==2.19.2; extra == "dev"
Requires-Dist: pylint[spelling]==4.0.2; extra == "dev"
Requires-Dist: pylint-per-file-ignores==3.1.0; extra == "dev"
Requires-Dist: pyproject-fmt==2.11.0; extra == "dev"
Requires-Dist: pyright==1.1.407; extra == "dev"
Requires-Dist: pyroma==5.0; extra == "dev"
Requires-Dist: pytest==8.4.2; extra == "dev"
Requires-Dist: pytest-cov==7.0.0; extra == "dev"
Requires-Dist: pytest-regressions==2.8.3; extra == "dev"
Requires-Dist: pyyaml==6.0.3; extra == "dev"
Requires-Dist: ruff==0.14.2; extra == "dev"
Requires-Dist: shellcheck-py==0.11.0.1; extra == "dev"
Requires-Dist: shfmt-py==3.12.0.2; extra == "dev"
Requires-Dist: sphinx==8.2.3; extra == "dev"
Requires-Dist: sphinx-copybutton==0.5.2; extra == "dev"
Requires-Dist: sphinx-lint==1.0.0; extra == "dev"
Requires-Dist: sphinx-pyproject==0.3.0; extra == "dev"
Requires-Dist: sphinx-substitution-extensions==2025.10.24; extra == "dev"
Requires-Dist: sphinxcontrib-spelling==8.0.1; extra == "dev"
Requires-Dist: vulture==2.14; extra == "dev"
Requires-Dist: yamlfix==1.19.0; extra == "dev"
Provides-Extra: release
Requires-Dist: check-wheel-contents==0.6.3; extra == "release"
Dynamic: license-file

click-compose
=============

Composable Click callback utilities for building flexible CLI applications.

.. contents::
   :local:

Installation
------------

.. code-block:: shell

   $ pip install click-compose

Or with ``uv``:

.. code-block:: shell

   $ uv add click-compose

Quick Start
-----------

``click-compose`` provides two main utilities for composing Click callbacks:

multi_callback
~~~~~~~~~~~~~~

Combine multiple callbacks into a single callback that applies them in sequence:

.. code-block:: python

   import click
   from click_compose import multi_callback

   def validate_positive(ctx, param, value):
       if value <= 0:
           raise click.BadParameter("Must be positive")
       return value

   def validate_max_100(ctx, param, value):
       if value > 100:
           raise click.BadParameter("Must be <= 100")
       return value

   @click.command()
   @click.option(
       "--count",
       type=int,
       callback=multi_callback([validate_positive, validate_max_100]),
   )
   def cmd(count):
       click.echo(f"Count: {count}")

sequence_validator
~~~~~~~~~~~~~~~~~~

Apply a validator to each element in a sequence (useful with ``multiple=True``):

.. code-block:: python

   import click
   from click_compose import sequence_validator

   def validate_positive(ctx, param, value):
       if value <= 0:
           raise click.BadParameter("Must be positive")
       return value

   @click.command()
   @click.option(
       "--numbers",
       multiple=True,
       type=int,
       callback=sequence_validator(validate_positive),
   )
   def cmd(numbers):
       click.echo(f"Sum: {sum(numbers)}")

Documentation
-------------

See the `full documentation <https://adamtheturtle.github.io/click-compose/>`__.
