Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python 3.12 support #64

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 7 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
Create **man pages** for [click](https://github.com/pallets/click) application as easy as this:

```bash
python3 setup.py --command-packages=click_man.commands man_pages
click-man foo
```

where `foo` is the name of your script, as defined in [`console_scripts`](https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html#the-console-scripts-entry-point).

→ Checkout the [debian packaging example](#debian-packages)

## What it does

*click-man* will generate one man page per command of your click CLI application specified in `console_scripts` in your `setup.py`.
*click-man* will generate one man page per command of your click CLI application specified in `console_scripts` in your `setup.py` / `setup.cfg` / `pyproject.toml`.

## Installation

Expand Down Expand Up @@ -47,29 +49,14 @@ To specify a target directory for the man pages, use the `--target` option:
click-man --target path/to/man/pages commandname
```

### Use with setuptools

**click-man** provides a sane setuptools command extension which can be used like the following:

```bash
python3 setup.py --command-packages=click_man.commands man_pages
```

or specify the man pages target directory:

```bash
python3 setup.py --command-packages=click_man.commands man_pages --target path/to/man/pages
```

### Automatic man page installation with setuptools and pip

This approach of installing man pages is problematic for various reasons:

#### (1) Man pages are a UNIX thing

Python in general and with that pip and setuptools are aimed to be platform independent.
Man pages are **not**: they are a UNIX thing which means setuptools does not provide a sane
solution to generate and install man pages.
Man pages are **not**: they are a UNIX thing which means setuptools does not provide a sane solution to generate and install man pages.
We should consider using automatic man page installation only with vendor specific packaging, e.g. for `*.deb` or `*.rpm` packages.

#### (2) Man pages are not compatible with Python virtualenvs
Expand All @@ -88,8 +75,7 @@ the version and behavior available in any given virtualenv.
#### (3) We want to generate man pages on the fly

First, we do not want to commit man pages to our source control.
We want to generate them on the fly. Either
during build or installation time.
We want to generate them on the fly, either during build or installation time.

With setuptools and pip we face two problems:

Expand All @@ -109,7 +95,7 @@ We override the rule provided by `dh_installman` to generate our man pages in ad

```Makefile
override_dh_installman:
python3 setup.py --command-packages=click_man.commands man_pages --target debian/tmp/manpages
click-man <executable> --target debian/tmp/manpages
dh_installman -O--buildsystem=pybuild
```

Expand Down
20 changes: 11 additions & 9 deletions click_man/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
:license: MIT, see LICENSE for more details.
"""

import importlib.metadata
import os

import click
from pkg_resources import iter_entry_points, get_distribution

from click_man.core import write_man_pages

Expand All @@ -20,7 +21,7 @@
@click.option('--target', '-t', default=os.path.join(os.getcwd(), 'man'),
type=click.Path(file_okay=False, dir_okay=True, resolve_path=True),
help='Target location for the man pages')
@click.version_option(get_distribution('click-man').version, '-V', '--version')
@click.version_option(importlib.metadata.version('click-man'), '-V', '--version')
@click.argument('name')
def cli(target, name):
"""
Expand All @@ -31,29 +32,30 @@ def cli(target, name):
The generated man pages are written to files in the directory given
by ``--target``.
"""
console_scripts = [ep for ep in iter_entry_points('console_scripts', name=name)]
entry_points = importlib.metadata.entry_points()
console_scripts = entry_points.select(group='console_scripts', name=name)
if len(console_scripts) < 1:
raise click.ClickException('"{0}" is not an installed console script.'.format(name))
# Only generate man pages for first console script
entry_point = console_scripts[0]
(entry_point,) = console_scripts

# create target directory if it does not exist yet
try:
os.makedirs(target)
except OSError:
pass

click.echo('Load entry point {0}'.format(name))
cli = entry_point.resolve()
cli = entry_point.load()

# If the entry point isn't a click.Command object, try to find it in the module
if not isinstance(cli, click.Command):
from importlib import import_module
from inspect import getmembers

if not entry_point.module_name:
if not entry_point.module:
raise click.ClickException('Could not find module name for "{0}".'.format(name))
ep_module = import_module(entry_point.module_name)
ep_module = import_module(entry_point.module)
ep_members = getmembers(ep_module, lambda x: isinstance(x, click.Command))

if len(ep_members) < 1:
Expand All @@ -62,7 +64,7 @@ def cli(target, name):
click.echo('Found alternate entry point {0} in {1}'.format(ep_name, name))

click.echo('Generate man pages for {0} in {1}'.format(name, target))
write_man_pages(name, cli, version=entry_point.dist.version, target_dir=target)
write_man_pages(name, cli, version=entry_point.version, target_dir=target)


if __name__ == '__main__':
Expand Down
5 changes: 0 additions & 5 deletions click_man/commands/__init__.py

This file was deleted.

67 changes: 0 additions & 67 deletions click_man/commands/man_pages.py

This file was deleted.