diff --git a/src/kapidox/argparserutils.py b/src/kapidox/argparserutils.py index 7d29c57..e58fc08 100644 --- a/src/kapidox/argparserutils.py +++ b/src/kapidox/argparserutils.py @@ -1,133 +1,137 @@ # -*- coding: utf-8 -*- # # Copyright 2014 Aurélien Gâteau # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Python 2/3 compatibility (NB: we require at least 2.7) from __future__ import division, absolute_import, print_function, unicode_literals import argparse import logging import os import sys def parse_args(depdiagram_available): + import textwrap parser = argparse.ArgumentParser( - description='Generate API documentation for the KDE Products' + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent('''Generate API documentations of complex projects. + +>> This function must be run from an empty directory (where the documentation will be build).''') ) group = add_sources_group(parser) group.add_argument('sourcesdir', help='Location of the sources.') group.add_argument('--depdiagram-dot-dir', help='Generate dependency diagrams, using the .dot files from DIR.', metavar="DIR") add_output_group(parser) add_qt_doc_group(parser) add_paths_group(parser) add_misc_group(parser) args = parser.parse_args() check_common_args(args) if args.depdiagram_dot_dir and not depdiagram_available: logging.error('You need to install the Graphviz Python bindings to ' 'generate dependency diagrams.\n' 'See .') exit(1) if not os.path.isdir(args.sourcesdir): logging.error(args.sourcesdir + " is not a directory") exit(2) return args def add_sources_group(parser): return parser.add_argument_group('sources') def add_output_group(parser): group = parser.add_argument_group('output options') group.add_argument('--title', default='API Documentation', help='String to use for page titles.') group.add_argument('--man-pages', action='store_true', help='Generate man page documentation.') group.add_argument('--qhp', action='store_true', help='Generate Qt Compressed Help documentation.') group.add_argument('--searchengine', action='store_true', help="Enable Doxygen's search engine feature.") group.add_argument('--api-searchbox', action='store_true', help="Enable the API searchbox.") group.add_argument('--indexing', action='store_true', help="Enable indexing.") return group def add_qt_doc_group(parser): group = parser.add_argument_group('Qt documentation') group.add_argument('--qtdoc-dir', help='Location of (local) Qt documentation; this is searched ' + 'for tag files to create links to Qt classes.') group.add_argument('--qtdoc-link', help='Override Qt documentation location for the links in the ' + 'html files. May be a path or URL.') group.add_argument('--qtdoc-flatten-links', action='store_true', help='Whether to assume all Qt documentation html files ' + 'are immediately under QTDOC_LINK (useful if you set ' + 'QTDOC_LINK to the online Qt documentation). Ignored ' + 'if QTDOC_LINK is not set.') return group def add_paths_group(parser): group = parser.add_argument_group('paths') group.add_argument('--doxygen', default='doxygen', help='(Path to) the doxygen executable.') group.add_argument('--qhelpgenerator', default='qhelpgenerator', help='(Path to) the qhelpgenerator executable.') return group def add_misc_group(parser): scriptdir = os.path.dirname(os.path.realpath(__file__)) doxdatadir = os.path.join(scriptdir, 'data') group = parser.add_argument_group('misc') group.add_argument('--doxdatadir', default=doxdatadir, help='Location of the HTML header files and support graphics.') group.add_argument('--keep-temp-dirs', action='store_true', help='Do not delete temporary dirs, useful for debugging.') return parser def check_common_args(args): if not _is_doxdatadir(args.doxdatadir): logging.error("{} is not a valid doxdatadir".format(args.doxdatadir)) sys.exit(1) def _is_doxdatadir(directory): for name in ['header.html', 'footer.html', 'htmlresource']: if not os.path.exists(os.path.join(directory, name)): return False return True diff --git a/src/kapidox/hlfunctions.py b/src/kapidox/hlfunctions.py index 7b9d51a..e0d9da1 100644 --- a/src/kapidox/hlfunctions.py +++ b/src/kapidox/hlfunctions.py @@ -1,132 +1,141 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- # # Copyright 2014 Alex Merry # Copyright 2014 Aurélien Gâteau # Copyright 2014 Alex Turbov # Copyright 2016 Olivier Churlaud # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Python 2/3 compatibility (NB: we require at least 2.7) from __future__ import division, absolute_import, print_function, unicode_literals import logging import os import shutil import sys import tempfile if sys.version_info.major < 3: from urllib import urlretrieve else: from urllib.request import urlretrieve from . import generator, utils, argparserutils, preprocessing try: from kapidox import depdiagram DEPDIAGRAM_AVAILABLE = True except ImportError: DEPDIAGRAM_AVAILABLE = False -def do_it(maintainers, copyright, searchpaths=None): + +def do_it(maintainers_fct, copyright, searchpaths=None): + utils.setup_logging() if searchpaths is None: searchpaths = searchpaths=['/usr/share/doc/qt5', '/usr/share/doc/qt'] - utils.setup_logging() args = argparserutils.parse_args(DEPDIAGRAM_AVAILABLE) + if len(os.listdir(os.getcwd())) > 0: + logging.error("Run this command from an empty directory.") + exit(2) + + if not DEPDIAGRAM_AVAILABLE: + logging.warning("Missing Graphviz dependency: diagrams will not be generated.") + tagfiles = generator.search_for_tagfiles( suggestion=args.qtdoc_dir, doclink=args.qtdoc_link, flattenlinks=args.qtdoc_flatten_links, searchpaths=searchpaths) rootdir = args.sourcesdir + maintainers = maintainers_fct() metalist = preprocessing.parse_tree(rootdir) products, groups, libraries, available_platforms = preprocessing.sort_metainfo(metalist, maintainers) dirsrc = os.path.join(args.doxdatadir, 'htmlresource') dirdest = 'resources' if os.path.isdir(dirdest): shutil.rmtree(dirdest) shutil.copytree(dirsrc, dirdest) os.rename(dirdest+'/favicon.ico', './favicon.ico') generator.process_toplevel_html_file('index.html', args.doxdatadir, title=args.title, products=products, api_searchbox=args.api_searchbox ) generator.process_subgroup_html_files('index.html', args.doxdatadir, title=args.title, groups=groups, available_platforms=available_platforms, api_searchbox=args.api_searchbox ) tmp_dir = tempfile.mkdtemp(prefix='kapidox-') try: if args.depdiagram_dot_dir: dot_files = utils.find_dot_files(args.depdiagram_dot_dir) assert(dot_files) for lib in libraries: logging.info('# Generating doc for {}'.format(lib.fancyname)) if args.depdiagram_dot_dir: png_path = os.path.join(tmp_dir, lib.name) + '.png' ok = generator.generate_diagram(png_path, lib.fancyname, dot_files, tmp_dir) if ok: lib.dependency_diagram = png_path ctx = generator.create_fw_context(args, lib, tagfiles) generator.gen_fw_apidocs(ctx, tmp_dir) tagfiles.append(generator.create_fw_tagfile_tuple(lib)) # Rebuild for interdependencies for lib in libraries: logging.info('# Rebuilding {} for interdependencies' .format(lib.fancyname)) shutil.rmtree(lib.outputdir) ctx = generator.create_fw_context(args, lib, tagfiles, copyright) generator.gen_fw_apidocs(ctx, tmp_dir) generator.finish_fw_apidocs(ctx, None) logging.info('# Generate indexing files') generator.indexer(lib) logging.info('# Done') for product in products: generator.create_product_index(product) if product.logo_url is not None: logodir = os.path.dirname(product.logo_url) if not os.path.isdir(logodir): os.mkdir(logodir) shutil.copy(product.logo_url_src, product.logo_url) generator.create_global_index(products) if args.qhp: generator.create_qch(products, tagfiles) finally: if args.keep_temp_dirs: logging.info('Kept temp dir at {}'.format(tmp_dir)) else: shutil.rmtree(tmp_dir) diff --git a/src/kapidox_generate b/src/kapidox_generate index 3578743..aabc2dd 100755 --- a/src/kapidox_generate +++ b/src/kapidox_generate @@ -1,111 +1,110 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- # # Copyright 2014 Alex Merry # Copyright 2014 Aurélien Gâteau # Copyright 2014 Alex Turbov # Copyright 2016 Olivier Churlaud # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Python 2/3 compatibility (NB: we require at least 2.7) from __future__ import division, absolute_import, print_function, unicode_literals import logging import codecs import os import sys import time import datetime if sys.version_info.major < 3: from urllib import urlretrieve else: from urllib.request import urlretrieve from kapidox import generator, utils, argparserutils, preprocessing, hlfunctions try: from kapidox import depdiagram DEPDIAGRAM_AVAILABLE = True except ImportError: DEPDIAGRAM_AVAILABLE = False def download_kde_identities(): """Download the "accounts" file on the KDE SVN repository in order to get the KDE identities with their name and e-mail address """ cache_file = os.path.join(utils.cache_dir(), 'kde-accounts') needs_download = True if os.path.exists(cache_file): logging.debug("Found cached identities file at %s", cache_file) # not quite a day, so that generation on api.kde.org gets a fresh # copy every time the daily cron job runs it yesterday = time.time() - (23.5 * 3600) if os.path.getmtime(cache_file) > yesterday: needs_download = False else: logging.debug("Cached file too old; updating") if needs_download: logging.info("Downloading KDE identities") try: if not utils.svn_export( 'svn://anonsvn.kde.org/home/kde/trunk/kde-common/accounts', cache_file, overwrite=True): logging.debug("Falling back to using websvn to fetch " "identities file") urlretrieve('http://websvn.kde.org/*checkout*/trunk/kde-common/accounts', cache_file) except Exception as e: if os.path.exists(cache_file): logging.error('Failed to update KDE identities: %s', e) else: logging.error('Failed to fetch KDE identities: %s', e) return None maintainers = {} with codecs.open(cache_file, 'r', encoding='utf8') as f: for line in f: parts = line.strip().split() if len(parts) >= 3: maintainers[parts[0]] = { 'name': ' '.join(parts[1:-1]), 'email': parts[-1] } return maintainers def main(): - utils.setup_logging() kde_copyright = '1996-' + str(datetime.date.today().year) + ' The KDE developers' - maintainers = download_kde_identities() + get_maintainers = download_kde_identities - hlfunctions.do_it(maintainers=maintainers, + hlfunctions.do_it(maintainers_fct=get_maintainers, copyright=kde_copyright) if __name__ == "__main__": main()