click-man-0.4.1/0000755000175000017500000000000013633452426012066 5ustar ryanryanclick-man-0.4.1/MANIFEST.in0000644000175000017500000000012313633452242013614 0ustar ryanryaninclude *.md include *.rst include *.txt include LICENSE recursive-include tests * click-man-0.4.1/requirements-dev.txt0000644000175000017500000000005713431773731016131 0ustar ryanryan-r requirements.txt sure nose rednose coverage click-man-0.4.1/setup.cfg0000644000175000017500000000004613633452426013707 0ustar ryanryan[egg_info] tag_build = tag_date = 0 click-man-0.4.1/requirements.txt0000644000175000017500000000000613431773731015347 0ustar ryanryanclick click-man-0.4.1/click_man/0000755000175000017500000000000013633452426014006 5ustar ryanryanclick-man-0.4.1/click_man/__init__.py0000644000175000017500000000000013431773731016106 0ustar ryanryanclick-man-0.4.1/click_man/commands/0000755000175000017500000000000013633452426015607 5ustar ryanryanclick-man-0.4.1/click_man/commands/__init__.py0000644000175000017500000000006713431773731017724 0ustar ryanryanfrom . import man_pages __all__ = [ 'man_pages' ] click-man-0.4.1/click_man/commands/man_pages.py0000644000175000017500000000411413633452233020107 0ustar ryanryan""" click-man - Generate man pages for click application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This module provides a setuptools command to generate man pages from a click application. :copyright: (c) 2016 by Timo Furrer. :license: MIT, see LICENSE for more details. """ import os from distutils.core import Command from distutils.errors import DistutilsSetupError from pkg_resources import EntryPoint from click_man.core import write_man_pages __all__ = ['man_pages'] class man_pages(Command): description = 'distutils command to generate man pages' user_options = [ ('target=', 't', 'Target location for the man pages'), ('version=', 'v', 'Version of the CLI application') ] boolean_options = [] def initialize_options(self): self.target = os.path.join(os.getcwd(), 'man') self.version = '' def finalize_options(self): self.target = os.path.abspath(self.target) # create target directory if it does not exist yet try: os.makedirs(self.target) except OSError: pass def run(self): """ Generate man pages for the scripts defined in distutils setup(). The cli application is gathered from the setuptools setup() function in setup.py. The generated man pages are written to files in the directory given by ``--target``. """ eps = EntryPoint.parse_map(self.distribution.entry_points or '') if 'console_scripts' not in eps or not eps['console_scripts']: raise DistutilsSetupError('No entry points defined in setup()') console_scripts = [(k, v) for k, v in eps['console_scripts'].items()] # FIXME: create own setup() attribute for CLI script configuration for name, entry_point in console_scripts: self.announce('Load entry point {0}'.format(name), level=2) cli = entry_point.resolve() self.announce('Generate man pages for {0}'.format(name), level=2) write_man_pages(name, cli, version=self.version, target_dir=self.target) click-man-0.4.1/click_man/__main__.py0000644000175000017500000000500513633452242016074 0ustar ryanryan""" click-man - Generate man pages for click application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This module provides a click CLI command to generate man pages from a click application. :copyright: (c) 2016 by Timo Furrer. :license: MIT, see LICENSE for more details. """ import os import click from pkg_resources import iter_entry_points, get_distribution from click_man.core import write_man_pages @click.command(context_settings={'help_option_names': ['-h', '--help']}) @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.argument('name') def cli(target, name): """ Generate man pages for the scripts defined in the ``console_acripts`` entry point. The cli application is gathered from entry points of installed packages. 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)] 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] # 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() # 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: raise click.ClickException('Could not find module name for "{0}".'.format(name)) ep_module = import_module(entry_point.module_name) ep_members = getmembers(ep_module, lambda x: isinstance(x, click.Command)) if len(ep_members) < 1: raise click.ClickException('Could not find click.Command object for "{0}".'.format(name)) (ep_name, cli) = ep_members[0] 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) if __name__ == '__main__': cli() click-man-0.4.1/click_man/man.py0000644000175000017500000000747313633452242015142 0ustar ryanryan""" click-man - Generate man pages for click application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This module provides functionality to write a man page from some given information about a CLI application. :copyright: (c) 2016 by Timo Furrer. :license: MIT, see LICENSE for more details. """ import os import time class ManPage(object): """ Represent a man page :param str command: the name of the command """ TITLE_KEYWORD = '.TH' SECTION_HEADING_KEYWORD = '.SH' PARAGRAPH_KEYWORD = '.PP' BOLD_KEYWORD = '.B' INDENT_KEYWORDD = '.TP' def __init__(self, command): #: Holds the command of the man page self.command = command #: Holds the short help of the man page self.short_help = '' #: Holds the synopsis of the man page self.synopsis = '' #: Holds the description of the man page self.description = '' #: Holds the version of the man page self.version = '1.0.0' #: Holds a list of tuple options of the man page # the first item in the tuple are the option switches # and the second one is the option's description self.options = [] #: Holds the commands of the man page self.commands = [] #: Holds the date of the man page creation time. self.date = time.strftime("%Y-%m-%d", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))) def replace_blank_lines(self, s): ''' Find any blank lines and replace them with .PP ''' lines = map(lambda l: self.PARAGRAPH_KEYWORD if l == '' else l, s.split('\n')) return '\n'.join(lines) def __str__(self): """ Generate and return the string representation of this man page. """ lines = [] # write title and footer lines.append('{0} "{1}" "1" "{2}" "{3}" "{4} Manual"'.format( self.TITLE_KEYWORD, self.command.upper(), self.date, self.version, self.command)) # write name section lines.append('{0} NAME'.format(self.SECTION_HEADING_KEYWORD)) lines.append(r'{0} \- {1}'.format(self.command.replace(' ', r'\-'), self.short_help)) # write synopsis lines.append('{0} SYNOPSIS'.format(self.SECTION_HEADING_KEYWORD)) lines.append('{0} {1}'.format(self.BOLD_KEYWORD, self.command)) lines.append(self.synopsis.replace('-', r'\-')) # write the description if self.description: lines.append('{0} DESCRIPTION'.format(self.SECTION_HEADING_KEYWORD)) lines.append(self.replace_blank_lines(self.description)) # write the options if self.options: lines.append('{0} OPTIONS'.format(self.SECTION_HEADING_KEYWORD)) for option, description in self.options: lines.append(self.INDENT_KEYWORDD) option_unpacked = option.replace('-', r'\-').split() lines.append(r'\fB{0}\fP{1}'.format(option_unpacked[0], (' ' + ' '.join(option_unpacked[1:])) if len(option_unpacked) > 1 else '')) lines.append(self.replace_blank_lines(description)) # write commands if self.commands: lines.append('{0} COMMANDS'.format(self.SECTION_HEADING_KEYWORD)) for name, description in self.commands: lines.append(self.PARAGRAPH_KEYWORD) lines.append(r'\fB{0}\fP'.format(name)) lines.append(' ' + self.replace_blank_lines(description)) lines.append(r' See \fB{0}-{1}(1)\fP for full documentation on the \fB{1}\fP command.'.format( self.command, name)) man_page = '\n'.join(lines) if not man_page.endswith('\n'): # Ensure man page ends with newline. man_page += '\n' return man_page click-man-0.4.1/click_man/core.py0000644000175000017500000000464413633452242015314 0ustar ryanryan""" click-man - Generate man pages for click application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This module implements the core functionality to generate man pages for entire click applications. :copyright: (c) 2016 by Timo Furrer. :license: MIT, see LICENSE for more details. """ import os from distutils.version import LooseVersion import click from .man import ManPage def generate_man_page(ctx, version=None): """ Generate documentation for the given command. :param click.Context ctx: the click context for the cli application. :rtype: str :returns: the generate man page from the given click Context. """ # Create man page with the details from the given context man_page = ManPage(ctx.command_path) man_page.version = version man_page.short_help = ctx.command.get_short_help_str() man_page.description = ctx.command.help man_page.synopsis = ' '.join(ctx.command.collect_usage_pieces(ctx)) man_page.options = [x.get_help_record(ctx) for x in ctx.command.params if isinstance(x, click.Option)] commands = getattr(ctx.command, 'commands', None) if commands: man_page.commands = [ (k, v.get_short_help_str()) for k, v in commands.items() ] return str(man_page) def write_man_pages(name, cli, parent_ctx=None, version=None, target_dir=None): """ Generate man page files recursively for the given click cli function. :param str name: the cli name :param cli: the cli instance :param click.Context parent_ctx: the parent click context :param str target_dir: the directory where the generated man pages are stored. """ ctx = click.Context(cli, info_name=name, parent=parent_ctx) man_page = generate_man_page(ctx, version) path = '{0}.1'.format(ctx.command_path.replace(' ', '-')) if target_dir: path = os.path.join(target_dir, path) with open(path, 'w+') as f: f.write(man_page) commands = getattr(cli, 'commands', {}) for name, command in commands.items(): if LooseVersion(click.__version__) >= LooseVersion("7.0"): # Since Click 7.0, we have been able to mark commands as hidden if command.hidden: # Do not write a man page for a hidden command continue write_man_pages(name, command, parent_ctx=ctx, version=version, target_dir=target_dir) click-man-0.4.1/CHANGELOG.md0000644000175000017500000000250713633452242013677 0ustar ryanryan# Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] *Nothing here yet* ## [v0.4.0] - Discover command if not in entry_points ## [v0.3.0] - Make compatible with click >= 7.0 ## [v0.2.2] - Release ## [v0.2.1] ### Added - Add information to man page for commands. Refs #3 ### Fixed - Use hyphens to split words in a command. Refs #2 ## [v0.2.0] ### Added - Allow to specify version via command line - Proof-of-concept for debian packaging ## [v0.1.1] ### Fixed - Several small bugs - Improved README ## [v0.1.0] ### Added - Initial release ## Info Please also see `git log` [Unreleased]: https://github.com/click-contrib/click-man/compare/v0.4.0...HEAD [v0.4.0]: https://github.com/click-contrib/click-man/compare/v0.3.0...v0.4.0 [v0.3.0]: https://github.com/click-contrib/click-man/compare/v0.2.2...v0.3.0 [v0.2.2]: https://github.com/click-contrib/click-man/compare/v0.2.1...v0.2.2 [v0.2.1]: https://github.com/click-contrib/click-man/compare/v0.2.0...v0.2.1 [v0.2.0]: https://github.com/click-contrib/click-man/compare/v0.1.1...v0.2.0 [v0.1.1]: https://github.com/click-contrib/click-man/compare/v0.1.0...v0.1.1 [v0.1.0]: https://github.com/click-contrib/click-man/compare/30626839cc048856f799eb0bcd9e731fff4221dc...v0.1.0 click-man-0.4.1/LICENSE0000644000175000017500000000205413431773731013075 0ustar ryanryanMIT License Copyright (c) 2016 Timo Furrer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. click-man-0.4.1/click_man.egg-info/0000755000175000017500000000000013633452426015500 5ustar ryanryanclick-man-0.4.1/click_man.egg-info/top_level.txt0000644000175000017500000000001213633452426020223 0ustar ryanryanclick_man click-man-0.4.1/click_man.egg-info/entry_points.txt0000644000175000017500000000006613633452426021000 0ustar ryanryan[console_scripts] click-man = click_man.__main__:cli click-man-0.4.1/click_man.egg-info/SOURCES.txt0000644000175000017500000000072313633452426017366 0ustar ryanryanCHANGELOG.md LICENSE MANIFEST.in README.md requirements-dev.txt requirements.txt setup.py click_man/__init__.py click_man/__main__.py click_man/core.py click_man/man.py click_man.egg-info/PKG-INFO click_man.egg-info/SOURCES.txt click_man.egg-info/dependency_links.txt click_man.egg-info/entry_points.txt click_man.egg-info/requires.txt click_man.egg-info/top_level.txt click_man/commands/__init__.py click_man/commands/man_pages.py tests/__init__.py tests/test_man.pyclick-man-0.4.1/click_man.egg-info/requires.txt0000644000175000017500000000000613633452426020074 0ustar ryanryanclick click-man-0.4.1/click_man.egg-info/PKG-INFO0000644000175000017500000001347713633452426016611 0ustar ryanryanMetadata-Version: 2.1 Name: click-man Version: 0.4.1 Summary: Generate man pages for click based CLI applications Home-page: https://github.com/click-contrib/click-man Author: Timo Furrer Author-email: tuxtimo@gmail.com License: MIT Description: # click-man [![Build Status](https://travis-ci.org/click-contrib/click-man.svg?branch=master)](https://travis-ci.org/click-contrib/click-man) [![PyPI Package version](https://badge.fury.io/py/click-man.svg)](https://pypi.python.org/pypi/click-man) 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 ``` → Checkout the [debian packaging example](https://github.com/timofurrer/click-man#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`. ## Installation ```bash pip3 install click-man ``` **click-man** is also available for Python 2: ```bash pip install click-man ``` ## Usage Recipes The following sections describe different usage example for *click-man*. ### Use with a previously installed package **click-man** provides its own command line tool which can be passed the name of an installed script: ```bash click-man commandname ``` where `commandname` is the name of an installed `console_script` entry point. To specify a target directory for the man pages, use the `--target` option: ```bash 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. 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 compatable with Python virtualenvs Even on systems that support man pages, Python packages can be installed in virtualenvs via pip and setuptools, which do not make commands available globally. In fact, one of the "features" of a virtualenv is the ability to install a package without affecting the main system. As it is imposable to ensure a man page is only generated when not installing into a virtualenv, auto-generated man pages would pollute the main system and not stay contained in the virtualenv. Additionally, as a user could install multiple different versions of the same package into multiple different virtualenvs on the same system, there is no guarantee that a globally installed man page will document 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. With setuptools and pip we face two problems: 1. If we generate and install them during installation of the package pip does not know about the man pages and thus cannot uninstall it. 2. If we generate them in our build process and add them to your distribution we do not have a way to prevent installation to */usr/share/man* for non-UNIX-like Operating Systems or from within virtualenvs. ### Debian packages The `debhelper` packages provides a very convenient script called `dh_installman`. It checks for the `debian/(pkg_name.)manpages` file and it's content which is basically a line by line list of man pages or globs: ``` debian/tmp/manpages/* ``` We override the rule provided by `dh_installman` to generate our man pages in advance, like this: ```Makefile override_dh_installman: python3 setup.py --command-packages=click_man.commands man_pages --target debian/tmp/manpages dh_installman -O--buildsystem=pybuild ``` Now we are able to build are debian package with the tool of your choice, e.g.: ```debuild -us -uc``` Checkout a working example here: [repo debian package](https://github.com/timofurrer/click-man/tree/master/examples/debian_pkg) Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Documentation Description-Content-Type: text/markdown click-man-0.4.1/click_man.egg-info/dependency_links.txt0000644000175000017500000000000113633452426021546 0ustar ryanryan click-man-0.4.1/tests/0000755000175000017500000000000013633452426013230 5ustar ryanryanclick-man-0.4.1/tests/__init__.py0000644000175000017500000000000013431773731015330 0ustar ryanryanclick-man-0.4.1/tests/test_man.py0000644000175000017500000000365113431774274015425 0ustar ryanryan""" Module to test man page functionality of click-man package. """ from sure import expect from click_man.man import ManPage def test_simple_man_page(): """ Test creating most simple man page """ man = ManPage('my-command') man.short_help = 'Command to test man pages for click.' man.date = '21-Feb-1994' expect(str(man)).to.be.equal(""".TH "MY-COMMAND" "1" "21-Feb-1994" "1.0.0" "my-command Manual" .SH NAME my-command \- Command to test man pages for click. .SH SYNOPSIS .B my-command """) def test_full_man_page(): """ Test creating man page with all options set """ man = ManPage('my-command') man.short_help = 'Command to test man pages for click.' man.date = '21-Feb-1994' man.synopsis = '[--yolo] [--iambatman]' man.description = """This is my awesome multi line description of a click-man test. Boaa, richtig geili sach.""" man.options = [ ('--yolo', 'Do it in yolo sytle'), ('--iambatman', 'Make me think I am batman') ] man.commands = [ ('start', 'Start it'), ('stop', 'Stop it'), ('test', 'Pretend you are testing your code') ] expect(str(man)).to.be.equal(r""".TH "MY-COMMAND" "1" "21-Feb-1994" "1.0.0" "my-command Manual" .SH NAME my-command \- Command to test man pages for click. .SH SYNOPSIS .B my-command [\-\-yolo] [\-\-iambatman] .SH DESCRIPTION This is my awesome .PP multi line description of a click-man test. .PP Boaa, richtig geili sach. .SH OPTIONS .TP \fB\-\-yolo\fP Do it in yolo sytle .TP \fB\-\-iambatman\fP Make me think I am batman .SH COMMANDS .PP \fBstart\fP Start it See \fBmy-command-start(1)\fP for full documentation on the \fBstart\fP command. .PP \fBstop\fP Stop it See \fBmy-command-stop(1)\fP for full documentation on the \fBstop\fP command. .PP \fBtest\fP Pretend you are testing your code See \fBmy-command-test(1)\fP for full documentation on the \fBtest\fP command. """) click-man-0.4.1/PKG-INFO0000644000175000017500000001347713633452426013177 0ustar ryanryanMetadata-Version: 2.1 Name: click-man Version: 0.4.1 Summary: Generate man pages for click based CLI applications Home-page: https://github.com/click-contrib/click-man Author: Timo Furrer Author-email: tuxtimo@gmail.com License: MIT Description: # click-man [![Build Status](https://travis-ci.org/click-contrib/click-man.svg?branch=master)](https://travis-ci.org/click-contrib/click-man) [![PyPI Package version](https://badge.fury.io/py/click-man.svg)](https://pypi.python.org/pypi/click-man) 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 ``` → Checkout the [debian packaging example](https://github.com/timofurrer/click-man#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`. ## Installation ```bash pip3 install click-man ``` **click-man** is also available for Python 2: ```bash pip install click-man ``` ## Usage Recipes The following sections describe different usage example for *click-man*. ### Use with a previously installed package **click-man** provides its own command line tool which can be passed the name of an installed script: ```bash click-man commandname ``` where `commandname` is the name of an installed `console_script` entry point. To specify a target directory for the man pages, use the `--target` option: ```bash 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. 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 compatable with Python virtualenvs Even on systems that support man pages, Python packages can be installed in virtualenvs via pip and setuptools, which do not make commands available globally. In fact, one of the "features" of a virtualenv is the ability to install a package without affecting the main system. As it is imposable to ensure a man page is only generated when not installing into a virtualenv, auto-generated man pages would pollute the main system and not stay contained in the virtualenv. Additionally, as a user could install multiple different versions of the same package into multiple different virtualenvs on the same system, there is no guarantee that a globally installed man page will document 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. With setuptools and pip we face two problems: 1. If we generate and install them during installation of the package pip does not know about the man pages and thus cannot uninstall it. 2. If we generate them in our build process and add them to your distribution we do not have a way to prevent installation to */usr/share/man* for non-UNIX-like Operating Systems or from within virtualenvs. ### Debian packages The `debhelper` packages provides a very convenient script called `dh_installman`. It checks for the `debian/(pkg_name.)manpages` file and it's content which is basically a line by line list of man pages or globs: ``` debian/tmp/manpages/* ``` We override the rule provided by `dh_installman` to generate our man pages in advance, like this: ```Makefile override_dh_installman: python3 setup.py --command-packages=click_man.commands man_pages --target debian/tmp/manpages dh_installman -O--buildsystem=pybuild ``` Now we are able to build are debian package with the tool of your choice, e.g.: ```debuild -us -uc``` Checkout a working example here: [repo debian package](https://github.com/timofurrer/click-man/tree/master/examples/debian_pkg) Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Documentation Description-Content-Type: text/markdown click-man-0.4.1/README.md0000644000175000017500000001040513431773731013346 0ustar ryanryan# click-man [![Build Status](https://travis-ci.org/click-contrib/click-man.svg?branch=master)](https://travis-ci.org/click-contrib/click-man) [![PyPI Package version](https://badge.fury.io/py/click-man.svg)](https://pypi.python.org/pypi/click-man) 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 ``` → Checkout the [debian packaging example](https://github.com/timofurrer/click-man#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`. ## Installation ```bash pip3 install click-man ``` **click-man** is also available for Python 2: ```bash pip install click-man ``` ## Usage Recipes The following sections describe different usage example for *click-man*. ### Use with a previously installed package **click-man** provides its own command line tool which can be passed the name of an installed script: ```bash click-man commandname ``` where `commandname` is the name of an installed `console_script` entry point. To specify a target directory for the man pages, use the `--target` option: ```bash 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. 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 compatable with Python virtualenvs Even on systems that support man pages, Python packages can be installed in virtualenvs via pip and setuptools, which do not make commands available globally. In fact, one of the "features" of a virtualenv is the ability to install a package without affecting the main system. As it is imposable to ensure a man page is only generated when not installing into a virtualenv, auto-generated man pages would pollute the main system and not stay contained in the virtualenv. Additionally, as a user could install multiple different versions of the same package into multiple different virtualenvs on the same system, there is no guarantee that a globally installed man page will document 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. With setuptools and pip we face two problems: 1. If we generate and install them during installation of the package pip does not know about the man pages and thus cannot uninstall it. 2. If we generate them in our build process and add them to your distribution we do not have a way to prevent installation to */usr/share/man* for non-UNIX-like Operating Systems or from within virtualenvs. ### Debian packages The `debhelper` packages provides a very convenient script called `dh_installman`. It checks for the `debian/(pkg_name.)manpages` file and it's content which is basically a line by line list of man pages or globs: ``` debian/tmp/manpages/* ``` We override the rule provided by `dh_installman` to generate our man pages in advance, like this: ```Makefile override_dh_installman: python3 setup.py --command-packages=click_man.commands man_pages --target debian/tmp/manpages dh_installman -O--buildsystem=pybuild ``` Now we are able to build are debian package with the tool of your choice, e.g.: ```debuild -us -uc``` Checkout a working example here: [repo debian package](https://github.com/timofurrer/click-man/tree/master/examples/debian_pkg) click-man-0.4.1/setup.py0000644000175000017500000000203613633452367013605 0ustar ryanryanimport os from setuptools import setup, find_packages def read(fname): return open(os.path.join(os.path.dirname(__file__), fname)).read() setup( name='click-man', version='0.4.1', url='https://github.com/click-contrib/click-man', license='MIT', description='Generate man pages for click based CLI applications', long_description=read('README.md'), long_description_content_type='text/markdown', author='Timo Furrer', author_email='tuxtimo@gmail.com', install_requires=[ 'click' ], packages=find_packages(exclude=('tests', )), entry_points={ 'console_scripts': [ 'click-man = click_man.__main__:cli', ] }, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Topic :: Documentation', ], )