diff --git a/docs/source/conf.py b/docs/source/conf.py index 63ea4447..01ae984b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -86,9 +86,15 @@ def linkcode_resolve(domain, info): pygements_dark_style = "monokai" # -- sphinx-click ------------------------------------------------------------ +# These functions let us write descriptions/docstrings in a way that doesn't look +# weird in the Click CLI, but get additional formatting in the sphinx-click autodocs for +# better readability. from typing import List import re +from click.core import Context +from sphinx.application import Sphinx + CMD_PATTERN = r"--[^ ]+" STR_PATTERN = r"\"[^ ]+\"" SNAKE_PATTERN = r"[A-Z]+_[A-Z_]*[A-Z]" @@ -106,13 +112,14 @@ def _add_formatting_to_string(line: str) -> str: return line -def process_description(app, ctx, lines: List[str]): - """Add custom formatting to sphinx-click autodocs. This lets us write Click - docstrings in ways that look presentable in the CLI, but adds extra formatting when - generating Sphinx docs. +def process_description(app: Sphinx, ctx: Context, lines: List[str]): + """Add custom formatting to sphinx-click autodoc descriptions. * add fixed-width (code) font to certain words * add code block formatting to example shell commands + + Because we have to modify the lines list in place, we have to make multiple passes + through it to format everything correctly. """ # chop off params param_boundary = None @@ -147,5 +154,13 @@ def process_description(app, ctx, lines: List[str]): lines.insert(i, ".. code-block:: console") +def process_option(app: Sphinx, ctx: Context, lines: List[str]): + """Add fixed-width formatting to strings in sphinx-click autodoc options.""" + for i, line in enumerate(lines): + if re.findall(STR_PATTERN, line): + lines[i] = re.sub(STR_PATTERN, lambda x: f"``{x.group()}``", line) + + def setup(app): app.connect("sphinx-click-process-description", process_description) + app.connect("sphinx-click-process-options", process_option) diff --git a/src/gene/cli.py b/src/gene/cli.py index 102d0213..e8606413 100644 --- a/src/gene/cli.py +++ b/src/gene/cli.py @@ -15,6 +15,9 @@ logger.setLevel(logging.DEBUG) +url_description = 'URL endpoint for the application database. Can either be a URL to a local DynamoDB server (e.g. "http://localhost:8001") or a libpq-compliant PostgreSQL connection description (e.g. "postgresql://postgres:password@localhost:5432/gene_normalizer").' + + @click.group() def cli() -> None: """Manage Gene Normalizer data.""" @@ -24,7 +27,7 @@ def cli() -> None: @click.argument("sources", nargs=-1) @click.option("--all", is_flag=True, help="Update records for all sources.") @click.option("--normalize", is_flag=True, help="Update normalized concepts.") -@click.option("--db_url", help="URL endpoint for the application database.") +@click.option("--db_url", help=url_description) @click.option("--aws_instance", is_flag=True, help="Use cloud DynamodDB instance.") @click.option( "--use_existing", @@ -109,7 +112,7 @@ def update( @cli.command() @click.option("--data_url", help="URL to data dump") -@click.option("--db_url", help="URL endpoint for the application database.") +@click.option("--db_url", help=url_description) def update_from_remote(data_url: Optional[str], db_url: str) -> None: """Update data from remotely-hosted DB dump. By default, fetches from latest available dump on VICC S3 bucket; specific URLs can be provided instead by @@ -137,7 +140,7 @@ def update_from_remote(data_url: Optional[str], db_url: str) -> None: @cli.command() -@click.option("--db_url", help="URL endpoint for the application database.") +@click.option("--db_url", help=url_description) @click.option("--verbose", "-v", is_flag=True, help="Print result to console if set.") def check_db(db_url: str, verbose: bool = False) -> None: """Perform basic checks on DB health and population. Exits with status code 1 @@ -181,7 +184,7 @@ def check_db(db_url: str, verbose: bool = False) -> None: help="Output location to write to", type=click.Path(exists=True, path_type=Path), ) -@click.option("--db_url", help="URL endpoint for the application database.") +@click.option("--db_url", help=url_description) def dump_database(output_directory: Path, db_url: str) -> None: """Dump data from database into file.