Skip to content

Commit

Permalink
docs: cleanup README, rearrange the rest
Browse files Browse the repository at this point in the history
  • Loading branch information
neithere committed Jan 1, 2024
1 parent 9c35a72 commit 971ce4c
Show file tree
Hide file tree
Showing 20 changed files with 157 additions and 197 deletions.
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ build:

# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/source/conf.py
configuration: docs/conf.py

# NOTE: PDF generation was intentionally disabled due to failed builds.
# Should you require enabling this, please make sure that it's tested.
Expand Down
File renamed without changes.
255 changes: 70 additions & 185 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Argh: The Natural CLI
=====================
Argh: The Effortless CLI
========================

.. image:: https://github.com/neithere/argh/actions/workflows/lint-and-test.yml/badge.svg
:target: https://github.com/neithere/argh/actions/workflows/lint-and-test.yml
Expand All @@ -25,21 +25,71 @@ Argh: The Natural CLI
.. image:: https://readthedocs.org/projects/argh/badge/?version=latest
:target: http://argh.readthedocs.org/en/latest/

**The power of Argparse with plain Python functions!**

Building a command-line interface? Found yourself uttering "argh!" while
struggling with the API of `argparse`? Don't like the complexity but need
the power?

.. epigraph::
`Argh` builds on the power of `argparse` (which comes with Python) and makes it
really easy to use. It eliminates the complex API and lets you "dispatch"
ordinary Python functions as CLI commands.

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

Everything should be made as simple as possible, but no simpler.
::

-- Albert Einstein (probably)
$ pip install argh

`Argh` is a smart wrapper for `argparse`. `Argparse` is a very powerful tool;
`Argh` just makes it easy to use.
Example
-------

In a nutshell
-------------
.. code-block:: python
import argh
def verify_paths(paths: list[str], *, verbose: bool = False):
"""
Verify that all given paths exist.
"""
for path in paths:
if verbose:
print(f"Checking {path}...")
assert os.path.exists(path)
argh.dispatch_command(verify_paths)
Now you can run the script like this:

.. code-block:: bash
$ python app.py foo.txt bar/quux.txt
$ python app.py foo.txt bar/quux.txt --verbose
Checking foo.txt...
Checking bar/quux.txt...
$ python app.py -h
usage: app.py [-h] [-v] [paths ...]
Verify that all given paths exist.
positional arguments:
paths -
options:
-h, --help show this help message and exit
-v, --verbose False
Please check the documentation for examples of multiple commands, modularity,
help generation, advanced type annotations inspection, decorators and more:

* `Quick Start <https://argh.readthedocs.io/en/latest/quickstart.html>`_
* `Tutorial <https://argh.readthedocs.io/en/latest/tutorial.html>`_

Why Argh?
---------

`Argh`-powered applications are *simple* but *flexible*:

Expand Down Expand Up @@ -80,198 +130,33 @@ In a nutshell
:Compact:
No dependencies apart from Python's standard library.

Sounds good? Dive in! :)

* `Quick Start <https://argh.readthedocs.io/en/latest/quickstart.html>`_
* `Tutorial <https://argh.readthedocs.io/en/latest/tutorial.html>`_

Relation to argparse
--------------------

`Argh` is fully compatible with `argparse`. You can mix `Argh`-agnostic and
`Argh`-aware code. Just keep in mind that the dispatcher does some extra work
that a custom dispatcher may not do.

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

::

$ pip install argh

Examples
--------

Hello World
...........

A very simple application with one command:

.. code-block:: python
import argh
def main() -> str:
return "Hello world"
argh.dispatch_command(main)
Run it:

.. code-block:: bash
$ ./app.py
Hello world
Type Annotations
................

Type annotations are used to infer argument types:

.. code-block:: python
def summarise(numbers: list[int]) -> int:
return sum(numbers)
argh.dispatch_command(summarise)
Run it (note that ``nargs="+"`` + ``type=int`` were inferred from the
annotation):

.. code-block:: bash
$ ./app.py 1 2 3
6
Multiple Commands
.................

An app with multiple commands:

.. code-block:: python
import argh
from my_commands import hello, echo
argh.dispatch_commands([hello, echo])
Run it:

.. code-block:: bash
$ ./app.py echo Hey
Hey
Modularity
..........

A potentially modular application with more control over the process:

.. code-block:: python
import argh
# declaring:
def echo(text):
"Returns given word as is."
return text
def greet(name: str, *, greeting: str = "Hello") -> str:
"Greets the user with given name. The greeting is customizable."
return f"{greeting}, {name}!"
# assembling:
parser = argh.ArghParser()
parser.add_commands([echo, greet])
# dispatching:
if __name__ == "__main__":
parser.dispatch()
.. code-block:: bash
$ ./app.py greet Andy
Hello, Andy
$ ./app.py greet Andy -g Arrrgh
Arrrgh, Andy
Here's the auto-generated help for this application (note how the docstrings
are reused)::

$ ./app.py --help

usage: app.py {echo,greet} ...

positional arguments:
echo Returns given word as is.
greet Greets the user with given name. The greeting is customizable.

...and for a specific command (an ordinary function signature is converted
to CLI arguments)::

$ ./app.py --help greet

usage: app.py greet [-g GREETING] name

Greets the user with given name. The greeting is customizable.

positional arguments:
name

optional arguments:
-g GREETING, --greeting GREETING 'Hello'

(The help messages have been simplified a bit for brevity.)

Decorators
..........

`Argh` easily maps plain Python functions to CLI. Sometimes this is not
enough; in these cases the powerful API of `argparse` is also available:

.. code-block:: python
@arg("words", default="hello world", nargs="+", help="The message")
def echo(words: list[str]) -> str:
return " ".join(words)
Please note that decorators will soon be fully replaced with annotations.

Links
-----

* `Project home page`_ (GitHub)
* `Documentation`_ (Read the Docs)
* `Package distribution`_ (PyPI)
* Questions, requests, bug reports, etc.:

* `Issue tracker`_ (GitHub)
* Direct e-mail (neithere at gmail com)
See also the `project page on GitHub`_, `documentation`_ and `PyPI page`_.

.. _project home page: http://github.com/neithere/argh/
.. _project page on GitHub: http://github.com/neithere/argh/
.. _documentation: http://argh.readthedocs.org
.. _package distribution: http://pypi.python.org/pypi/argh
.. _issue tracker: http://github.com/neithere/argh/issues/
.. _PyPI page: http://pypi.python.org/pypi/argh

Author
------

Developed by Andrey Mikhaylenko since 2010.

See file `AUTHORS.rst` for a list of contributors to this library.
See `contributors <https://argh.readthedocs.io/en/latest/contributors.html>`_
for a list of contributors to this library.

Support
-------
Contribute
----------

The fastest way to improve this project is to submit tested and documented
patches or detailed bug reports.

You can also `donate via Liberapay`_. This may speed up development or simply
Donate
------

You can `donate via Liberapay`_. This may speed up development or simply
make the original author happy :)

.. _donate via Liberapay: https://liberapay.com/neithere/donate
Expand Down
72 changes: 72 additions & 0 deletions docs/CONTRIBUTING.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
Contributing to Argh
====================

Argh would not be so good without the FOSS community.

Your contributions matter!

This document describes how to contribute to Argh.

Issues, Bug reports, Feature requests
-------------------------------------

If you have a question, a bug report or a feature request, please
`create an issue <https://github.com/neithere/argh/issues/new>`.

Please include, if possible:

* a minimal reproducible example;
* a description of the expected and observed behaviour;
* a description of your environment (OS, Python version, etc.).

Code changes
------------

Starting work on a new release
..............................

* Assign tasks to the release milestone.
* Create a release branch (e.g. `release/v0.30.4`) from `master`.
* Bump version in `pyproject.toml`.
* Create section in `CHANGES.rst` for the new version.
* Create a pull request from the release branch to `master`.

Contributing to the release
...........................

* Create a feature branch from the release branch.
* Make changes, commit, push, create a pull request (target branch = release).
* Make sure the pipeline is green.
* Ask for review.
* Merge the pull request.

* Default strategy: squash. Fast-forward or rebase if:

- there are multiple commits from different authors;
- there are commits which are important to keep separate.

Finalising the release
......................

* Make sure the pipeline is green.
* Make sure all tasks in the release milestone are "ready for release".
* Update `CHANGES.rst`, then proof-read on RTD:

* make sure all merged PRs are mentioned;
* add current date in section title.

* Create a GitHub release: https://github.com/neithere/argh/releases/new

* based on the release branch;
* new tag in the format `v0.30.4`;
* tick "Set as the latest release" checkbox;
* click the "Generate release notes" button;
* add link to RTD changelog.

* Monitor the release pipeline: https://github.com/neithere/argh/actions

* if it failed, fix and re-create the release with the same tag.

* Merge the release branch into `master`.

* don't squash!
2 changes: 1 addition & 1 deletion docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
SOURCEDIR = .
BUILDDIR = build

# Put it first so that "make" without argument is like "make help".
Expand Down
1 change: 1 addition & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. include:: ../CHANGELOG.rst
2 changes: 1 addition & 1 deletion docs/source/conf.py → docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

current_year = date.today().year

config = SphinxConfig("../../pyproject.toml")
config = SphinxConfig("../pyproject.toml")

# -- Project information

Expand Down
Loading

0 comments on commit 971ce4c

Please sign in to comment.