diff --git a/README.md b/README.md index 77c3e50..0ad5762 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -catkin_tools_document -===================== +# catkin_tools_document + +[![Lint](https://github.com/mikepurvis/catkin_tools_document/actions/workflows/lint.yml/badge.svg)](https://github.com/mikepurvis/catkin_tools_document/actions/workflows/lint.yml) This package is an experimental documentation-builder for ROS packages, similar to [rosdoc_lite](http://wiki.ros.org/rosdoc_lite). It differs in the following ways: @@ -15,13 +16,12 @@ This package is an experimental documentation-builder for ROS packages, similar in-package symbols only, and once with all links to get the HTML output. This avoids the duplicate symbol warnings which rosdoc_lite produces. -Demonstration -------------- +## Demonstration Using a virtualenv is recommended if using `pip`. Alternatively, you can get a system package for Ubuntu or Debian [on my PPA][1] (2022-03-17: PPA is broken/not updated for now). -``` +```bash pip install catkin_tools_document mkdir -p catkin_ws/src && cd catkin_ws rosinstall_generator ros_base --deps --tar --rosdistro noetic > src/.rosinstall @@ -33,10 +33,9 @@ Now open up `catkin_ws/docs/index.html` in the browser of your choice. [1]: https://launchpad.net/~mikepurvis/+archive/ubuntu/catkin -Release -------- +## Release -``` +```bash # Upload to pypi python setup.py sdist bdist_wheel twine upload dist/* diff --git a/catkin_tools_document/__init__.py b/catkin_tools_document/__init__.py index 4f63e0a..cfaaf40 100644 --- a/catkin_tools_document/__init__.py +++ b/catkin_tools_document/__init__.py @@ -19,7 +19,7 @@ description = dict( - verb='document', + verb="document", description="Build documentation for packages in a workspace.", main=main, prepare_arguments=prepare_arguments, diff --git a/catkin_tools_document/builders.py b/catkin_tools_document/builders.py index b0b8b00..38aae2f 100644 --- a/catkin_tools_document/builders.py +++ b/catkin_tools_document/builders.py @@ -32,113 +32,99 @@ def doxygen(conf, package, deps, doc_deps, output_path, source_path, docs_build_ # for this suggestion: http://stackoverflow.com/a/35640905/109517 return [ FunctionStage( - 'generate_doxygen_config', generate_doxygen_config, + "generate_doxygen_config", + generate_doxygen_config, conf=conf, package=package, recursive_build_deps=doc_deps, output_path=output_path, source_path=source_path, - docs_build_path=docs_build_path), - CommandStage( - 'rosdoc_doxygen', - [which('doxygen'), os.path.join(docs_build_path, 'Doxyfile')], - cwd=source_path), + docs_build_path=docs_build_path, + ), + CommandStage("rosdoc_doxygen", [which("doxygen"), os.path.join(docs_build_path, "Doxyfile")], cwd=source_path), FunctionStage( - 'generate_doxygen_config_tags', generate_doxygen_config_tags, + "generate_doxygen_config_tags", + generate_doxygen_config_tags, conf=conf, package=package, output_path=output_path, source_path=source_path, - docs_build_path=docs_build_path), + docs_build_path=docs_build_path, + ), CommandStage( - 'rosdoc_doxygen_tags', - [which('doxygen'), os.path.join(docs_build_path, 'Doxyfile_tags')], - cwd=source_path), + "rosdoc_doxygen_tags", [which("doxygen"), os.path.join(docs_build_path, "Doxyfile_tags")], cwd=source_path + ), # Filter the tags XML to remove user-defined references that may appear in multiple # packages (like "codeapi"), since they are not namespaced. - FunctionStage( - 'filter_doxygen_tags', filter_doxygen_tags, - docs_build_path=docs_build_path) + FunctionStage("filter_doxygen_tags", filter_doxygen_tags, docs_build_path=docs_build_path), ] def sphinx(conf, package, deps, doc_deps, output_path, source_path, docs_build_path, job_env): - root_dir = os.path.join(source_path, conf.get('sphinx_root_dir', '.')) - output_dir = os.path.join(output_path, 'html', conf.get('output_dir', '')) + root_dir = os.path.join(source_path, conf.get("sphinx_root_dir", ".")) + output_dir = os.path.join(output_path, "html", conf.get("output_dir", "")) - rpp = os.environ['ROS_PACKAGE_PATH'].split(':') + rpp = os.environ["ROS_PACKAGE_PATH"].split(":") rpp.insert(0, source_path) - if os.path.isdir(os.path.join(source_path, 'src')): - rpp.insert(0, os.path.join(source_path, 'src')) + if os.path.isdir(os.path.join(source_path, "src")): + rpp.insert(0, os.path.join(source_path, "src")) env = { - 'PATH': os.environ.get('PATH', ''), - 'PYTHONPATH': os.environ.get('PYTHONPATH', ''), - 'ROS_PACKAGE_PATH': ':'.join(rpp), - 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', '') + "PATH": os.environ.get("PATH", ""), + "PYTHONPATH": os.environ.get("PYTHONPATH", ""), + "ROS_PACKAGE_PATH": ":".join(rpp), + "LD_LIBRARY_PATH": os.environ.get("LD_LIBRARY_PATH", ""), } return [ FunctionStage( - 'cache_sphinx_output', + "cache_sphinx_output", write_file, contents=output_dir, - dest_path=os.path.join(docs_build_path, output_dir_file('sphinx')), + dest_path=os.path.join(docs_build_path, output_dir_file("sphinx")), ), FunctionStage( - 'job_env_set_intersphinx_mapping', + "job_env_set_intersphinx_mapping", generate_intersphinx_mapping, output_path=output_path, root_dir=root_dir, doc_deps=doc_deps, docs_build_path=docs_build_path, - job_env=job_env), - CommandStage( - 'rosdoc_sphinx', - [which('sphinx-build'), '-E', root_dir, output_dir], - cwd=root_dir, - env=env), - FunctionStage( - 'job_env_unset_intersphinx_mapping', - unset_env, job_env=job_env, - keys=['INTERSPHINX_MAPPING']), + ), + CommandStage("rosdoc_sphinx", [which("sphinx-build"), "-E", root_dir, output_dir], cwd=root_dir, env=env), + FunctionStage("job_env_unset_intersphinx_mapping", unset_env, job_env=job_env, keys=["INTERSPHINX_MAPPING"]), ] def pydoctor(conf, package, deps, doc_deps, output_path, source_path, docs_build_path, job_env): - output_dir = os.path.join(output_path, 'html', conf.get('output_dir', '')) + output_dir = os.path.join(output_path, "html", conf.get("output_dir", "")) # TODO: Would be better to extract this information from the setup.py, but easier # for now to just codify an assumption of {pkg}/python, falling back to {pkg}/src. - src_dir = os.path.join(source_path, 'python') + src_dir = os.path.join(source_path, "python") if not os.path.isdir(src_dir): - src_dir = os.path.join(source_path, 'src') + src_dir = os.path.join(source_path, "src") - command = [which('pydoctor'), '--project-name', package.name, '--html-output', output_dir] + command = [which("pydoctor"), "--project-name", package.name, "--html-output", output_dir] - if 'config' in conf and 'epydoc' not in conf['config']: - command.extend(['--config', os.path.join(source_path, conf['config'])]) + if "config" in conf and "epydoc" not in conf["config"]: + command.extend(["--config", os.path.join(source_path, conf["config"])]) for subdir in os.listdir(src_dir): command.append(os.path.join(src_dir, subdir)) # pydoctor returns error codes for minor issues we don't care about. - wrapper_command = ['/bin/bash', '-c', '%s || true' % ' '.join(command)] + wrapper_command = ["/bin/bash", "-c", "%s || true" % " ".join(command)] return [ + FunctionStage("mkdir_pydoctor", makedirs, path=output_dir), FunctionStage( - 'mkdir_pydoctor', - makedirs, - path=output_dir), - FunctionStage( - 'cache_pydoctor_output', + "cache_pydoctor_output", write_file, contents=output_dir, - dest_path=os.path.join(docs_build_path, output_dir_file('pydoctor'))), - CommandStage( - 'rosdoc_pydoctor', - wrapper_command, - cwd=src_dir) + dest_path=os.path.join(docs_build_path, output_dir_file("pydoctor")), + ), + CommandStage("rosdoc_pydoctor", wrapper_command, cwd=src_dir), ] @@ -149,36 +135,26 @@ def epydoc(conf, package, deps, doc_deps, output_path, source_path, docs_build_p # If epydoc is missing, fall back to pydoctor. return pydoctor(conf, package, deps, doc_deps, output_path, source_path, docs_build_path, job_env) - output_dir = os.path.join(output_path, 'html', conf.get('output_dir', '')) + output_dir = os.path.join(output_path, "html", conf.get("output_dir", "")) - command = [epydoc_exe, '--html', package.name, '-o', output_dir] - for s in conf.get('exclude', []): - command.extend(['--exclude', s]) + command = [epydoc_exe, "--html", package.name, "-o", output_dir] + for s in conf.get("exclude", []): + command.extend(["--exclude", s]) - if 'config' in conf: - command.extend(['--config', os.path.join(source_path, conf['config'])]) + if "config" in conf: + command.extend(["--config", os.path.join(source_path, conf["config"])]) else: # default options - command.extend(['--inheritance', 'included', '--no-private']) + command.extend(["--inheritance", "included", "--no-private"]) - env = { - 'PYTHONPATH': os.environ.get('PYTHONPATH', ''), - 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', '') - } + env = {"PYTHONPATH": os.environ.get("PYTHONPATH", ""), "LD_LIBRARY_PATH": os.environ.get("LD_LIBRARY_PATH", "")} # Swallow errors from epydoc until we figure out a better story for Python 3. - wrapper_command = ['/bin/bash', '-c', '%s || true' % ' '.join(command)] + wrapper_command = ["/bin/bash", "-c", "%s || true" % " ".join(command)] return [ - FunctionStage( - 'mkdir_epydoc', - makedirs, - path=output_dir), - CommandStage( - 'rosdoc_epydoc', - wrapper_command, - cwd=source_path, - env=env) + FunctionStage("mkdir_epydoc", makedirs, path=output_dir), + CommandStage("rosdoc_epydoc", wrapper_command, cwd=source_path, env=env), ] diff --git a/catkin_tools_document/cli.py b/catkin_tools_document/cli.py index 4d6e685..84fbc8a 100644 --- a/catkin_tools_document/cli.py +++ b/catkin_tools_document/cli.py @@ -36,13 +36,14 @@ def main(opts): # Suppress warnings since this won't necessarily find all packages # in the workspace (it stops when it finds one package), and # relying on it for warnings could mislead people. - this_package = find_enclosing_package( - search_start_path=getcwd(), - ws_path=ws_path, - warnings=[]) + this_package = find_enclosing_package(search_start_path=getcwd(), ws_path=ws_path, warnings=[]) except InvalidPackage as ex: - sys.exit(clr("@{rf}Error:@| The file %s is an invalid package.xml file." - " See below for details:\n\n%s" % (ex.package_path, ex.msg))) + sys.exit( + clr( + "@{rf}Error:@| The file %s is an invalid package.xml file." + " See below for details:\n\n%s" % (ex.package_path, ex.msg) + ) + ) # Handle context-based package building if opts.document_this: @@ -50,7 +51,8 @@ def main(opts): opts.packages += [this_package] else: sys.exit( - "[document] Error: In order to use --this, the current directory must be part of a catkin package.") + "[document] Error: In order to use --this, the current directory must be part of a catkin package." + ) # If --start--with was used without any packages and --this was specified, start with this package if opts.start_with_this: @@ -58,12 +60,10 @@ def main(opts): opts.start_with = this_package else: sys.exit( - "[document] Error: In order to use --this, the current directory must be part of a catkin package.") + "[document] Error: In order to use --this, the current directory must be part of a catkin package." + ) - job_server.initialize( - max_jobs=4, - max_load=None, - gnu_make_enabled=False) + job_server.initialize(max_jobs=4, max_load=None, gnu_make_enabled=False) return document_workspace( ctx, @@ -78,52 +78,114 @@ def main(opts): limit_status_rate=opts.limit_status_rate, no_notify=opts.no_notify, continue_on_failure=opts.continue_on_failure, - summarize_build=opts.summarize) + summarize_build=opts.summarize, + ) def prepare_arguments(parser): add_context_args(parser) # What packages to document - pkg_group = parser.add_argument_group('Packages', 'Control which packages get documented.') + pkg_group = parser.add_argument_group("Packages", "Control which packages get documented.") add = pkg_group.add_argument - add('packages', metavar='PKGNAME', nargs='*', - help='Workspace packages to document, package dependencies are documented as well unless --no-deps is used. ' - 'If no packages are given, then all the packages are documented.') - add('--this', dest='document_this', action='store_true', default=False, - help='Build the package containing the current working directory.') - add('--no-deps', action='store_true', default=False, - help='Only document specified packages, not their dependencies.') - - add('-j', '--jobs', default=None, - help='Maximum number of build jobs to be distributed across active packages. (default is cpu count)') - add('-p', '--parallel-packages', metavar='PACKAGE_JOBS', dest='parallel_jobs', default=None, - help='Maximum number of packages allowed to be built in parallel (default is cpu count)') + add( + "packages", + metavar="PKGNAME", + nargs="*", + help="Workspace packages to document, package dependencies are documented as well unless --no-deps is used. " + "If no packages are given, then all the packages are documented.", + ) + add( + "--this", + dest="document_this", + action="store_true", + default=False, + help="Build the package containing the current working directory.", + ) + add( + "--no-deps", + action="store_true", + default=False, + help="Only document specified packages, not their dependencies.", + ) + + add( + "-j", + "--jobs", + default=None, + help="Maximum number of build jobs to be distributed across active packages. (default is cpu count)", + ) + add( + "-p", + "--parallel-packages", + metavar="PACKAGE_JOBS", + dest="parallel_jobs", + default=None, + help="Maximum number of packages allowed to be built in parallel (default is cpu count)", + ) start_with_group = pkg_group.add_mutually_exclusive_group() add = start_with_group.add_argument - add('--start-with', metavar='PKGNAME', type=str, - help='Build a given package and those which depend on it, skipping any before it.') - add('--start-with-this', action='store_true', default=False, - help='Similar to --start-with, starting with the package containing the current directory.') + add( + "--start-with", + metavar="PKGNAME", + type=str, + help="Build a given package and those which depend on it, skipping any before it.", + ) + add( + "--start-with-this", + action="store_true", + default=False, + help="Similar to --start-with, starting with the package containing the current directory.", + ) add = pkg_group.add_argument - add('--continue-on-failure', '-c', action='store_true', default=False, - help='Try to continue documenting packages whose dependencies documented successfully even if some other requested ' - 'packages fail to document.') - - behavior_group = parser.add_argument_group('Interface', 'The behavior of the command-line interface.') + add( + "--continue-on-failure", + "-c", + action="store_true", + default=False, + help="Try to continue documenting packages whose dependencies documented successfully even if some other requested " + "packages fail to document.", + ) + + behavior_group = parser.add_argument_group("Interface", "The behavior of the command-line interface.") add = behavior_group.add_argument - add('--verbose', '-v', action='store_true', default=False, - help='Print output from commands in ordered blocks once the command finishes.') - add('--interleave-output', '-i', action='store_true', default=False, - help='Prevents ordering of command output when multiple commands are running at the same time.') - add('--no-status', action='store_true', default=False, - help='Suppresses status line, useful in situations where carriage return is not properly supported.') - add('--summarize', '--summary', '-s', action='store_true', default=None, - help='Adds a document summary to the end of a document; defaults to on with --continue-on-failure, off otherwise') - add('--no-summarize', '--no-summary', action='store_false', dest='summarize', - help='Explicitly disable the end of document summary') + add( + "--verbose", + "-v", + action="store_true", + default=False, + help="Print output from commands in ordered blocks once the command finishes.", + ) + add( + "--interleave-output", + "-i", + action="store_true", + default=False, + help="Prevents ordering of command output when multiple commands are running at the same time.", + ) + add( + "--no-status", + action="store_true", + default=False, + help="Suppresses status line, useful in situations where carriage return is not properly supported.", + ) + add( + "--summarize", + "--summary", + "-s", + action="store_true", + default=None, + help="Adds a document summary to the end of a document; defaults to on with --continue-on-failure, off otherwise", + ) + add( + "--no-summarize", + "--no-summary", + action="store_false", + dest="summarize", + help="Explicitly disable the end of document summary", + ) def status_rate_type(rate): rate = float(rate) @@ -131,10 +193,14 @@ def status_rate_type(rate): raise ArgumentTypeError("must be greater than or equal to zero.") return rate - add('--limit-status-rate', '--status-rate', type=status_rate_type, default=10.0, - help='Limit the update rate of the status bar to this frequency. Zero means unlimited. ' - 'Must be positive, default is 10 Hz.') - add('--no-notify', action='store_true', default=False, - help='Suppresses system pop-up notification.') + add( + "--limit-status-rate", + "--status-rate", + type=status_rate_type, + default=10.0, + help="Limit the update rate of the status bar to this frequency. Zero means unlimited. " + "Must be positive, default is 10 Hz.", + ) + add("--no-notify", action="store_true", default=False, help="Suppresses system pop-up notification.") return parser diff --git a/catkin_tools_document/document.py b/catkin_tools_document/document.py index 6f4344f..754a477 100644 --- a/catkin_tools_document/document.py +++ b/catkin_tools_document/document.py @@ -55,15 +55,15 @@ def create_package_job(context, package, package_path, deps, doc_deps): docs_space = os.path.join(context.docs_space_abs, package.name) - docs_build_space = os.path.join(context.build_space_abs, 'docs', package.name) + docs_build_space = os.path.join(context.build_space_abs, "docs", package.name) package_path_abs = os.path.join(context.source_space_abs, package_path) package_meta_path = context.package_metadata_path(package) # Load rosdoc config, if it exists. - rosdoc_yaml_path = os.path.join(package_path_abs, 'rosdoc.yaml') + rosdoc_yaml_path = os.path.join(package_path_abs, "rosdoc.yaml") for export in package.exports: if export.tagname == "rosdoc": - config = export.attributes.get('config', '') + config = export.attributes.get("config", "") if config: rosdoc_yaml_path_temp = os.path.join(package_path_abs, config) if os.path.isfile(rosdoc_yaml_path_temp): @@ -75,32 +75,57 @@ def create_package_job(context, package, package_path, deps, doc_deps): with open(rosdoc_yaml_path) as f: rosdoc_conf = yaml.full_load(f) else: - if os.path.isdir(os.path.join(package_path_abs, 'src')) or \ - os.path.isdir(os.path.join(package_path_abs, 'include')): - rosdoc_conf = [{'builder': 'doxygen'}] + if os.path.isdir(os.path.join(package_path_abs, "src")) or os.path.isdir( + os.path.join(package_path_abs, "include") + ): + rosdoc_conf = [{"builder": "doxygen"}] else: rosdoc_conf = [] stages = [] # Create package docs spaces. - stages.append(FunctionStage('mkdir_docs_build_space', makedirs, path=docs_build_space)) + stages.append(FunctionStage("mkdir_docs_build_space", makedirs, path=docs_build_space)) # Generate msg/srv/action docs with package summary page. - stages.append(FunctionStage('generate_messages', generate_messages, - package=package, package_path=package_path, - output_path=docs_build_space)) - stages.append(FunctionStage('generate_services', generate_services, - package=package, package_path=package_path, - output_path=docs_build_space)) - stages.append(FunctionStage('generate_package_summary', generate_package_summary, - package=package, package_path=package_path_abs, - rosdoc_conf=rosdoc_conf, output_path=docs_build_space)) + stages.append( + FunctionStage( + "generate_messages", + generate_messages, + package=package, + package_path=package_path, + output_path=docs_build_space, + ) + ) + stages.append( + FunctionStage( + "generate_services", + generate_services, + package=package, + package_path=package_path, + output_path=docs_build_space, + ) + ) + stages.append( + FunctionStage( + "generate_package_summary", + generate_package_summary, + package=package, + package_path=package_path_abs, + rosdoc_conf=rosdoc_conf, + output_path=docs_build_space, + ) + ) # Cache document config - stages.append(FunctionStage('cache_rosdoc_config', yaml_dump_file, - contents=rosdoc_conf, - dest_path=os.path.join(package_meta_path, 'rosdoc.yaml'))) + stages.append( + FunctionStage( + "cache_rosdoc_config", + yaml_dump_file, + contents=rosdoc_conf, + dest_path=os.path.join(package_meta_path, "rosdoc.yaml"), + ) + ) job_env = {} @@ -109,37 +134,43 @@ def create_package_job(context, package, package_path, deps, doc_deps): # files generated by that sphinx run. for conf in rosdoc_conf: try: - builder = conf['builder'] - if builder == 'doxygen': + builder = conf["builder"] + if builder == "doxygen": docs_space = os.path.realpath(docs_space) docs_build_space = os.path.realpath(docs_build_space) package_path_abs = os.path.realpath(package_path_abs) - stages.extend(getattr(builders, builder)( - conf, package, deps, doc_deps, docs_space, package_path_abs, docs_build_space, job_env)) + stages.extend( + getattr(builders, builder)( + conf, package, deps, doc_deps, docs_space, package_path_abs, docs_build_space, job_env + ) + ) except AttributeError: - log(fmt("[document] @!@{yf}Warning:@| Skipping unrecognized rosdoc builder [%s] for package [%s]" % - (conf['builder'], package.name))) + log( + fmt( + "[document] @!@{yf}Warning:@| Skipping unrecognized rosdoc builder [%s] for package [%s]" + % (conf["builder"], package.name) + ) + ) return Job(jid=package.name, deps=deps, env=job_env, stages=stages) def create_summary_job(context, package_names): docs_space = context.docs_space_abs - docs_build_space = os.path.join(context.build_space_abs, 'docs') + docs_build_space = os.path.join(context.build_space_abs, "docs") stages = [] - stages.append(FunctionStage('generate_overall_summary', generate_overall_summary, - output_path=docs_build_space)) + stages.append(FunctionStage("generate_overall_summary", generate_overall_summary, output_path=docs_build_space)) # Run Sphinx for the package summary. - stages.append(CommandStage( - 'summary_sphinx', - [which('sphinx-build'), '-j8', '-E', docs_build_space, docs_space], - cwd=docs_build_space - )) + stages.append( + CommandStage( + "summary_sphinx", [which("sphinx-build"), "-j8", "-E", docs_build_space, docs_space], cwd=docs_build_space + ) + ) - return Job(jid='summary', deps=package_names, env={}, stages=stages) + return Job(jid="summary", deps=package_names, env={}, stages=stages) def document_workspace( @@ -155,7 +186,7 @@ def document_workspace( limit_status_rate=10.0, no_notify=False, continue_on_failure=False, - summarize_build=None + summarize_build=None, ): pre_start_time = time.time() @@ -170,7 +201,8 @@ def document_workspace( # Find list of packages in the workspace packages_to_be_documented, packages_to_be_documented_deps, all_packages = determine_packages_to_be_built( - packages, context, workspace_packages) + packages, context, workspace_packages + ) if not no_deps: # Extend packages to be documented to include their deps @@ -180,21 +212,23 @@ def document_workspace( try: packages_to_be_documented = topological_order_packages(dict(packages_to_be_documented)) except AttributeError: - log(fmt("[document] @!@{rf}Error:@| The workspace packages have a circular " + log( + fmt( + "[document] @!@{rf}Error:@| The workspace packages have a circular " "dependency, and cannot be documented. Please run `catkin list " - "--deps` to determine the problematic package(s).")) + "--deps` to determine the problematic package(s)." + ) + ) return # Check the number of packages to be documented if len(packages_to_be_documented) == 0: - log(fmt('[document] No packages to be documented.')) + log(fmt("[document] No packages to be documented.")) # Assert start_with package is in the workspace verify_start_with_option( - start_with, - packages, - all_packages, - packages_to_be_documented + packages_to_be_documented_deps) + start_with, packages, all_packages, packages_to_be_documented + packages_to_be_documented_deps + ) # Remove packages before start_with if start_with is not None: @@ -214,14 +248,12 @@ def document_workspace( for pkg_path, pkg in packages_to_be_documented: # Get actual execution deps - deps = [ - p.name for _, p - in get_cached_recursive_build_depends_in_workspace(pkg, packages_to_be_documented) - ] + deps = [p.name for _, p in get_cached_recursive_build_depends_in_workspace(pkg, packages_to_be_documented)] doc_deps = [ - p.name for _, p - in get_cached_recursive_build_depends_in_workspace(pkg, packages_to_be_documented + - packages_to_be_documented_deps) + p.name + for _, p in get_cached_recursive_build_depends_in_workspace( + pkg, packages_to_be_documented + packages_to_be_documented_deps + ) ] jobs.append(create_package_job(context, pkg, pkg_path, deps, doc_deps)) @@ -235,8 +267,8 @@ def document_workspace( try: # Spin up status output thread status_thread = ConsoleStatusController( - 'document', - ['package', 'packages'], + "document", + ["package", "packages"], jobs, n_jobs, [pkg.name for _, pkg in context.packages], @@ -252,20 +284,24 @@ def document_workspace( show_stage_events=not quiet, show_full_summary=(summarize_build is True), pre_start_time=pre_start_time, - active_status_rate=limit_status_rate) + active_status_rate=limit_status_rate, + ) status_thread.start() # Block while running N jobs asynchronously try: - all_succeeded = run_until_complete(execute_jobs( - 'document', - jobs, - None, - event_queue, - context.log_space_abs, - max_toplevel_jobs=n_jobs, - continue_on_failure=continue_on_failure, - continue_without_deps=False)) + all_succeeded = run_until_complete( + execute_jobs( + "document", + jobs, + None, + event_queue, + context.log_space_abs, + max_toplevel_jobs=n_jobs, + continue_on_failure=continue_on_failure, + continue_without_deps=False, + ) + ) except Exception: status_thread.keep_running = False diff --git a/catkin_tools_document/doxygen.py b/catkin_tools_document/doxygen.py index 415da40..20cd81f 100644 --- a/catkin_tools_document/doxygen.py +++ b/catkin_tools_document/doxygen.py @@ -29,91 +29,99 @@ def _write_config(f, conf): f.write("%s = %s\n" % (k, v)) -def generate_doxygen_config(logger, event_queue, conf, package, recursive_build_deps, - output_path, source_path, docs_build_path): - header_filename = '' - footer_filename = '' - output_subdir = os.path.join('html', conf.get('output_dir', ''), '') +def generate_doxygen_config( + logger, event_queue, conf, package, recursive_build_deps, output_path, source_path, docs_build_path +): + header_filename = "" + footer_filename = "" + output_subdir = os.path.join("html", conf.get("output_dir", ""), "") output_dir = os.path.join(output_path, output_subdir) mkdir_p(output_dir) tagfiles = [] # Add tags for the standard library. - cppreference_tagfile = pkg_resources.resource_filename('catkin_tools_document', 'external/cppreference-doxygen-web.tag.xml') - tagfiles.append('%s=%s' % (cppreference_tagfile, 'https://en.cppreference.com/w/')) + cppreference_tagfile = pkg_resources.resource_filename( + "catkin_tools_document", "external/cppreference-doxygen-web.tag.xml" + ) + tagfiles.append("%s=%s" % (cppreference_tagfile, "https://en.cppreference.com/w/")) # Link up doxygen for all in-workspace build dependencies. for build_depend_name in recursive_build_deps: - depend_docs_tagfile = os.path.join(docs_build_path, '..', build_depend_name, 'tags') + depend_docs_tagfile = os.path.join(docs_build_path, "..", build_depend_name, "tags") if os.path.isfile(depend_docs_tagfile): - with open(os.path.join(docs_build_path, '..', build_depend_name, output_dir_file('doxygen'))) as f: + with open(os.path.join(docs_build_path, "..", build_depend_name, output_dir_file("doxygen"))) as f: depend_output_dir = f.read() depend_docs_relative_path = os.path.relpath(depend_output_dir, output_dir) - tagfiles.append('%s=%s' % (depend_docs_tagfile, depend_docs_relative_path)) + tagfiles.append("%s=%s" % (depend_docs_tagfile, depend_docs_relative_path)) - mdfile = conf.get('use_mdfile_as_mainpage', '') + mdfile = conf.get("use_mdfile_as_mainpage", "") if mdfile: mdfile = os.path.join(source_path, mdfile) doxyfile_conf = copy.copy(_base_config) - doxyfile_conf.update({ - 'ALIASES': conf.get('aliases', ''), - 'EXAMPLE_PATTERNS': conf.get('example_patterns', ''), - 'EXCLUDE_PATTERNS': conf.get('exclude_patterns', ''), - 'EXCLUDE_SYMBOLS': conf.get('exclude_symbols', ''), - 'FILE_PATTERNS': conf.get('file_patterns', doxyfile_conf['FILE_PATTERNS']), # Use predefined values as default if not defined - 'GENERATE_HTML': True, - 'GENERATE_XML': True, - 'SEARCHENGINE': True, - 'HTML_FOOTER': footer_filename, - 'HTML_HEADER': header_filename, - 'HTML_OUTPUT': output_dir, - 'IMAGE_PATH': conf.get('image_path', source_path), - 'INPUT': " ".join([source_path, mdfile]), - 'PROJECT_NAME': package.name, - 'OUTPUT_DIRECTORY': output_path, - 'TAB_SIZE': conf.get('tab_size', '8'), - 'TAGFILES': ' '.join(tagfiles), - 'USE_MATHJAX': True, - 'USE_MDFILE_AS_MAINPAGE': mdfile - }) - - with open(os.path.join(docs_build_path, 'Doxyfile'), 'w') as f: + doxyfile_conf.update( + { + "ALIASES": conf.get("aliases", ""), + "EXAMPLE_PATTERNS": conf.get("example_patterns", ""), + "EXCLUDE_PATTERNS": conf.get("exclude_patterns", ""), + "EXCLUDE_SYMBOLS": conf.get("exclude_symbols", ""), + "FILE_PATTERNS": conf.get( + "file_patterns", doxyfile_conf["FILE_PATTERNS"] + ), # Use predefined values as default if not defined + "GENERATE_HTML": True, + "GENERATE_XML": True, + "SEARCHENGINE": True, + "HTML_FOOTER": footer_filename, + "HTML_HEADER": header_filename, + "HTML_OUTPUT": output_dir, + "IMAGE_PATH": conf.get("image_path", source_path), + "INPUT": " ".join([source_path, mdfile]), + "PROJECT_NAME": package.name, + "OUTPUT_DIRECTORY": output_path, + "TAB_SIZE": conf.get("tab_size", "8"), + "TAGFILES": " ".join(tagfiles), + "USE_MATHJAX": True, + "USE_MDFILE_AS_MAINPAGE": mdfile, + } + ) + + with open(os.path.join(docs_build_path, "Doxyfile"), "w") as f: _write_config(f, doxyfile_conf) return 0 -def generate_doxygen_config_tags(logger, event_queue, conf, package, - output_path, source_path, docs_build_path): - output_subdir = os.path.join('html', conf.get('output_dir', ''), '') +def generate_doxygen_config_tags(logger, event_queue, conf, package, output_path, source_path, docs_build_path): + output_subdir = os.path.join("html", conf.get("output_dir", ""), "") output_dir = os.path.join(output_path, output_subdir) - tagfile_path = os.path.join(docs_build_path, 'tags') + tagfile_path = os.path.join(docs_build_path, "tags") # This is a token to let dependent packages know what the subdirectory name is for linking # to this package's doxygen docs (since it isn't always "html"). - with open(os.path.join(docs_build_path, output_dir_file('doxygen')), 'w') as f: + with open(os.path.join(docs_build_path, output_dir_file("doxygen")), "w") as f: f.write(output_dir) doxyfile_conf = copy.copy(_base_config) - doxyfile_conf.update({ - 'ALIASES': conf.get('aliases', ''), - 'EXAMPLE_PATTERNS': conf.get('example_patterns', ''), - 'EXCLUDE_PATTERNS': conf.get('exclude_patterns', ''), - 'EXCLUDE_SYMBOLS': conf.get('exclude_symbols', ''), - 'INPUT': source_path, - 'PROJECT_NAME': package.name, - 'GENERATE_TAGFILE': tagfile_path - }) - - with open(os.path.join(docs_build_path, 'Doxyfile_tags'), 'w') as f: + doxyfile_conf.update( + { + "ALIASES": conf.get("aliases", ""), + "EXAMPLE_PATTERNS": conf.get("example_patterns", ""), + "EXCLUDE_PATTERNS": conf.get("exclude_patterns", ""), + "EXCLUDE_SYMBOLS": conf.get("exclude_symbols", ""), + "INPUT": source_path, + "PROJECT_NAME": package.name, + "GENERATE_TAGFILE": tagfile_path, + } + ) + + with open(os.path.join(docs_build_path, "Doxyfile_tags"), "w") as f: _write_config(f, doxyfile_conf) return 0 def filter_doxygen_tags(logger, event_queue, docs_build_path): - tagfile_path = os.path.join(docs_build_path, 'tags') + tagfile_path = os.path.join(docs_build_path, "tags") tree = etree.parse(tagfile_path) root = tree.getroot() @@ -125,126 +133,126 @@ def filter_doxygen_tags(logger, event_queue, docs_build_path): _base_config = { - 'DOXYFILE_ENCODING': 'UTF-8', - 'CREATE_SUBDIRS': False, - 'OUTPUT_LANGUAGE': 'English', - 'BRIEF_MEMBER_DESC': True, - 'REPEAT_BRIEF': True, - 'ALWAYS_DETAILED_SEC': False, - 'INLINE_INHERITED_MEMB': False, - 'FULL_PATH_NAMES': False, - 'SHORT_NAMES': False, - 'QT_AUTOBRIEF': False, - 'INHERIT_DOCS': True, - 'SEPARATE_MEMBER_PAGES': False, - 'TAB_SIZE': 4, - 'OPTIMIZE_OUTPUT_FOR_C': False, - 'OPTIMIZE_OUTPUT_JAVA': False, - 'OPTIMIZE_FOR_FORTRAN': False, - 'OPTIMIZE_OUTPUT_VHDL': False, - 'MARKDOWN_SUPPORT': True, - 'AUTOLINK_SUPPORT': True, - 'BUILTIN_STL_SUPPORT': False, - 'CPP_CLI_SUPPORT': False, - 'SIP_SUPPORT': False, - 'IDL_PROPERTY_SUPPORT': True, - 'DISTRIBUTE_GROUP_DOC': False, - 'SUBGROUPING': True, - 'INLINE_GROUPED_CLASSES': False, - 'INLINE_SIMPLE_STRUCTS': False, - 'TYPEDEF_HIDES_STRUCT': False, - 'LOOKUP_CACHE_SIZE': 0, - 'EXTRACT_ALL': True, - 'EXTRACT_PRIVATE': True, - 'EXTRACT_PACKAGE': False, - 'EXTRACT_STATIC': True, - 'EXTRACT_LOCAL_CLASSES': True, - 'EXTRACT_LOCAL_METHODS': False, - 'EXTRACT_ANON_NSPACES': False, - 'HIDE_UNDOC_MEMBERS': False, - 'HIDE_UNDOC_CLASSES': False, - 'HIDE_FRIEND_COMPOUNDS': False, - 'HIDE_IN_BODY_DOCS': False, - 'INTERNAL_DOCS': False, - 'CASE_SENSE_NAMES': True, - 'HIDE_SCOPE_NAMES': False, - 'SHOW_INCLUDE_FILES': True, - 'SHOW_GROUPED_MEMB_INC': False, - 'FORCE_LOCAL_INCLUDES': False, - 'INLINE_INFO': True, - 'SORT_MEMBER_DOCS': True, - 'SORT_BRIEF_DOCS': True, - 'SORT_GROUP_NAMES': False, - 'SORT_BY_SCOPE_NAME': False, - 'STRICT_PROTO_MATCHING': False, - 'GENERATE_TODOLIST': True, - 'GENERATE_TESTLIST': True, - 'GENERATE_BUGLIST': True, - 'MAX_INITIALIZER_LINES': 30, - 'SHOW_USED_FILES': True, - 'SHOW_FILES': True, - 'SHOW_NAMESPACES': True, - 'QUIET': False, - 'WARNINGS': True, - 'WARN_IF_UNDOCUMENTED': True, - 'WARN_IF_DOC_ERROR': True, - 'WARN_NO_PARAMDOC': False, - 'WARN_FORMAT': '"$file:$line: $text"', - 'INPUT_ENCODING': 'UTF-8', - 'FILE_PATTERNS': '*.c *.cpp *.h *.cc *.hh *.hpp *.py *.dox *.java', - 'RECURSIVE': True, - 'EXCLUDE_SYMLINKS': False, - 'EXAMPLE_RECURSIVE': True, - 'FILTER_SOURCE_FILES': False, - 'SOURCE_BROWSER': True, - 'INLINE_SOURCES': False, - 'STRIP_CODE_COMMENTS': True, - 'REFERENCED_BY_RELATION': False, - 'REFERENCES_RELATION': False, - 'REFERENCES_LINK_SOURCE': True, - 'SOURCE_TOOLTIPS': True, - 'USE_HTAGS': False, - 'VERBATIM_HEADERS': False, - 'ALPHABETICAL_INDEX': False, - 'COLS_IN_ALPHA_INDEX': 5, - 'GENERATE_HTML': False, - 'HTML_FILE_EXTENSION': '.html', - 'HTML_COLORSTYLE_HUE': 220, - 'HTML_COLORSTYLE_SAT': 100, - 'HTML_COLORSTYLE_GAMMA': 80, - 'HTML_TIMESTAMP': True, - 'HTML_DYNAMIC_SECTIONS': False, - 'HTML_INDEX_NUM_ENTRIES': 100, - 'ENABLE_PREPROCESSING': True, - 'MACRO_EXPANSION': False, - 'EXPAND_ONLY_PREDEF': False, - 'SEARCHENGINE': False, - 'SEARCH_INCLUDES': False, - 'SKIP_FUNCTION_MACROS': True, - 'ALLEXTERNALS': False, - 'EXTERNAL_GROUPS': False, - 'EXTERNAL_PAGES': False, - 'CLASS_DIAGRAMS': True, - 'HIDE_UNDOC_RELATIONS': True, - 'HAVE_DOT': True, - 'DOT_NUM_THREADS': 0, - 'DOT_FONTNAME': 'Helvetica', - 'DOT_FONTSIZE': 10, - 'CLASS_GRAPH': True, - 'COLLABORATION_GRAPH': False, - 'GROUP_GRAPHS': True, - 'UML_LOOK': False, - 'UML_LIMIT_NUM_FIELDS': 10, - 'TEMPLATE_RELATIONS': False, - 'INCLUDE_GRAPH': True, - 'INCLUDED_BY_GRAPH': True, - 'CALL_GRAPH': False, - 'CALLER_GRAPH': False, - 'GRAPHICAL_HIERARCHY': True, - 'DIRECTORY_GRAPH': True, - 'JAVADOC_AUTOBRIEF': False, - 'MULTILINE_CPP_IS_BRIEF': False, - 'GENERATE_LATEX': False, - 'GENERATE_XML': False, - 'XML_OUTPUT': 'xml' + "ALLEXTERNALS": False, + "ALPHABETICAL_INDEX": False, + "ALWAYS_DETAILED_SEC": False, + "AUTOLINK_SUPPORT": True, + "BRIEF_MEMBER_DESC": True, + "BUILTIN_STL_SUPPORT": False, + "CALLER_GRAPH": False, + "CALL_GRAPH": False, + "CASE_SENSE_NAMES": True, + "CLASS_DIAGRAMS": True, + "CLASS_GRAPH": True, + "COLLABORATION_GRAPH": False, + "COLS_IN_ALPHA_INDEX": 5, + "CPP_CLI_SUPPORT": False, + "CREATE_SUBDIRS": False, + "DIRECTORY_GRAPH": True, + "DISTRIBUTE_GROUP_DOC": False, + "DOT_FONTNAME": "Helvetica", + "DOT_FONTSIZE": 10, + "DOT_NUM_THREADS": 0, + "DOXYFILE_ENCODING": "UTF-8", + "ENABLE_PREPROCESSING": True, + "EXAMPLE_RECURSIVE": True, + "EXCLUDE_SYMLINKS": False, + "EXPAND_ONLY_PREDEF": False, + "EXTERNAL_GROUPS": False, + "EXTERNAL_PAGES": False, + "EXTRACT_ALL": True, + "EXTRACT_ANON_NSPACES": False, + "EXTRACT_LOCAL_CLASSES": True, + "EXTRACT_LOCAL_METHODS": False, + "EXTRACT_PACKAGE": False, + "EXTRACT_PRIVATE": True, + "EXTRACT_STATIC": True, + "FILE_PATTERNS": "*.c *.cpp *.h *.cc *.hh *.hpp *.py *.dox *.java", + "FILTER_SOURCE_FILES": False, + "FORCE_LOCAL_INCLUDES": False, + "FULL_PATH_NAMES": False, + "GENERATE_BUGLIST": True, + "GENERATE_HTML": False, + "GENERATE_LATEX": False, + "GENERATE_TESTLIST": True, + "GENERATE_TODOLIST": True, + "GENERATE_XML": False, + "GRAPHICAL_HIERARCHY": True, + "GROUP_GRAPHS": True, + "HAVE_DOT": True, + "HIDE_FRIEND_COMPOUNDS": False, + "HIDE_IN_BODY_DOCS": False, + "HIDE_SCOPE_NAMES": False, + "HIDE_UNDOC_CLASSES": False, + "HIDE_UNDOC_MEMBERS": False, + "HIDE_UNDOC_RELATIONS": True, + "HTML_COLORSTYLE_GAMMA": 80, + "HTML_COLORSTYLE_HUE": 220, + "HTML_COLORSTYLE_SAT": 100, + "HTML_DYNAMIC_SECTIONS": False, + "HTML_FILE_EXTENSION": ".html", + "HTML_INDEX_NUM_ENTRIES": 100, + "HTML_TIMESTAMP": True, + "IDL_PROPERTY_SUPPORT": True, + "INCLUDED_BY_GRAPH": True, + "INCLUDE_GRAPH": True, + "INHERIT_DOCS": True, + "INLINE_GROUPED_CLASSES": False, + "INLINE_INFO": True, + "INLINE_INHERITED_MEMB": False, + "INLINE_SIMPLE_STRUCTS": False, + "INLINE_SOURCES": False, + "INPUT_ENCODING": "UTF-8", + "INTERNAL_DOCS": False, + "JAVADOC_AUTOBRIEF": False, + "LOOKUP_CACHE_SIZE": 0, + "MACRO_EXPANSION": False, + "MARKDOWN_SUPPORT": True, + "MAX_INITIALIZER_LINES": 30, + "MULTILINE_CPP_IS_BRIEF": False, + "OPTIMIZE_FOR_FORTRAN": False, + "OPTIMIZE_OUTPUT_FOR_C": False, + "OPTIMIZE_OUTPUT_JAVA": False, + "OPTIMIZE_OUTPUT_VHDL": False, + "OUTPUT_LANGUAGE": "English", + "QT_AUTOBRIEF": False, + "QUIET": False, + "RECURSIVE": True, + "REFERENCED_BY_RELATION": False, + "REFERENCES_LINK_SOURCE": True, + "REFERENCES_RELATION": False, + "REPEAT_BRIEF": True, + "SEARCHENGINE": False, + "SEARCH_INCLUDES": False, + "SEPARATE_MEMBER_PAGES": False, + "SHORT_NAMES": False, + "SHOW_FILES": True, + "SHOW_GROUPED_MEMB_INC": False, + "SHOW_INCLUDE_FILES": True, + "SHOW_NAMESPACES": True, + "SHOW_USED_FILES": True, + "SIP_SUPPORT": False, + "SKIP_FUNCTION_MACROS": True, + "SORT_BRIEF_DOCS": True, + "SORT_BY_SCOPE_NAME": False, + "SORT_GROUP_NAMES": False, + "SORT_MEMBER_DOCS": True, + "SOURCE_BROWSER": True, + "SOURCE_TOOLTIPS": True, + "STRICT_PROTO_MATCHING": False, + "STRIP_CODE_COMMENTS": True, + "SUBGROUPING": True, + "TAB_SIZE": 4, + "TEMPLATE_RELATIONS": False, + "TYPEDEF_HIDES_STRUCT": False, + "UML_LIMIT_NUM_FIELDS": 10, + "UML_LOOK": False, + "USE_HTAGS": False, + "VERBATIM_HEADERS": False, + "WARNINGS": True, + "WARN_FORMAT": '"$file:$line: $text"', + "WARN_IF_DOC_ERROR": True, + "WARN_IF_UNDOCUMENTED": True, + "WARN_NO_PARAMDOC": False, + "XML_OUTPUT": "xml", } diff --git a/catkin_tools_document/intersphinx.py b/catkin_tools_document/intersphinx.py index b1f169a..a974b0e 100644 --- a/catkin_tools_document/intersphinx.py +++ b/catkin_tools_document/intersphinx.py @@ -22,56 +22,62 @@ from .util import output_dir_file -INTERSPHINX_GENERATORS = ['pydoctor', 'sphinx'] +INTERSPHINX_GENERATORS = ["pydoctor", "sphinx"] def generate_intersphinx_mapping(logger, event_queue, output_path, root_dir, doc_deps, docs_build_path, job_env): intersphinx_mapping = copy.copy(_base_intersphinx_mapping) - python_version = f'{sys.version_info.major}.{sys.version_info.minor}' - intersphinx_mapping['python'] = (f'https://docs.python.org/{python_version}/', None) + python_version = f"{sys.version_info.major}.{sys.version_info.minor}" + intersphinx_mapping["python"] = (f"https://docs.python.org/{python_version}/", None) # Add workspace objects file - objects_file = os.path.join(output_path, '..', 'objects.inv') + objects_file = os.path.join(output_path, "..", "objects.inv") if os.path.isfile(objects_file): - intersphinx_mapping['workspace'] = (os.path.relpath(os.path.dirname(objects_file), root_dir), - os.path.realpath(objects_file)) + intersphinx_mapping["workspace"] = ( + os.path.relpath(os.path.dirname(objects_file), root_dir), + os.path.realpath(objects_file), + ) # Add other dependencies in the workspace for index, dep in enumerate(doc_deps): for gen_type in INTERSPHINX_GENERATORS: - dep_output_dir_file = os.path.join(docs_build_path, '..', dep, output_dir_file(gen_type)) + dep_output_dir_file = os.path.join(docs_build_path, "..", dep, output_dir_file(gen_type)) if not os.path.isfile(dep_output_dir_file): continue - with open(dep_output_dir_file, 'r') as f: + with open(dep_output_dir_file, "r") as f: depend_output_dir = f.read() - objects_file = os.path.join(depend_output_dir, 'objects.inv') + objects_file = os.path.join(depend_output_dir, "objects.inv") if not os.path.isfile(objects_file): continue - intersphinx_mapping[f'{dep}_{gen_type}'] = (os.path.relpath(depend_output_dir, root_dir), - os.path.realpath(objects_file)) + intersphinx_mapping[f"{dep}_{gen_type}"] = ( + os.path.relpath(depend_output_dir, root_dir), + os.path.realpath(objects_file), + ) - event_queue.put(ExecutionEvent( - 'STAGE_PROGRESS', - job_id=logger.job_id, - stage_label=logger.stage_label, - percent=str(index/float(len(doc_deps))) - )) + event_queue.put( + ExecutionEvent( + "STAGE_PROGRESS", + job_id=logger.job_id, + stage_label=logger.stage_label, + percent=str(index / float(len(doc_deps))), + ) + ) - job_env['INTERSPHINX_MAPPING'] = yaml.dump(intersphinx_mapping) + job_env["INTERSPHINX_MAPPING"] = yaml.dump(intersphinx_mapping) return 0 _base_intersphinx_mapping = { - 'catkin_pkg': ('https://docs.ros.org/independent/api/catkin_pkg/html', None), - 'jenkins_tools': ('https://docs.ros.org/independent/api/jenkins_tools/html', None), - 'rosdep': ('https://docs.ros.org/independent/api/rosdep/html', None), - 'rosdistro': ('https://docs.ros.org/independent/api/rosdistro/html', None), - 'rosinstall': ('https://docs.ros.org/independent/api/rosinstall/html', None), - 'rospkg': ('https://docs.ros.org/independent/api/rospkg/html', None), - 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), - 'vcstools': ('https://docs.ros.org/independent/api/vcstools/html', None), + "catkin_pkg": ("https://docs.ros.org/independent/api/catkin_pkg/html", None), + "jenkins_tools": ("https://docs.ros.org/independent/api/jenkins_tools/html", None), + "rosdep": ("https://docs.ros.org/independent/api/rosdep/html", None), + "rosdistro": ("https://docs.ros.org/independent/api/rosdistro/html", None), + "rosinstall": ("https://docs.ros.org/independent/api/rosinstall/html", None), + "rospkg": ("https://docs.ros.org/independent/api/rospkg/html", None), + "sphinx": ("https://www.sphinx-doc.org/en/master/", None), + "vcstools": ("https://docs.ros.org/independent/api/vcstools/html", None), } diff --git a/catkin_tools_document/messages.py b/catkin_tools_document/messages.py index 7883ae6..aadb9b1 100644 --- a/catkin_tools_document/messages.py +++ b/catkin_tools_document/messages.py @@ -20,52 +20,53 @@ from catkin_tools.common import mkdir_p -CONF_ENVVAR_NAME = 'CATKIN_TOOLS_DOCUMENT_CONFIG_FILE' +CONF_ENVVAR_NAME = "CATKIN_TOOLS_DOCUMENT_CONFIG_FILE" CONF_DEFAULT = { - 'project': 'Project', - 'copyright': 'the Authors', - 'version': '0.0', - 'master_doc': 'index', - 'html_theme': 'agogo', - 'templates_path': [] + "project": "Project", + "copyright": "the Authors", + "version": "0.0", + "master_doc": "index", + "html_theme": "agogo", + "templates_path": [], } def _write_raw(f, msg_type): - msg_text = re.split('^=+$', msg_type._full_text, maxsplit=1, flags=re.MULTILINE)[0] - msg_text = re.sub('^(.*?)$', ' \\1', msg_text, flags=re.MULTILINE) + msg_text = re.split("^=+$", msg_type._full_text, maxsplit=1, flags=re.MULTILINE)[0] + msg_text = re.sub("^(.*?)$", " \\1", msg_text, flags=re.MULTILINE) f.write(msg_text) - f.write('\n') + f.write("\n") def generate_messages(logger, event_queue, package, package_path, output_path): try: - msg_module = __import__(package.name + '.msg').msg - msg_names = [ msg_name for msg_name in dir(msg_module) - if re.match('^[A-Z]', msg_name) ] + msg_module = __import__(package.name + ".msg").msg + msg_names = [msg_name for msg_name in dir(msg_module) if re.match("^[A-Z]", msg_name)] except: msg_names = [] if msg_names: - mkdir_p(os.path.join(output_path, 'msg')) - with open(os.path.join(output_path, 'msg/index.rst'), 'w') as f: - f.write('%s » Messages\n' % package.name) - f.write('=' * 50 + '\n') - f.write(""" + mkdir_p(os.path.join(output_path, "msg")) + with open(os.path.join(output_path, "msg/index.rst"), "w") as f: + f.write("%s » Messages\n" % package.name) + f.write("=" * 50 + "\n") + f.write( + """ .. toctree:: :titlesonly: :glob: * - """) + """ + ) for msg_name in msg_names: msg_type = getattr(msg_module, msg_name) - with open(os.path.join(output_path, 'msg', '%s.rst' % msg_name), 'w') as f: - f.write('%s\n' % msg_name) - f.write('=' * 50 + '\n\n') - f.write('Definition::\n\n') + with open(os.path.join(output_path, "msg", "%s.rst" % msg_name), "w") as f: + f.write("%s\n" % msg_name) + f.write("=" * 50 + "\n\n") + f.write("Definition::\n\n") _write_raw(f, msg_type) return 0 @@ -73,35 +74,36 @@ def generate_messages(logger, event_queue, package, package_path, output_path): def generate_services(logger, event_queue, package, package_path, output_path): try: - srv_module = __import__(package.name + '.srv').srv - srv_names = [ srv_name for srv_name in dir(srv_module) - if re.match('^[A-Z]', srv_name) ] + srv_module = __import__(package.name + ".srv").srv + srv_names = [srv_name for srv_name in dir(srv_module) if re.match("^[A-Z]", srv_name)] except: srv_names = [] if srv_names: - mkdir_p(os.path.join(output_path, 'srv')) + mkdir_p(os.path.join(output_path, "srv")) - with open(os.path.join(output_path, 'srv/index.rst'), 'w') as f: - f.write('%s » Services\n' % package.name) - f.write('=' * 50 + '\n') - f.write(""" + with open(os.path.join(output_path, "srv/index.rst"), "w") as f: + f.write("%s » Services\n" % package.name) + f.write("=" * 50 + "\n") + f.write( + """ .. toctree:: :titlesonly: :glob: * - """) + """ + ) for srv_name in srv_names: srv_type = getattr(srv_module, srv_name) - if hasattr(srv_type, '_request_class'): - with open(os.path.join(output_path, 'srv', '%s.rst' % srv_name), 'w') as f: - f.write('%s\n' % srv_name) - f.write('=' * 50 + '\n\n') - f.write('Request Definition::\n\n') + if hasattr(srv_type, "_request_class"): + with open(os.path.join(output_path, "srv", "%s.rst" % srv_name), "w") as f: + f.write("%s\n" % srv_name) + f.write("=" * 50 + "\n\n") + f.write("Request Definition::\n\n") _write_raw(f, srv_type._request_class) - f.write('Response Definition::\n\n') + f.write("Response Definition::\n\n") _write_raw(f, srv_type._response_class) return 0 @@ -111,7 +113,7 @@ def _get_person_links(people): for person in people: if str == bytes: # Python 2 - name = person.name.encode('utf-8') + name = person.name.encode("utf-8") else: # Python 3 name = person.name @@ -122,64 +124,65 @@ def _get_person_links(people): return person_links -def generate_package_summary(logger, event_queue, package, package_path, - rosdoc_conf, output_path): +def generate_package_summary(logger, event_queue, package, package_path, rosdoc_conf, output_path): mkdir_p(output_path) - with open(os.path.join(output_path, 'index.rst'), 'w') as f: - f.write('%s\n' % package.name) - f.write('=' * 50 + '\n\n') + with open(os.path.join(output_path, "index.rst"), "w") as f: + f.write("%s\n" % package.name) + f.write("=" * 50 + "\n\n") if str == bytes: # Python 2 - description = package.description.encode('utf-8') + description = package.description.encode("utf-8") else: # Python 3 description = package.description - f.write('.. raw:: html\n\n') - f.write('

' + description + '

\n\n') + f.write(".. raw:: html\n\n") + f.write("

" + description + "

\n\n") if package.maintainers: - f.write('**Maintainers:** %s\n\n' % ', '.join(_get_person_links(package.maintainers))) + f.write("**Maintainers:** %s\n\n" % ", ".join(_get_person_links(package.maintainers))) if package.authors: - f.write('**Authors:** %s\n\n' % ', '.join(_get_person_links(package.authors))) + f.write("**Authors:** %s\n\n" % ", ".join(_get_person_links(package.authors))) + + f.write("**License:** %s\n\n" % ", ".join(package.licenses)) - f.write('**License:** %s\n\n' % ', '.join(package.licenses)) - for url in package.urls: - if url.type == 'repository': + if url.type == "repository": if str == bytes: # Python 2 - url_ = url.url.encode('utf-8') + url_ = url.url.encode("utf-8") else: # Python 3 url_ = url.url - f.write('**Source:** %s\n\n' % url_) + f.write("**Source:** %s\n\n" % url_) break if rosdoc_conf: - f.write('**API:** ') + f.write("**API:** ") for conf in rosdoc_conf: - rosdoc_link = os.path.join('html', conf.get('output_dir', ''), 'index.html') - rosdoc_name = conf.get('name', conf['builder']) + rosdoc_link = os.path.join("html", conf.get("output_dir", ""), "index.html") + rosdoc_name = conf.get("name", conf["builder"]) f.write("`%s <%s>`_ " % (rosdoc_name, rosdoc_link)) - f.write('\n\n') + f.write("\n\n") - f.write(""" + f.write( + """ .. toctree:: :titlesonly: -""") - if os.path.isfile(os.path.join(output_path, 'msg/index.rst')): +""" + ) + if os.path.isfile(os.path.join(output_path, "msg/index.rst")): f.write(" Messages \n") - if os.path.isfile(os.path.join(output_path, 'srv/index.rst')): + if os.path.isfile(os.path.join(output_path, "srv/index.rst")): f.write(" Services \n") - if os.path.isfile(os.path.join(output_path, 'action/index.rst')): + if os.path.isfile(os.path.join(output_path, "action/index.rst")): f.write(" Actions \n") - changelog_path = os.path.join(package_path, 'CHANGELOG.rst') - changelog_symlink_path = os.path.join(output_path, 'CHANGELOG.rst') + changelog_path = os.path.join(package_path, "CHANGELOG.rst") + changelog_symlink_path = os.path.join(output_path, "CHANGELOG.rst") if os.path.isfile(changelog_path) and not os.path.isfile(changelog_symlink_path): os.symlink(changelog_path, changelog_symlink_path) @@ -195,12 +198,13 @@ def generate_overall_summary(logger, event_queue, output_path): with open(os.environ[CONF_ENVVAR_NAME]) as f: conf.update(yaml.full_load(f)) - with open(os.path.join(output_path, 'conf.py'), 'w') as f: + with open(os.path.join(output_path, "conf.py"), "w") as f: for k, v in conf.items(): - f.write('%s = %s\n' % (k, repr(v))) + f.write("%s = %s\n" % (k, repr(v))) - with open(os.path.join(output_path, 'index.rst'), 'w') as f: - f.write(""" + with open(os.path.join(output_path, "index.rst"), "w") as f: + f.write( + """ Packages ======== @@ -210,5 +214,6 @@ def generate_overall_summary(logger, event_queue, output_path): :glob: */index -""") +""" + ) return 0 diff --git a/catkin_tools_document/spaces/docs.py b/catkin_tools_document/spaces/docs.py index fdeefd1..39d4b8d 100644 --- a/catkin_tools_document/spaces/docs.py +++ b/catkin_tools_document/spaces/docs.py @@ -13,8 +13,8 @@ # limitations under the License. description = dict( - default='docs', - short_flag='-z', - space='Docs Space', - description='Generated documentation files are placed in this location.' + default="docs", + short_flag="-z", + space="Docs Space", + description="Generated documentation files are placed in this location.", ) diff --git a/catkin_tools_document/util.py b/catkin_tools_document/util.py index 7d4a1b7..55060d3 100644 --- a/catkin_tools_document/util.py +++ b/catkin_tools_document/util.py @@ -58,17 +58,19 @@ def unset_env(logger, event_queue, job_env: dict, keys: Union[List[str], None] = except KeyError: logger.err("Could not delete missing key '{}' from the job environment".format(key)) finally: - event_queue.put(ExecutionEvent( - 'STAGE_PROGRESS', - job_id=logger.job_id, - stage_label=logger.stage_label, - percent=str(index/float(len(keys))) - )) + event_queue.put( + ExecutionEvent( + "STAGE_PROGRESS", + job_id=logger.job_id, + stage_label=logger.stage_label, + percent=str(index / float(len(keys))), + ) + ) return 0 -def write_file(logger, event_queue, contents: Any, dest_path: str, mode: str = 'w') -> int: +def write_file(logger, event_queue, contents: Any, dest_path: str, mode: str = "w") -> int: """ FunctionStage functor that writes the contents to a file. In case the file exists, the file is overwritten. @@ -100,7 +102,7 @@ def yaml_dump_file(logger, event_queue, contents: Any, dest_path: str, dumper=ya :return: return code """ mkdir_p(os.path.dirname(dest_path)) - with open(dest_path, 'w') as f: + with open(dest_path, "w") as f: yaml.dump(contents, f, dumper) return 0 diff --git a/setup.py b/setup.py index 2410e55..aa5b81a 100644 --- a/setup.py +++ b/setup.py @@ -2,40 +2,40 @@ from setuptools import setup setup( - name='catkin_tools_document', + name="catkin_tools_document", packages=find_packages(), - package_data={'catkin_tools_document': ['catkin_tools_document/external/*']}, + package_data={"catkin_tools_document": ["catkin_tools_document/external/*"]}, include_package_data=True, - version='0.5.2', - author='Mike Purvis', - author_email='mike@uwmike.com', - maintainer='Mike Purvis', - maintainer_email='mike@uwmike.com', - url='https://github.com/mikepurvis/catkin_tools_document', - keywords=['catkin'], + version="0.5.2", + author="Mike Purvis", + author_email="mike@uwmike.com", + maintainer="Mike Purvis", + maintainer_email="mike@uwmike.com", + url="https://github.com/mikepurvis/catkin_tools_document", + keywords=["catkin"], classifiers=[ - 'Environment :: Console', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: Apache Software License', - 'Programming Language :: Python', + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", ], description="Plugin for catkin_tools to enable building workspace documentation.", - license='Apache 2.0', + license="Apache 2.0", entry_points={ - 'catkin_tools.commands.catkin.verbs': [ - 'document = catkin_tools_document:description', + "catkin_tools.commands.catkin.verbs": [ + "document = catkin_tools_document:description", ], - 'catkin_tools.spaces': [ - 'docs = catkin_tools_document.spaces.docs:description', + "catkin_tools.spaces": [ + "docs = catkin_tools_document.spaces.docs:description", ], }, python_version=">=3.8", install_requires=[ - 'catkin_pkg', - 'catkin_tools>=0.8.3', - 'catkin_sphinx', - 'pydoctor>=20.12.0', - 'pyyaml', - 'sphinx>=4.3.0' - ] + "catkin_pkg", + "catkin_tools>=0.8.3", + "catkin_sphinx", + "pydoctor>=20.12.0", + "pyyaml", + "sphinx>=4.3.0", + ], )