From 13d356854805094e465a14b3d61d62b0875b9285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Wed, 7 Oct 2015 21:07:12 -0400 Subject: [PATCH] move usage generation to setup.py this is an unfortunate rewrite of the manpage creation code mentionned in #208. ideally, this would be rewritten into a class that can generate both man pages and .rst files. --- borg/archiver.py | 50 +++++++++++++++++++++++++---------------------- docs/Makefile | 16 +-------------- setup.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 38 deletions(-) diff --git a/borg/archiver.py b/borg/archiver.py index 57e30760e..9b18486c8 100644 --- a/borg/archiver.py +++ b/borg/archiver.py @@ -548,24 +548,8 @@ def preprocess_args(self, args): print(warning) return args - def run(self, args=None): - check_extension_modules() - keys_dir = get_keys_dir() - if not os.path.exists(keys_dir): - os.makedirs(keys_dir) - os.chmod(keys_dir, stat.S_IRWXU) - cache_dir = get_cache_dir() - if not os.path.exists(cache_dir): - os.makedirs(cache_dir) - os.chmod(cache_dir, stat.S_IRWXU) - with open(os.path.join(cache_dir, 'CACHEDIR.TAG'), 'w') as fd: - fd.write(textwrap.dedent(""" - Signature: 8a477f597d28d172789f06886806bc55 - # This file is a cache directory tag created by Borg. - # For information about cache directory tags, see: - # http://www.brynosaurus.com/cachedir/ - """).lstrip()) - common_parser = argparse.ArgumentParser(add_help=False) + def build_parser(self, args=None, prog=None): + common_parser = argparse.ArgumentParser(add_help=False, prog=prog) common_parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='verbose output') @@ -576,11 +560,7 @@ def run(self, args=None): common_parser.add_argument('--remote-path', dest='remote_path', default=RemoteRepository.remote_path, metavar='PATH', help='set remote path to executable (default: "%(default)s")') - # We can't use argparse for "serve" since we don't want it to show up in "Available commands" - if args: - args = self.preprocess_args(args) - - parser = argparse.ArgumentParser(description='Borg %s - Deduplicated Backups' % __version__) + parser = argparse.ArgumentParser(prog=prog, description='Borg %s - Deduplicated Backups' % __version__) subparsers = parser.add_subparsers(title='Available commands') serve_epilog = textwrap.dedent(""" @@ -976,6 +956,30 @@ def run(self, args=None): subparser.set_defaults(func=functools.partial(self.do_help, parser, subparsers.choices)) subparser.add_argument('topic', metavar='TOPIC', type=str, nargs='?', help='additional help on TOPIC') + return parser + + def run(self, args=None): + check_extension_modules() + keys_dir = get_keys_dir() + if not os.path.exists(keys_dir): + os.makedirs(keys_dir) + os.chmod(keys_dir, stat.S_IRWXU) + cache_dir = get_cache_dir() + if not os.path.exists(cache_dir): + os.makedirs(cache_dir) + os.chmod(cache_dir, stat.S_IRWXU) + with open(os.path.join(cache_dir, 'CACHEDIR.TAG'), 'w') as fd: + fd.write(textwrap.dedent(""" + Signature: 8a477f597d28d172789f06886806bc55 + # This file is a cache directory tag created by Borg. + # For information about cache directory tags, see: + # http://www.brynosaurus.com/cachedir/ + """).lstrip()) + + # We can't use argparse for "serve" since we don't want it to show up in "Available commands" + if args: + args = self.preprocess_args(args) + parser = self.build_parser(args) args = parser.parse_args(args or ['-h']) self.verbose = args.verbose diff --git a/docs/Makefile b/docs/Makefile index 1f3f7d76c..fb470c6a9 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -36,7 +36,7 @@ help: clean: -rm -rf $(BUILDDIR)/* -html: usage +html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -139,17 +139,3 @@ gh-io: html inotify: html while inotifywait -r . --exclude usage.rst --exclude '_build/*' ; do make html ; done - -# generate list of targets -usage: $(shell borg help | grep -A1 "Available commands:" | tail -1 | sed 's/[{} ]//g;s/,\|^/.rst.inc usage\//g;s/^.rst.inc//;s/usage\/help//') - -# generate help file based on usage -usage/%.rst.inc: ../borg/archiver.py - @echo generating usage for $* - @printf ".. _borg_$*:\n\n" > $@ - @printf "borg $*\n" >> $@ - @echo -n borg $* | tr 'a-z- ' '-' >> $@ - @printf "\n::\n\n" >> $@ - @borg help $* --usage-only | sed -e 's/^/ /' >> $@ - @printf "\nDescription\n~~~~~~~~~~~\n" >> $@ - @borg help $* --epilog-only >> $@ diff --git a/setup.py b/setup.py index ffcbac101..2f29b4a20 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ # -*- encoding: utf-8 *-* import os +import re import sys from glob import glob @@ -119,6 +120,54 @@ def detect_lz4(prefixes): with open('README.rst', 'r') as fd: long_description = fd.read() + +class build_usage(Command): + description = "generate usage for each command" + + user_options = [ + ('output=', 'O', 'output directory'), + ] + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + import pdb + print('generating usage docs') + from borg.archiver import Archiver + parser = Archiver().build_parser(prog='borg') + choices = {} + for action in parser._actions: + if action.choices is not None: + choices.update(action.choices) + print('found commands: %s' % list(choices.keys())) + if not os.path.exists('docs/usage'): + os.mkdir('docs/usage') + for command, parser in choices.items(): + if command is 'help': + continue + with open('docs/usage/%s.rst.inc' % command, 'w') as cmdfile: + print('generating help for %s' % command) + cmdfile.write(""".. _borg_{command}: + +borg {command} +{underline} +:: + +""".format(**{"command": command, + "underline": '-' * len('borg ' + command)})) + epilog = parser.epilog + parser.epilog = None + cmdfile.write(re.sub("^", " ", parser.format_help(), flags=re.M)) + cmdfile.write(""" +Description +~~~~~~~~~~~ +""") + cmdfile.write(epilog) + + class build_api(Command): description = "generate a basic api.rst file based on the modules available" @@ -149,10 +198,12 @@ def run(self): # (function, predicate), see http://docs.python.org/2/distutils/apiref.html#distutils.cmd.Command.sub_commands build.sub_commands.append(('build_api', None)) +build.sub_commands.append(('build_usage', None)) cmdclass = { 'build_ext': build_ext, 'build_api': build_api, + 'build_usage': build_usage, 'sdist': Sdist }